为什么IDENTITY_INSERT ON一次只能在一个表上使用?


20

在这种情况下,一次只能在一个数据库表中将IDENTITY_INSERT设置为ON,但是为什么呢?由于IDENTITY列不是全局唯一的,所以我无法想到可能由于将标识同时插入一个以上的表而引起的任何危险情况(至少没有比使用IDENTITY INSERT进行伪造更危险)。

很少使用IDENTITY INSERT,但是硬限制的原因是什么?


1
也许有威慑力,所以很少使用?
Remus Rusanu'2

@RemusRusanu就是我在想的那种,或者是要确保您不会意外地将II留在多个表上。
Ben Brocka'2

@Ben为什么不小心将其留在多张桌子上而不是意外将其留在一张桌子上呢?两者都可能导致相同的问题。我真的对您的问题很好奇,我不认为威慑是答案,否则我们在引擎方面会有更多限制。但是我确实同意,如果您觉得需要经常这样做,那么可能会有些怀疑。
亚伦·伯特兰

@AaronBertrand并非如此,正如我在问中所暗示的那样。由于SQL Server允许许多其他不良做法,例如使用保留关键字命名列(有时甚至不使用[]!)
Ben Brocka

@Ben正确,不一定适合您,但适合遇到此问题的任何读者。
亚伦·伯特兰

Answers:


12

我认为这很困难。如果您可以一直将其保留,为什么还要拥有一个身份字段呢?

但是实际上有两个限制:

  • 它仅在该连接上持续存在
  • 每个连接只能在一张桌子上设置

基于与连接有关的限制,我认为主要是因为它永远不会被意外打开。

想象一下,如果有人在您的一个表上打开了ID插入,那么您没有意识到,执行了(通常)无效的插入,破坏了ID字段的完整性吗?

如果没有约束或唯一索引,请记住ID字段可以有重复值...


1
+1我认为您关于重复的最后一点被很多人遗漏了。人们认为,如果设置了IDENTITY它,也将成为唯一的约束。当然,如果他们愿意尝试的话,很容易反驳。
亚伦·伯特兰

@AaronBertrand但是,再次使用IDENTITY INSERT的任何表上的ID重复风险完全相同,为什么要设置硬限制?我认为它仅在连接中持续存在这一事实作为预防措施更为有意义。
Ben Brocka'2

我并不是说重复ID问题是硬限制的原因。
亚伦·伯特兰

6

我的猜测是由于实施的限制。在多个表上允许此设置可能会导致性能下降:

由于这是一个会话参数,因此允许在单个表上激活该设置意味着它是简单的标志,并且表的对象ID存储在服务器端的会话中。也许这只是一个整数:如果没有IDENTITY_INSERT处于活动状态,则为0,并且对该表进行了一些databaseid + objectid编码。

允许在一个会话中的多个表上设置该参数将意味着服务器将存储此类对象的动态列表,并针对每个insert语句对其进行检查。假设一个会话激活了1000个表的参数:

  1. 这意味着服务器已在会话变量中分配了1000个项目
  2. 这也意味着服务器必须为此会话中的每个插入语句检查1000个项目的列表。

我也怀疑将identity_insert设置为on会对服务器的性能产生很大的影响。在sybase中,有一个“ 身份刻录设置因子 ”,它允许保存表的身份计数器的值,该值仅在一段时间内保存一次(该值保留在内存中,并偶尔在服务器上写入磁盘中)关掉 )。SQL Server基于相同的代码,因此可能具有一些可比的优化,但是在表上激活identity_insert可能会限制服务器为每个插入保存标识值,因为否则无法保证最大的间隙大小。因此,如果一个会话对一个表中的插入产生性能影响,这可能是可以接受的,但是如果它可以对服务器上所有auto_increment表的性能造成影响,则不可接受。


+1可能是一些事实。我不买差距大小的论点,因为一次INSERT只能一次进行一次会话,而且我很容易插入一千万个硬编码IDENTITY值。
亚伦·伯特兰

间隙大小与发生崩溃时发生的情况有关:在sybase上,如果服务器崩溃,则丢失了最后一个身份(它在内存中),因此它重新开始留下了一个间隙(请参阅身份刻录设置因子)
Olivier S

因此,在SQL Server中,您是否建议如果在插入带有身份列的1,000,000行时引擎崩溃,或者在SET IDENTITY_INSERT启用时用1,000,000硬编码值覆盖身份列而导致引擎崩溃,会发生什么不同的事情?我只是建议间隙大小不会影响多个表,而只会影响单个表。
亚伦·伯特兰

我的猜测-我对此完全没有证据-是表上的SET IDENTITY_INSERT会在每次插入时强制自动增量写入磁盘。理由是,由于您插入的值可以是任何值,因此服务器无法考虑“好,如果我每1000行只写一次磁盘,万一发生崩溃,我可以安全地将1000添加到我保存的最后一个值中”
Olivier S
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.