ca9*_*3d9 11 sql-server sql-server-2008
我在存储过程中有以下代码.
....
select ... into #temp from ....
alter table #temp add constraint PK_mytemp13 primary key (....)
....
Run Code Online (Sandbox Code Playgroud)
如果存储过程并行运行,我将不时收到以下错误消息.
数据库中已经有一个名为"PK_perf322dsf"的对象.无法创建约束.查看以前的错误.
我认为可以通过以下方法避免这种情况.还有其他更优雅的解决方案吗?
首先使用主键创建临时表.然后插入行.
create table #temp (... primary key (....))
动态创建具有会话ID的PK.
declare @s varchar(500) = 'alter table #temp add constraint PK_temp' + @@spid + ' primary key (....)
gbn*_*gbn 12
只有在相同的客户端连接实例化(等于SQL Server中的一个SPID或连接)被重用于2个不同的调用时,才会发生这种情况.两个并行调用应具有不同的连接实例和单独的SPID
SPID与本地(单个#temp表)完全隔离
编辑:
忽略上面
我以前从未在临时表上命名约束.我根据需要使用索引,或者只在列之后添加PRIMARY KEY.约束名称在sys.objects中是数据库唯一的
PK基本上是一个非唯一的聚簇索引.因此,请使用sys.indexes中的每个表的CREATE UNIQUE CLUSTERED INDEX索引名称是唯一的.
在2个SSMS查询窗口中运行时,此操作失败
CREATE TABLE #gbn (foo int NOT NULL);
ALTER TABLE #gbn ADD CONSTRAINT PK_gbn PRIMARY KEY (foo);
Run Code Online (Sandbox Code Playgroud)
消息2714,级别16,状态5,行2
数据库中已存在名为"PK_gbn"的对象.
消息1750,级别16,状态0,行2
无法创建约束.查看以前的错误.
奇怪的是,错误和约束名称匹配不同于您的错误
这有效
CREATE TABLE #gbn (foo int NOT NULL);
CREATE UNIQUE CLUSTERED INDEX PK_gbn ON #gbn (foo);
Run Code Online (Sandbox Code Playgroud)
CDC*_*CDC 10
我试图记住如何执行此操作,但您可以在临时表上创建无名主键并避免此错误.这与放置列级PK不同,因为它支持多于1列.这是一个例子:
CREATE TABLE #test
(
AccountNumber INT NOT NULL,
TransactionNumber INT NOT NULL,
PRIMARY KEY CLUSTERED (tranid, sys_process_dt)
);
Run Code Online (Sandbox Code Playgroud)
这允许最终目标加上防止名称重复.查询将显示SQL Server将在sys.sysobjects中为您的PK名称添加GUID:
SELECT *
FROM tempdb.sys.sysobjects
WHERE name LIKE '%#test%'
Run Code Online (Sandbox Code Playgroud)
名字| 的xtype
--------------------------------
#test ___..._ 000000000407 | ü
PK __#test_____B88A05A770B3A6A6 | PK
你可以吃蛋糕,也可以吃.
如果是第二个 - 您只需执行以下操作 - ALTER TABLE #temp ADD PRIMARY KEY(...)
如果是第一个 - 您必须先使用键创建表(常规或全局临时),然后才能在并行操作中使用它