2012-06-08 31 views
73

我對數據庫做了一些修改,我需要將舊數據遷移到新表中。爲此,我需要填寫一張表格(ReportOptions)從原始表格(Practice)中獲取數據,並填寫第二個中間表格(PracticeReportOption)。是否可以讓SQL Output子句返回未插入的列?

ReportOption (ReportOptionId int PK, field1, field2...) 
Practice (PracticeId int PK, field1, field2...) 
PracticeReportOption (PracticeReportOptionId int PK, PracticeId int FK, ReportOptionId int FK, field1, field2...) 

我做了一個查詢來獲取所有我需要從實踐移到ReportOptions的數據,但我有麻煩,填補了中間表

--Auxiliary tables 
DECLARE @ReportOption TABLE (PracticeId int /*This field is not on the actual ReportOption table*/, field1, field2...) 
DECLARE @PracticeReportOption TABLE (PracticeId int, ReportOptionId int, field1, field2) 

--First I get all the data I need to move 
INSERT INTO @ReportOption 
SELECT P.practiceId, field1, field2... 
    FROM Practice P 

--I insert it into the new table, but somehow I need to have the repation PracticeId/ReportOptionId 
INSERT INTO ReportOption (field1, field2...) 
OUTPUT @ReportOption.PracticeId, --> this is the field I don't know how to get 
     inserted.ReportOptionId 
    INTO @PracticeReportOption (PracticeId, ReportOptionId) 
SELECT field1, field2 
    FROM @ReportOption 

--This would insert the relationship, If I knew how to get it! 
INSERT INTO @PracticeReportOption (PracticeId, ReportOptionId) 
SELECT PracticeId, ReportOptionId 
    FROM @ReportOption 

如果我可以引用一個領域,不在OUTPUT子句的目標表上,那會很棒(我認爲我不能,但我不知道)。關於如何滿足我的需求的任何想法?

在此先感謝。

+0

您可以在OUTPUT子句中返回插入行的表中的任何列。因此,即使您沒有在INSERT語句中爲給定列提供值,仍然可以在OUTPUT子句中指定該列。但是,您不能從其他表中返回SQL變量或列。 –

+0

@marc_s謝謝你的回覆,但我沒有在目的地表中需要的字段(我需要的是PracticeId,它不在ReportOption上) –

回答

117

您可以通過使用MERGE,而不是插入的做到這一點:

所以更換此

INSERT INTO ReportOption (field1, field2...) 
OUTPUT @ReportOption.PracticeId, --> this is the field I don't know how to get 
     inserted.ReportOptionId 
    INTO @PracticeReportOption (PracticeId, ReportOptionId) 
SELECT field1, field2 
    FROM @ReportOption 

MERGE INTO ReportOption USING @ReportOption AS temp ON 1 = 0 
WHEN NOT MATCHED THEN 
    INSERT (field1, field2) 
    VALUES (temp.Field1, temp.Field2) 
    OUTPUT temp.PracticeId, inserted.ReportOptionId, inserted.Field1, inserted.Field2 
    INTO @PracticeReportOption (PracticeId, ReportOptionId, Field1, Field2); 

的關鍵是使用的是不會是真實的陳述( 1 = 0),因此您將始終執行插入操作,但可以訪問源表和目標表中的字段。


這裏是我用來測試它的整個代碼:

CREATE TABLE ReportOption (ReportOptionID INT IDENTITY(1, 1), Field1 INT, Field2 INT) 
CREATE TABLE Practice (PracticeID INT IDENTITY(1, 1), Field1 INT, Field2 INT) 
CREATE TABLE PracticeReportOption (PracticeReportOptionID INT IDENTITY(1, 1), PracticeID INT, ReportOptionID INT, Field1 INT, Field2 INT) 

INSERT INTO Practice VALUES (1, 1), (2, 2), (3, 3), (4, 4) 


MERGE INTO ReportOption r USING Practice p ON 1 = 0 
WHEN NOT MATCHED THEN 
    INSERT (field1, field2) 
    VALUES (p.Field1, p.Field2) 
    OUTPUT p.PracticeId, inserted.ReportOptionId, inserted.Field1, inserted.Field2 
    INTO PracticeReportOption (PracticeId, ReportOptionId, Field1, Field2); 

SELECT * 
FROM PracticeReportOption 

DROP TABLE ReportOption 
DROP TABLE Practice 
DROP TABLE PracticeReportOption 

多看書,和所有我知道關於這個問題的來源是Here

+1

謝謝,這真是個竅門!我打算使用一個虛假的溫度場,但這更優雅。 –

+0

非常好!這招是一粒金子!添加到集合中的第一行! –

+0

這正是我正在尋找的,謝謝! – fhilton

11

也許有人誰使用MS SQL Server 2005或更低版本將會發現這個答案有用。


MERGE只能用於SQL Server 2008或更高版本。 對於休息我發現另一個解決方法,這將使您能夠創建一種映射表。

這裏的分辨率將如何看起來像2005 SQL:

DECLARE @ReportOption TABLE (ReportOptionID INT IDENTITY(1, 1), Field1 INT, Field2 INT) 
DECLARE @Practice TABLE(PracticeID INT IDENTITY(1, 1), Field1 INT, Field2 INT) 
DECLARE @PracticeReportOption TABLE(PracticeReportOptionID INT IDENTITY(1, 1), PracticeID INT, ReportOptionID INT, Field1 INT, Field2 INT) 

INSERT INTO @Practice (Field1, Field2) VALUES (1, 1) 
INSERT INTO @Practice (Field1, Field2) VALUES (2, 2) 
INSERT INTO @Practice (Field1, Field2) VALUES (3, 3) 
INSERT INTO @Practice (Field1, Field2) VALUES (4, 4) 

INSERT INTO @ReportOption (field1, field2) 
    OUTPUT INSERTED.ReportOptionID, INSERTED.Field1, INSERTED.Field2 INTO @PracticeReportOption (ReportOptionID, Field1, Field2) 
    SELECT Field1, Field2 FROM @Practice ORDER BY PracticeID ASC; 


WITH CTE AS (SELECT PracticeID, ROW_NUMBER() OVER (ORDER BY PracticeID ASC) AS ROW FROM @Practice) 
UPDATE M SET M.PracticeID = S.PracticeID 
    FROM @PracticeReportOption AS M 
    JOIN CTE AS S ON S.ROW = M.PracticeReportOptionID 

    SELECT * FROM @PracticeReportOption 

主要的竅門是,我們從源和目標表有序的數據填充映射表的兩倍。 更多詳細信息,請訪問:Merging Inserted Data Using OUTPUT in SQL Server 2005

相關問題