SQL插入失败 - 违反主键约束

时间:2014-01-16 17:39:25

标签: sql sql-server tsql

我看到一个SQL Insert语句的一个非常奇怪的问题,我有一个简单的表,ID和2个日期时间,请参阅下面的创建脚本 -

CREATE TABLE [dbo].[DATA_POPULATION_LOGS](
    [ID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
    [START] [datetime] NOT NULL,
    [FINISH] [datetime] NOT NULL,
 CONSTRAINT [PK__DATA_POP__3214EC2705D8E0BE] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

我现在正在尝试运行以下插入脚本 -

INSERT INTO [dbo].[DATA_POPULATION_LOGS]
           ([START]
           ,[FINISH])
     VALUES
           (GETDATE()
           ,GETDATE())

失败并出现以下错误 -

Msg 2627, Level 14, State 1, Line 1
Violation of PRIMARY KEY constraint 'PK__DATA_POP__3214EC2705D8E0BE'. Cannot insert duplicate key in object 'dbo.DATA_POPULATION_LOGS'. The duplicate key value is (11).

每次执行插入时,上面错误消息中的重复键值都会增加,因此它似乎知道它是一个标识列。

导致这个问题的原因是什么?!

提前致谢。 西蒙

修改

我现在已经创建了这个表的副本,并且可以使用该脚本插入到新表中,可能导致它失败的原因是什么?

1 个答案:

答案 0 :(得分:9)

可能有人发表DBCC CHECKIDENT反对该表。执行此操作时,SQL Server将服从您,并尝试从RESEED开始生成值并按增量递增。它不首先检查这些值是否已经存在(即使存在PK)。简单的repro会产生相同的错误:

USE tempdb;
GO
CREATE TABLE dbo.floob(ID INT IDENTITY(1,1) PRIMARY KEY);
GO
INSERT dbo.floob DEFAULT VALUES;
GO
DBCC CHECKIDENT('dbo.floob', RESEED, 0);
GO
INSERT dbo.floob DEFAULT VALUES;
GO
DROP TABLE dbo.floob;

要阻止这种情况发生,您可以找出现在的最大值,然后再次运行CHECKIDENT

DBCC CHECKIDENT('dbo.tablename', RESEED, <max value + 10 or 20 or something here>);