sql server 2008主键冲突错误

本文关键字:冲突 错误 server 2008 sql | 更新日期: 2023-09-27 18:05:43

我在c#中创建了两个线程,并且并行调用两个独立的函数。两个函数都从XYZ表中读取最后一个ID,并插入值为ID+1的新记录。这里ID列是主键。当我执行这两个函数时,我得到主键冲突错误。这两个函数都有以下查询:

insert into XYZ values((SELECT max(ID)+1 from XYZ),'Name') 

似乎两个函数都在一次读取值并试图用相同的值插入。我怎样才能解决这个问题?div ?

让数据库处理为您选择ID。从上面的代码中可以明显看出,您真正想要的是一个自动递增的整数ID列,数据库绝对可以为您处理这个问题。因此,正确设置您的表,而不是当前的插入语句,这样做:

insert into XYZ values('Name') 

如果你的数据库表已经建立,我相信你可以发出类似的语句:

alter table your_table modify column you_table_id int(size) auto_increment

最后,如果由于某种原因(包括您在评论部分指出的无法编辑表模式),这些解决方案都不合适,那么您可以按照其他用户在评论中建议的那样,创建一个同步方法来查找下一个ID。基本上,您只需创建一个返回int的静态方法,在该静态方法中发出select id语句,并使用返回的结果将下一条记录插入到表中。由于此方法不能保证插入成功(由于外部应用程序也可以插入到同一表中),因此您还必须捕获异常并在失败时重试)。

sql server 2008主键冲突错误

设置ID列为"Identity"列。然后,您可以以如下方式执行查询:

insert into XYZ values('Name') 

我认为你不能用ALTER TABLE在列创建后将列更改为Identity。使用management Studio将此列设置为Identity。如果您的表有很多行,这可能是一个长时间运行的过程,因为它实际上会将您的数据复制到一个新表中(将执行表重新创建)。

很可能在您的管理工作室中禁用了该选项。为了启用它,打开工具->选项->设计器并取消选中"防止保存需要重新创建表的更改"选项…根据您的表大小,您可能还需要设置超时。在此期间,您的表将被锁定

此类问题的解决方案是使用某种序列生成ID。

例如,在SQL Server中,您可以使用以下命令创建一个序列:

CREATE SEQUENCE Test.CountBy1
    START WITH 1
    INCREMENT BY 1 ;
GO

然后在c#中,你可以从Test中检索下一个值,并在插入之前将其分配给ID。

听起来您需要更高的事务隔离级别或更严格的锁定。

我不经常使用这些功能,所以如果我错了,希望有人能建议编辑,但你想要其中一个:

-- specify the strictest isolation level
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
insert into XYZ values((SELECT max(ID)+1 from XYZ),'Name') 

-- make locks exclusive so other transactions cannot access the same rows
insert into XYZ values((SELECT max(ID)+1 from XYZ WITH (XLOCK)),'Name')