2010-07-14 107 views
2

長時間閱讀器,第一次海報;-)而不是觸發器更新主鍵

我正在實現一個基於舊系統的系統。新系統使用SQL Server 2008,當嘗試在主表中插入新項目時出現問題。這將以兩種方式發生:它可以從現有系統導入(1)或可以在新系統(2)中創建。

如果(1)該項目已經有我想保留的ID(int)。如果(2)ID不填寫,我想生成一個ID,它是表中最大當前值的+1。這當然也適用於多行插入。

據我所見,解決方案將創建一個INSTEAD OF TRIGGER,但我無法弄清楚這是如何完成的。任何人都可以給我一個提示或者指導我如何做到這一點?

克里斯

回答

1

按照您的請求使用INSTEAD觸發這個SQL代碼可以讓你開始。

CREATE TABLE dbo.SampleTable 
(
    ID INT, 
    SomeOtherValue VARCHAR(100) NULL 
) 
GO 

CREATE TRIGGER dbo.TR_SampleTable_Insert 
    ON dbo.SampleTable 
    INSTEAD OF INSERT 
AS 
BEGIN 

    SET NOCOUNT ON; 

    -- Inserting rows with IDs 
    INSERT INTO dbo.SampleTable (
     ID, 
     SomeOtherValue) 
    SELECT 
     ID, 
     SomeOtherValue 
    FROM 
     Inserted  
    WHERE 
     ID IS NOT NULL 

    -- Now inserting rows without IDs 
    INSERT INTO dbo.SampleTable (
     ID, 
     SomeOtherValue) 
    SELECT 
     (SELECT ISNULL(MAX(ID), 0) FROM dbo.SampleTable) 
      + ROW_NUMBER() OVER(ORDER BY ID DESC), 
     SomeOtherValue 
    FROM 
     Inserted 
    WHERE 
     ID IS NULL 

END 
GO 

INSERT INTO dbo.SampleTable 
SELECT 1, 'First record with id' 
UNION 
SELECT NULL, 'First record without id' 
UNION 
SELECT 2, 'Second record with id' 
UNION 
SELECT NULL, 'Second record without id' 
GO 

SELECT * FROM dbo.SampleTable 
GO 
+0

我完全同意以前的意見,不推薦將舊ID與新ID混合。 – JCallico 2010-07-14 16:14:26

+0

謝謝 - 只是我正在尋找的那種例子:-) 關於ID的混合,我看到了不足之處 - 但是這個項目也給這個方法帶來了一些缺點,與這個技術問題無關。 – 2010-07-15 07:26:01

+0

很高興我能夠幫助。這就是爲什麼我實現了你原來所要求的,而不是立即建議一種替代方法,只是爲了跳躍才能獲得積分。這些日子似乎是StackOverflow的趨勢。 – JCallico 2010-07-15 17:10:53

1

如何使用存儲過程做你插入,與主鍵作爲可選的參數。在存儲過程中,您可以在主鍵未通過時進行設置。

我會提醒的是,如果新舊記錄插入混合匹配,您的方案可能會失敗,因爲新記錄會在插入舊記錄之前變舊。我建議立即獲取舊錶的最大ID,並在存儲過程中將新主鍵設置爲(舊max + 1,當前表最大值)的較大值

+0

我認爲這是一種可能性,但我發現觸發器解決方案是一個更乾淨的解決方案,如果有可能實現的話。如果不是的話,我一定會選擇存儲過程解決方案。 關於ID崩潰 - 我知道這個問題,並且我將生成足夠大的新ID以防止崩潰(爲了簡單起見,我只是將這部分留下了)。或者,至少不會再過75年 - 這應該足以滿足明年某個時間廢棄堆的系統的需要;-) – 2010-07-14 14:20:10

+0

我想也許我誤解了你對新老ID的評論。而且我認爲我沒有足夠好地描述這種情況。舊系統將繼續生成新項目,因此即使在新系統投入生產後,舊系統的ID也會繼續增加。直到所有功能都移植完畢,舊系統纔會被廢棄。 – 2010-07-14 14:37:13

+0

@Chris - 對,我剛纔問你爲什麼你不能導入所有的舊記錄,並做了它,但這解釋了它。 – 2010-07-14 14:40:44

0

其他人已經告訴你如何寫這種觸發器。

另一種經常推薦的方法是將兩個ID都存儲在新數據庫中。每個記錄在新系統中獲得新的ID(通過IDENTITY列或其他方式)。此外,如果記錄是從另一個系統導入的,則它具有關聯的OriginSystem和OriginID。這樣您可以保留舊ID以供參考。這種方法的另一個好處是能夠支持新的系統從數據庫導入數據。當合並或交換數據與另一個系統。

+0

這就是我會如果提出相同的問題。 – JCallico 2010-07-14 16:57:40

+0

感謝您的評論。該解決方案已經考慮。由於這裏沒有描述項目的細節,這會使數據模型更加複雜(舊系統有其他後備系統也需要處理)。這個問題的最終解決方案尚未決定 - 但很高興知道觸發解決方案似乎是一種可能性。 – 2010-07-15 07:31:48