SQL Server不同会话下临时表主键冲突:如何隔离键作用域
解决临时表主键约束名跨会话冲突的问题
这个问题我之前也碰到过,核心原因其实不是临时表的作用域问题——本地临时表(#开头)本身就是会话隔离的,每个会话的#tmpTable都是独立的实例。问题出在你显式指定的主键约束名PK_NamePK是数据库全局唯一的,当第二个会话执行同样的创建语句时,数据库里已经存在同名的约束(来自第一个会话),所以就会报错:
'PK_NamePK already exists'
下面是两种可行的解决方法:
方法1:让SQL Server自动生成唯一约束名(推荐)
最简单的方式就是去掉显式的约束名,让SQL Server自动为每个会话的临时表主键生成唯一的名字。修改后的代码如下:
CREATE TABLE #tmpTable ( [RowId] [bigint] IDENTITY(1,1) NOT NULL, [Id] [numeric](10, 0) NOT NULL ) ALTER TABLE #tmpTable ADD PRIMARY KEY CLUSTERED (RowId);
SQL Server会自动生成类似PK__#tmpTabl__12345678这样的唯一约束名,每个会话的约束名不会重复,自然就不会冲突了。
方法2:手动生成会话唯一的约束名(如果需要自定义命名)
如果你一定要给约束指定有意义的名字,可以结合会话ID(@@SPID,每个会话的ID是唯一的)来拼接约束名,确保每个会话的约束名不重复。需要用动态SQL来实现:
CREATE TABLE #tmpTable ( [RowId] [bigint] IDENTITY(1,1) NOT NULL, [Id] [numeric](10, 0) NOT NULL ) DECLARE @ConstraintName NVARCHAR(100) = 'PK_NamePK_' + CAST(@@SPID AS NVARCHAR(10)); DECLARE @SQL NVARCHAR(MAX) = N'ALTER TABLE #tmpTable ADD CONSTRAINT ' + QUOTENAME(@ConstraintName) + ' PRIMARY KEY CLUSTERED (RowId);'; EXEC sp_executesql @SQL;
这样每个会话的约束名会带上自己的会话ID,比如PK_NamePK_54、PK_NamePK_67,完全不会重复。
内容的提问来源于stack exchange,提问作者EvgenOrel
相关产品推荐
相关产品推荐

