2012-01-16 79 views
10

我在存儲過程中有以下代碼。腳本並行運行時爲#temp表創建PK失敗

.... 
select ... into #temp from .... 
alter table #temp add constraint PK_mytemp13 primary key (....) 
.... 

如果存儲過程並行運行,我將不時收到以下錯誤消息。

數據庫中已經有一個名爲'PK_perf322dsf'的對象。 無法創建約束。查看以前的錯誤。

我認爲這可以通過以下方法避免。還有其他更優雅的解決方案嗎?

  1. 首先用主鍵創建臨時表。然後插入行。
    create table #temp (... primary key (....))

  2. 動態地使用會話ID動態創建PK。
    declare @s varchar(500) = 'alter table #temp add constraint PK_temp' + @@spid + ' primary key (....)

回答

3
  1. 您嘗試從不同連接(這是不可能的,而不是全局臨時表),
  2. 插入到相同臨時表或嘗試插入不同的表。

如果第二個 - 您只需可能會做如下 - ALTER TABLE #TEMP ADD PRIMARY KEY(...)

如果1 - 你必須創建表事先鍵(常規或全局臨時)在並行操作中使用它

+2

這個錯誤與創建本地臨時表有關,在一段代碼中創建一個已命名的主鍵,並有多個連接調用該代碼塊。 SQL Server不允許具有相同名稱的2個PK,即使在本地臨時表中也是如此。 – CDC 2015-07-02 19:20:36

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); 

消息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); 
+0

@MartinSmith:從錯誤中,約束名稱被忽略。 IIRC,當我在臨時表上創建索引(而不是PK)時,會添加很多下劃線和一些十六進制。我從來沒有一個併發問題。我建議錯誤不在臨時表處理 – gbn 2012-01-16 09:43:29

+0

命名約束仍然必須在'tempdb'中唯一命名,因爲它們在'sys.objects'中是唯一的。命名索引不一定非要。實際上,OP應該只使用一個唯一的索引或一個無名的約束。 (編輯:看看你的意思是關於錯誤消息,雖然...) – 2012-01-16 09:44:31

+0

@MartinSmith:剛剛驗證過它。查看更新。我從來沒有想過在臨時表上使用命名約束。儘管如此,總是在持久表上做 – gbn 2012-01-16 09:51:04

8

我試圖記住如何做到這一點,但你可以創建一個無名的主鍵在臨時表上並避免此錯誤。這與放置列級PK不同,因爲它支持多於1列。這裏是一個例子:

CREATE TABLE #test 
(
    AccountNumber INT NOT NULL, 
    TransactionNumber INT NOT NULL, 
    PRIMARY KEY CLUSTERED (tranid, sys_process_dt) 
); 

這允許最終目標加上防止名稱重複。查詢將顯示SQL Server將在sys.sysobjects中爲您輸入一個GUID名稱:

SELECT * 
FROM tempdb.sys.sysobjects 
WHERE name LIKE '%#test%' 

name |的xtype

--------------------------------

#TEST ___..._ 000000000407 | U

PK __#test_____B88A05A770B3A6A6 | PK

你可以吃你的蛋糕,也可以吃它。

相關問題