2011-10-13 117 views
2

兩個步驟插入比方說,我有一個表定義如下:避免在SQL

CREATE TABLE SomeTable 
(
P_Id int PRIMARY KEY IDENTITY, 
CompoundKey varchar(255) NOT NULL, 
) 

CompoundKey與主鍵的字符串的p_id級聯到最後,就像Foo00000001它來源於「富」 + 00000001.目前,插入到這個表中的條目分兩步進行。

  1. 插入帶有CompoundKey的佔位符字符串的虛擬記錄。
  2. 用包含生成的複合鍵的列更新CompoundKey。

我正在尋找一種方法來完全避免第二次更新,並使用一個插入語句來完成所有操作。這可能嗎?我正在使用MS SQL Server 2005.

p.s.我同意這不是世界上最明智的模式,並且這個模式將被重構(並正確地標準化),但我現在無法對模式進行更改。

+0

你爲什麼要申請一個密鑰?這可以在需要時隨時生成。 – JeffO

+0

我個人不會。這是我繼承的數據庫模式,因此我需要分階段改進它,而不會破壞太多的現有代碼。 – CadentOrange

回答

5

你可以使用計算列;更改架構爲:

CREATE TABLE SomeTable 
(
P_Id int PRIMARY KEY IDENTITY, 
CompoundKeyPrefix varchar(255) NOT NULL, 
CompoundKey AS CompoundKeyPrefix + CAST(P_Id AS VARCHAR(10)) 
) 

這樣,SQL Server會自動地給你一個新列的複合鍵,即可自動保持它。您可能還需要查看計算列的PERSIST關鍵字,這會導致SQL Server實現數據文件中的值,而不必實時計算它。如果您願意,也可以在列中添加索引。

+2

+1這可能是最安全的方法,但實際上並沒有消除「UPDATE」,它只是從用戶那裏抽象出來。 – Matthew

+0

這看起來像是最好的答案。我明天在工作時會嘗試更改架構。更改架構是否會保留表中的現有數據? – CadentOrange

+0

只需使用ALTER TABLE代替:'ALTER TABLE SomeTable ADD RealCompoundKey AS .....',您的數據將保持不變。 –

1

一個trigger很容易做到這一點

+0

觸發器**不會消除'INSERT'和'UPDATE'用戶實際上並不真正執行'UPDATE' – Matthew

+0

+1 @Matthew PK在插入觸發器中,您可以更改記錄被插入。你不需要做更新,它會更快,更有效。更不用說,隱藏在所有需要插入記錄的進程中。 – GolezTrol

+0

@GolezTrol雖然它是通過觸發器發生的,並且對你來說是透明的,但是發生了'UPDATE'事務。 – Matthew

1

這根本不可能。
「下一個ID」不存在存在因此無法讀取以履行UPDATE,直到插入該行。

現在,如果您從其他地方購買自動編號,但我認爲這不是您的問題的好答案。

即使您要使用觸發器,仍會執行UPDATE,即使未手動執行它。 可以的CompoundKey晦澀的人口,但在這一天結束,它仍然將是一個UPDATE

我覺得你最安全的賭注只是爲了確保UPDATE是在相同的事務INSERT或使用觸發器。但是,對於它的學術論證,UPDATE仍然存在。

+0

這是不可能的。這就是爲什麼它應該首先被避免。 – JeffO

+0

@JeffO我不聽你的評論......你是同意我還是反駁我說的話? – Matthew

1

兩件事情:

1)如果你最終使用兩個插入,則必須使用交易!否則其他進程可能會看到數據庫處於不一致的狀態(即查看沒有CompoundKey的記錄)。

2)我不會試圖將Id粘貼到事務處理中的CompoundKey的末尾,觸發器等等。如果你需要它,它在輸出處做得更乾淨。在查詢中(select concat(CompoundKey, Id) as CompoundKeyId ...)。如果您需要它作爲其他表中的外鍵,只需使用該對(CompoundKey,Id)即可。

+0

別擔心,它們已經在交易中。這是我繼承代碼時所做的更改之一。當我有機會改變架構時,你的第二個選擇就是我如何做到這一點,但我還沒有做到。 – CadentOrange

+0

是@Philip,我知道 - 維護其他人的舊代碼有時會很棘手。 – TMS