1

我有一張表,我需要將記錄從後面複製到它自己。作爲其中的一部分,我希望使用OUTPUT子句將新行捕獲到表變量中,以便我可以在同一個進程中對行執行其他操作。我希望每行包含其新密鑰以及從複製的密鑰。這裏是一個人爲的例子:在SQL Server 2005中使用OUTPUT INTO複製錶行

INSERT 
    MyTable (myText1, myText2) -- myId is an IDENTITY column 
OUTPUT 
    Inserted.myId, 
    Inserted.myText1, 
    Inserted.myText2 
INTO 
    -- How do I get previousId into this table variable AND the newly inserted ID? 
    @MyTable  
SELECT 
    -- MyTable.myId AS previousId, 
    MyTable.myText1, 
    MyTable.myText2 
FROM 
    MyTable 
WHERE 
    ... 

SQL Server的叫聲,如果列在INSERT數不從SELECT語句中的列數相匹配。因此,如果我向MyTable添加了一列,我可以看到這可能會如何工作,但這不是一個選項。以前,這是通過一個導致性能瓶頸的遊標實現的 - 我故意試圖避免這種情況。

如何複製這些記錄,同時保留複製行的關鍵點以達到最高性能?

+1

正如你所提到的,最簡單的方法是使用額外的列來存放舊的ID。添加列不是一個選項的原因是什麼? – dougajmcdonald 2012-03-05 16:24:23

+0

是的,我認爲你是對的,但專欄之外的這個複製操作是沒有意義的 - 我想我沒有完全反對它,如果沒有別的東西出來。 – 2012-03-05 16:28:41

+0

這不像你說的那樣理想,因爲它不是真正的數據的一部分。我想你可以添加列作爲過程的一部分,然後將其刪除,但似乎有點沉重。我試圖讓它可以爲空,並確保在使用後爲空間節省空列(假設您不需要在過程外保留舊的ID值) – dougajmcdonald 2012-03-05 17:00:02

回答

1

我對上下文有點不清楚 - 這是在AFTER INSERT觸發器中。

無論如何,我看不出有任何方法可以在一次調用中做到這一點。 OUTPUT子句只允許你返回你插入的行。我會建議如下:

DECLARE @MyTable (
    myID INT, 
    previousID INT, 
    myText1 VARCHAR(20), 
    myText2 VARCHAR(20) 
) 

INSERT @MyTable (previousID, myText1, myText2) 
SELECT myID, myText1, myText2 FROM inserted 

INSERT MyTable (myText1, myText2) 
SELECT myText1, myText2 FROM inserted 

-- @@IDENTITY now points to the last identity value inserted, so... 
UPDATE m SET myID = i.newID 
FROM @myTable m, (SELECT @@IDENTITY - ROW_NUMBER() OVER(ORDER BY myID DESC) + 1 AS newID, myID FROM inserted) i 
WHERE m.previousID = i.myID 

... 

當然,你不會把這個變成一個AFTER INSERT觸發器,因爲它會給你一個遞歸調用,但你可以做到這一點在INSTEAD OF INSERT觸發器。我在遞歸問題上可能是錯的;我總是避免遞歸調用,所以我從來沒有真正發現過。然而,使用@@ IDENTITY和ROW_NUMBER()是我過去多次使用類似的一種方法。

+0

我不認爲這是一個觸發器。我相信這只是一個普通的SP。 – 2012-03-06 11:18:22