2008-09-30 38 views
15

我試圖建立一個映射表,將表中新行的ID與它們從中複製的ID相關聯。 OUTPUT INTO子句似乎是完美的,但它似乎沒有根據文檔的行爲。OUTPUT INTO子句中可以使用哪些列?

我的代碼:

DECLARE @Missing TABLE (SrcContentID INT PRIMARY KEY) 
INSERT INTO @Missing 
    (SrcContentID) 
SELECT cshadow.ContentID 
    FROM Private.Content AS cshadow 
    LEFT JOIN Private.Content AS cglobal ON cshadow.Tag = cglobal.Tag 
    WHERE cglobal.ContentID IS NULL 

PRINT 'Adding new content headers' 
DECLARE @Inserted TABLE (SrcContentID INT PRIMARY KEY, TgtContentID INT) 
INSERT INTO Private.Content 
    (Tag, Description, ContentDate, DateActivate, DateDeactivate, SortOrder, CreatedOn, IsDeleted, ContentClassCode, ContentGroupID, OrgUnitID) 
    OUTPUT cglobal.ContentID, INSERTED.ContentID INTO @Inserted (SrcContentID, TgtContentID) 
SELECT Tag, Description, ContentDate, DateActivate, DateDeactivate, SortOrder, CreatedOn, IsDeleted, ContentClassCode, ContentGroupID, NULL 
    FROM Private.Content AS cglobal 
    INNER JOIN @Missing AS m ON cglobal.ContentID = m.SrcContentID 

結果在錯誤消息:

Msg 207, Level 16, State 1, Line 34 
Invalid column name 'SrcContentID'. 

(線34作爲一個與OUTPUT INTO)

實驗表明,只有行是實際目前在INSERT的目標中可以在OUTPUT INTO中選擇。但是這與在線書籍中的文檔矛盾。在OUTPUT子句文章有介紹類似的用法示例E:

輸出INTO子句返回從表中被更新 (工單)值 並且還從產品 表。產品表用於 的FROM子句中,用於指定更新爲 的行。

有沒有人使用過此功能?

(在此期間我已經重寫我的代碼做使用遊標循環工作,但這是醜陋,我仍然好奇)

回答

13

我已驗證的問題是,你只能使用INSERTED列。該文件似乎表明,你可以使用from_table_name,但我似乎無法得到它的工作(多部分標識符「m.ContentID」無法綁定):

TRUNCATE TABLE main 

SELECT * 
FROM incoming 

SELECT * 
FROM main 

DECLARE @Missing TABLE (ContentID INT PRIMARY KEY) 
INSERT INTO @Missing(ContentID) 
SELECT incoming.ContentID 
FROM incoming 
LEFT JOIN main 
    ON main.ContentID = incoming.ContentID 
WHERE main.ContentID IS NULL 

SELECT * 
FROM @Missing 

DECLARE @Inserted TABLE (ContentID INT PRIMARY KEY, [Content] varchar(50)) 
INSERT INTO main(ContentID, [Content]) 
OUTPUT INSERTED.ContentID /* incoming doesn't work, m doesn't work */, INSERTED.[Content] INTO @Inserted (ContentID, [Content]) 
SELECT incoming.ContentID, incoming.[Content] 
FROM incoming 
INNER JOIN @Missing AS m 
    ON m.ContentID = incoming.ContentID 

SELECT * 
FROM @Inserted 

SELECT * 
FROM incoming 

SELECT * 
FROM main 

顯然,from_table_name前綴只是(在2008年或MERGE)允許在DELETEUPDATE - 我不知道爲什麼:

  • from_table_name

是一個colu mn前綴,用於指定DELETEUPDATE語句的FROM子句中包含的表,該表用於指定要更新或刪除的行。

如果還在FROM子句中指定了正在修改的表,則必須使用前綴INSERTED或來限定對該表中列的任何引用。

6

我遇到了與您完全相同的問題,我感到您的痛苦... 據我所知,無法使用帶INSERT語句的from_table_name前綴。 我相信這有一個可行的技術原因,我很想知道它到底是什麼。

好了,找到了,這裏有一個論壇的帖子上,爲什麼它不工作: MSDN forums

+0

它提供瞭解決方案的線索。 MERGE聲明!然後@Simon設法提供語法。太好了! – lambacck 2011-06-02 20:12:43

0

我想我找到了解決這個問題,它涉及到黯然臨時表,但至少它會防止創建一個可怕的遊標:) 你需要做的是添加一個額外的列到你正在複製記錄的表中,並給它一個'uniqueidentifer'類型。

然後聲明一個臨時表:

DECLARE @tmptable TABLE (uniqueid uniqueidentifier, original_id int, new_id int) 

插入的數據到臨時表是這樣的:

insert into @tmptable 
(uniqueid,original_id,new_id) 
select NewId(),id,0 from OriginalTable 

的繼續前進,做真正的插入到原始表:

insert into OriginalTable 
(uniqueid) 
select uniqueid from @tmptable 

現在將新創建的標識值添加到臨時表中:

update @tmptable 
set new_id = o.id 
from OriginalTable o inner join @tmptable tmp on tmp.uniqueid = o.uniqueid 

現在,你必須保持在一個創紀錄的新的ID和原始ID,您使用的樂趣:)

我希望這有助於有人查找表...

+1

謝謝,但這只是一個可行的解決方案,如果我需要跟蹤的關鍵是唯一標識符。我試圖解決的全部問題是跟蹤正在分配給新行的IDENTITY值。 – 2009-06-16 20:59:08

0

(MS)如果在FROM子句中也指定了正在修改的表,則必須使用INSERTED或DELETED前綴限定對該表中任何列的引用。

在你的榜樣,你不能在輸出時使用cglobal表,除非它是INSERTED.column_name或DELETED.column_name:

INSERT INTO Private.Content 
    (Tag) 
    OUTPUT cglobal.ContentID, INSERTED.ContentID 
    INTO @Inserted (SrcContentID, TgtContentID) 
SELECT Tag 
    FROM Private.Content AS cglobal 
    INNER JOIN @Missing AS m ON cglobal.ContentID = m.SrcContentID 

什麼工作對我來說是一個簡單的別名表,就像這樣:

INSERT INTO con1 
    (Tag) 
    OUTPUT **con2**.ContentID, INSERTED.ContentID 
    INTO @Inserted (SrcContentID, TgtContentID) 
SELECT Tag 
    FROM Private.Content con1 
    **INNER JOIN Private.Content con2 ON con1.id=con2.id** 
    INNER JOIN @Missing AS m ON con1.ContentID = m.SrcContentID 
+0

我無法得到這種工作方式:-( – 2011-01-11 12:15:15

21

您可以在SQL Server上比2008示例代碼一個MERGE做到這一點:

--drop table A 
create table A (a int primary key identity(1, 1)) 
insert into A default values 
insert into A default values 

delete from A where a>=3 

-- insert two values into A and get the new primary keys 
MERGE a USING (SELECT a FROM A) AS B(a) 
ON (1 = 0) -- ignore the values, NOT MATCHED will always be true 
WHEN NOT MATCHED THEN INSERT DEFAULT VALUES -- always insert here for this example 
OUTPUT $action, inserted.*, deleted.*, B.a; -- show the new primary key and source data 

[R對於每一行新的主鍵(3,4)和舊的鍵(1,2),結果是

INSERT, 3, NULL, 1 
INSERT, 4, NULL, 2 

。創建一個名爲例如#OUTPUT並添加「INTO #OUTPUT;」在OUTPUT子句的末尾將保存記錄。

+1

MERGE語句是我的新的最好的朋友:) – lambacck 2011-06-02 20:13:15

相關問題