@GMB 在他的回答中写道“SQL Server 没有内置选项(我知道)可以忽略此类错误”。
正如@a_horse_with_no_name 在评论中指出的那样,这里有一个相关的索引的IGNORE_DUP_KEY 选项。
你说:
我希望约束防止第二个相同的 ActorId 没有
抱怨[g]。 IOW,绕过它,不要告诉我,
不要停止应用程序或抛出异常。
可以通过这个选项实现。
首先,我应该指出,当您创建唯一约束时
CONSTRAINT [CK_ACTORS_Column] UNIQUE NONCLUSTERED ([ActorId] ASC)
引擎将创建一个唯一索引来强制执行约束。约束是逻辑概念,索引是概念的物理实现。
你可以通过只创建一个索引,一个唯一索引来达到同样的效果。创建索引时,您可以指定各种选项,包括 IGNORE_DUP_KEY 选项。
IGNORE_DUP_KEY = { 开 |关闭}
指定错误响应时
插入操作尝试将重复的键值插入到唯一的
指数。 IGNORE_DUP_KEY 选项仅适用于插入操作
在创建或重建索引之后。该选项在以下情况下无效
执行 CREATE INDEX、ALTER INDEX 或 UPDATE。默认为关闭。
ON 插入重复键值时会出现警告消息
成唯一索引。只有违反唯一性约束的行
会失败。
OFF 插入重复键值时会出现错误消息
成唯一索引。整个 INSERT 操作将被回滚。
默认情况下,此选项为OFF,因此尝试插入重复键值将失败并出现错误。服务器将回滚 INSERT 操作并将此错误消息发送到您的应用程序,这将取决于您的应用程序如何处理它。如果您的应用程序不期望它,它可能会抛出一些异常。
如果您将此选项设置为ON,您的应用程序将不再收到错误消息。它将收到一条警告消息,大多数应用程序通常会忽略该消息。因此,看起来服务器会默默地忽略重复值并仅插入那些不重复的值。
默默地忽略问题很少是一种理想的行为,但如果你真的知道自己在做什么,你就可以做到。
这是一个简短的演示。
让我们从你的桌子开始
CREATE TABLE [dbo].[ACTORS]
(
[Id] INT IDENTITY (1, 1) NOT NULL,
[ActorId] CHAR(9) NOT NULL,
[Actor] VARCHAR(50) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
);
选项 1。默认值。 IGNORE_DUP_KEY = OFF
CREATE UNIQUE NONCLUSTERED INDEX [IX_ActorID] ON [dbo].[ACTORS]
(
[ActorId] ASC
) WITH (IGNORE_DUP_KEY = OFF)
桌子是空的。让我们尝试插入一些值。
insert into actors (actorid, actor) values('foo', 'bar');
-- (1 row affected)
让我们尝试插入一个重复的值:
insert into actors (actorid, actor) values('foo', 'baz');
--Msg 2601, Level 14, State 1, Line 4
--Cannot insert duplicate key row in object 'dbo.ACTORS' with unique index 'IX_ActorID'.
--The duplicate key value is (foo ).
--The statement has been terminated.
让我们尝试在一条语句中插入多个重复值:
insert into actors (actorid, actor) values
('foo', 'baz'),
('fo2', 'baz'),
('fo2', 'baz'),
('fo3', 'baz'),
('fo3', 'baz'),
('fo3', 'baz'),
('fo4', 'baz');
--Msg 2601, Level 14, State 1, Line 16
--Cannot insert duplicate key row in object 'dbo.ACTORS' with unique index 'IX_ActorID'.
--The duplicate key value is (foo ).
--The statement has been terminated.
现在让我们看看表格中有什么。
SELECT * FROM Actors;
+----+-----------+-------+
| Id | ActorId | Actor |
+----+-----------+-------+
| 1 | foo | bar |
+----+-----------+-------+
只有第一个INSERT 语句成功并且只插入了一行。
现在,清理一下。
DROP INDEX [IX_ActorID] ON [dbo].[ACTORS];
TRUNCATE TABLE dbo.Actors;
选项 2。IGNORE_DUP_KEY = ON
CREATE UNIQUE NONCLUSTERED INDEX [IX_ActorID] ON [dbo].[ACTORS]
(
[ActorId] ASC
) WITH (IGNORE_DUP_KEY = ON)
桌子是空的。让我们尝试插入一些值。
insert into actors (actorid, actor) values('foo', 'bar');
-- (1 row affected)
让我们尝试插入一个重复的值:
insert into actors (actorid, actor) values('foo', 'baz');
--Duplicate key was ignored.
--(0 rows affected)
如您所见,现在它不是错误消息。这只是一个警告“重复键被忽略。”
让我们尝试在一条语句中插入多个重复值:
insert into actors (actorid, actor) values
('foo', 'baz1'),
('fo2', 'baz2'),
('fo2', 'baz3'),
('fo3', 'baz4'),
('fo3', 'baz5'),
('fo3', 'baz6'),
('fo4', 'baz7');
--Duplicate key was ignored.
--(3 rows affected)
在这里您可以看到在 7 行中只插入了 3 行。
现在让我们看看表格中有什么。
SELECT * FROM Actors;
+----+-----------+-------+
| Id | ActorId | Actor |
+----+-----------+-------+
| 1 | foo | bar |
| 4 | fo2 | baz2 |
| 6 | fo3 | baz4 |
| 9 | fo4 | baz7 |
+----+-----------+-------+
您可以看到最后一个INSERT 语句插入了非重复值。另外,请仔细查看ID 列中的值。 IDENTITY 值有间隙,因为它们是为尝试插入的每一行生成的,并且其中一些行被唯一索引拒绝。
总体而言,此索引选项主要设计用于需要在单个 INSERT 语句中批量插入大量行的情况,但您希望其中 一些 行可能违反唯一性约束。您不希望整个大型 INSERT 语句失败,您只希望忽略少数违规行。如果没有这个选项,您将不得不尝试逐行插入值,这可能比单个 INSERT 语句慢得多。