我在存储过程中有以下代码。
....
select ... into #temp from ....
alter table #temp add constraint PK_mytemp13 primary key (....)
....
如果存储过程并行运行,我将不时收到以下错误消息。
数据库中已有一个名为“PK_perf322dsf”的对象。 无法创建约束。查看以前的错误。
我认为可以通过以下方法避免这种情况。还有其他更优雅的解决方案吗?
首先使用主键创建临时表。然后插入行。
create table #temp (... primary key (....))
动态创建具有会话ID的PK
declare @s varchar(500) = 'alter table #temp add constraint PK_temp' + @@spid + ' primary key (....)
答案 0 :(得分:11)
只有在相同的客户端连接实例化(等于SQL Server中的一个SPID或连接)被重用于2个不同的调用时,才会发生这种情况。两个并行调用应具有不同的连接实例和单独的SPID
SPID与本地(单个#temp表)
完全隔离编辑:
忽略上面的
我以前从未在临时表上命名约束。我根据需要使用索引,或者只在列之后添加PRIMARY KEY。约束名称在sys.objects中是唯一的数据库
PK基本上是一个非唯一的聚簇索引。因此,请使用CREATE UNIQUE CLUSTERED INDEX
,因为索引名称在sys.indexes中是唯一的每个表。
在2个SSMS查询窗口中运行时失败
CREATE TABLE #gbn (foo int NOT NULL);
ALTER TABLE #gbn ADD CONSTRAINT PK_gbn PRIMARY KEY (foo);
Msg 2714,Level 16,State 5,Line 2
数据库中已有一个名为“PK_gbn”的对象 Msg 1750,Level 16,State 0,Line 2
无法创建约束。查看以前的错误。
奇怪的是,错误和约束名称匹配不同于您的错误
这有效
CREATE TABLE #gbn (foo int NOT NULL);
CREATE UNIQUE CLUSTERED INDEX PK_gbn ON #gbn (foo);
答案 1 :(得分:9)
我试图记住如何执行此操作,但您可以在临时表上创建无名主键并避免此错误。这与放置列级PK不同,因为它支持多于1列。这是一个例子:
CREATE TABLE #test
(
AccountNumber INT NOT NULL,
TransactionNumber INT NOT NULL,
PRIMARY KEY CLUSTERED (tranid, sys_process_dt)
);
这允许最终目标加上防止名称重复。查询将显示SQL Server将在sys.sysobjects中为您的PK名称添加GUID:
SELECT *
FROM tempdb.sys.sysobjects
WHERE name LIKE '%#test%'
名称|的xtype
--------------------------------
#test ___..._ 000000000407 | û
PK __#test_____B88A05A770B3A6A6 | PK
你也可以吃蛋糕。
答案 2 :(得分:3)
如果是第二个 - 您只需执行以下操作 - ALTER TABLE #temp ADD PRIMARY KEY(...)
如果是第一个 - 在并行操作中使用它之前必须使用键创建表(常规或全局临时)
答案 3 :(得分:1)
我知道这已经被回答并接受了,但是仍然没有看到正确的答案。
在创建命名约束时,约束的名称必须在表级别精确。它们在数据库级别范围内。因此,要么不要创建named constrained并让sql选择自己的名称,要么如果您提供名称,请确保它在该数据库中唯一。即使对于TEMP DB。
答案 4 :(得分:1)
更重要的是,临时表上的任何命名约束都必须在会话之间唯一地命名。这也意味着默认约束(例如,您将字段的默认值设置为-1),并且默认约束已明确命名,当您尝试在另一个会话窗口中创建临时表时,SQL Server将抛出错误。即使这不是关键限制。
例如,打开两个查询窗口,然后在一个窗口中运行以下代码,然后在另一个窗口中运行(不先关闭任何一个窗口):
DROP TABLE IF EXISTS #TempTbl1;
CREATE TABLE #TempTbl_1 (
[TestCol1] INT
,[TestCol2] BIGINT CONSTRAINT [DF_Tc2] DEFAULT (-1)
);
第一个窗口将正常执行,但第二个窗口将引发错误说明
Msg 2714, Level 16, State 5, Line 2
There is already an object named 'DF_Tc2' in the database.
Msg 1750, Level 16, State 1, Line 2
Could not create constraint or index. See previous errors.
尽管表没有PK或索引,而只是命名的默认约束,但事实如此。