为什么 IDENTITY_INSERT ON 一次只允许在一张表上使用?

Ben*_*cka 20 sql-server

它的情况是IDENTITY_INSERT只能在一个数据库表在时间设置为ON,但为什么呢?由于IDENTITY列不是全局唯一的,我想不出将身份同时插入多个表可能会导致的任何危险情况(至少不会比通常使用 IDENTITY INSERT 捏造更危险)。

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

JNK*_*JNK 12

我认为这是让它变得困难。如果你可以一直保持它,为什么还要有一个身份字段?

但实际上有一些限制:

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

基于与连接相关的限制,我认为这主要是因为它永远不会意外地保持开启状态。

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

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


小智 6

我的猜测是这是由于实施而受到的限制。在多个表上允许此设置可能会影响性能:

由于这是一个会话参数,允许在单个表上激活设置意味着它是简单的标志和表的对象 id 存储在会话服务器端。也许这只是一个整数:0 如果没有 IDENTITY_INSERT 处于活动状态,以及表的 databaseid + objectid 的一些编码。

允许在会话中的多个表上设置参数意味着服务器将存储此类对象的动态列表并检查每个插入语句。想象一个会话激活一千个表的参数:

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

此外,我怀疑将 identity_insert 设置为对服务器的性能有广泛的影响。在sybase中有一个“身份燃烧设置因子”,它允许保存一个表的身份计数器的值,只保存一次(该值保存在内存中,偶尔写入磁盘和服务器关掉 )。SQL Server 基于相同的代码,因此可能有一些类似的优化,但在表上激活 identity_insert 可能会限制服务器为每个插入保存标识值,否则它不能保证最大间隙大小。因此,如果一个会话对一个表中的插入产生性能影响,这可能是可以接受的,但如果它可以在服务器上的所有 auto_increment 表上产生性能影响,那就不行了。