【发布时间】:2011-04-16 21:36:12
【问题描述】:
我正在从多个进程插入 SQL 数据库。进程有时可能会尝试将重复数据插入表中。我尝试以一种可以处理重复项的方式编写查询,但我仍然得到:
System.Data.SqlClient.SqlException: Violation of UNIQUE KEY constraint 'UK1_MyTable'. Cannot insert duplicate key in object 'dbo.MyTable'.
The statement has been terminated.
我的查询类似于:
INSERT INTO MyTable (FieldA, FieldB, FieldC)
SELECT FieldA='AValue', FieldB='BValue', FieldC='CValue'
WHERE (SELECT COUNT(*) FROM MyTable WHERE FieldA='AValue' AND FieldB='BValue' AND FieldC='CValue' ) = 0
约束“UK1_MyConstraint”表示在 MyTable 中,3 个字段的组合应该是唯一的。
我的问题:
- 为什么这不起作用?
- 我需要进行哪些修改才能避免因违反约束而出现异常?
请注意,我知道还有其他方法可以解决“如果不存在则插入”的原始问题,例如(总而言之):
- 使用 TRY CATCH
- IF NOT EXIST INSERT(在具有可序列化隔离的事务内)
我应该使用其中一种方法吗?
编辑 1 用于创建表的 SQL:
CREATE TABLE [dbo].[MyTable](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[FieldA] [bigint] NOT NULL,
[FieldB] [int] NOT NULL,
[FieldC] [char](3) NULL,
[FieldD] [float] NULL,
CONSTRAINT [PK_MyTable] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON),
CONSTRAINT [UK1_MyTable] UNIQUE NONCLUSTERED
(
[FieldA] ASC,
[FieldB] ASC,
[FieldC] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
编辑 2 决定:
只是为了更新这一点 - 我决定使用链接问题 (link) 中建议的“JFDI”实现。虽然我仍然对为什么原始实现不起作用感到好奇。
【问题讨论】:
-
我没有什么有用的补充,但是你现在的声望(1234)和我行李箱的组合一样。
-
我希望您的行李组合在我的声誉发生变化时保持同步。如果我的声誉达到 5 位数,您可能需要获得新锁 :-)
-
我认为@Mike Cheel 拥有它,或者至少已经确定了一种可能导致这种情况的情况。如果 BValue 或 CValue 为空,除非 ANSI_NULLS 为 OFF,否则您的 SELECT COUNT(*) 将返回 0。
-
@pgroke - 您当前的方法中没有任何东西可以防止这些错误。在足够高的负载下,您会看到它们。
标签: sql-server sql-server-2005