我有一个带有SQL插入SQL Server 2005数据库的.net事务。该表具有一个身份主键。
当事务内发生错误时,将Rollback()
被调用。行插入将正确回滚,但是,下次我将数据插入表时,身份将增加,就好像从未发生过回滚一样。因此,本质上在同一性序列中存在缺口。有什么方法可以使该Rollback()
方法回收丢失的身份?
我不是用正确的方法吗?
我有一个带有SQL插入SQL Server 2005数据库的.net事务。该表具有一个身份主键。
当事务内发生错误时,将Rollback()
被调用。行插入将正确回滚,但是,下次我将数据插入表时,身份将增加,就好像从未发生过回滚一样。因此,本质上在同一性序列中存在缺口。有什么方法可以使该Rollback()
方法回收丢失的身份?
我不是用正确的方法吗?
Answers:
如果您考虑一下,则自动递增号不应是事务性的。如果其他事务必须等待以查看是否要使用或“回滚”自动编号,则使用该自动编号的现有事务将阻止它们。例如,考虑下面我的表A的伪代码,对ID列使用一个自动编号字段:
User 1
------------
begin transaction
insert into A ...
insert into B ...
update C ...
insert into D ...
commit
User 2
-----------
begin transaction
insert into A ...
insert into B ...
commit
如果用户2的事务在用户1的事务之后一毫秒开始,那么他们向表A的插入将不得不等待用户1的整个事务完成,以查看是否使用了从第一次插入A的自动编号。
这是一个功能,而不是错误。如果您需要自动编号,我建议使用另一种方案来生成自动编号。
其他所有不担心的海报发布者,应该避免差距,这都是对的。如果数字具有商业意义,并且该意义不存在空白,则不要使用标识列。
仅供参考,如果出于某种原因您想消除差距,大多数数据库都可以将自动编号重新设置为您选择的编号。这很麻烦,如果您发现自己需要定期进行此操作,则绝对不应该使用自动编号/身份字段,如上所述。但是以下是在SQL Server中执行此操作的代码:
DBCC CHECKIDENT('产品',RESEED,0)
这会将product表设置为从1开始(尽管如果表中有记录,显然它会跳过已获取的ID值。)其他RDBMS供应商也有自己的语法,但是效果大致相同,因此,请在系统帮助文件或互联网中查找“种子身份”或“种子自动编号”。
再次:这是在特殊场合,而不是经常使用。不要将其放在存储过程中,不要让我们所有人都来。
Muhan试图在执行此事务的多个同时连接而不是一次执行的情况下考虑它。有些会失败,有些会成功。您希望SQL Server专注于在新请求进入时运行它们,而不是维护无间隙的身份列。IMO它(价值差距)绝对不值得花时间。