0

The Situation:
I am inserting information from one table to another, a source and target. When the information is inserted into the target, a primary key is created. (In this case it is an integer.) I then need to be able to tie back to the source table. However, based on the data being moved, I am not able to reliably get the 1:1 match between the target and source tables.

The Question:
Is there a way to copy the primary key that was created for record(x) in the target table and copy it as a foreign key to that same record(x) in the source table as the bulk insert is happening?

Details:
I am trying to get this done in SQL. I have a work-around to this problem but I figure there has to be a way to do what I'm asking.

4

3 回答 3

2

I found my answer after reading this great article.

http://sqlblog.com/blogs/adam_machanic/archive/2009/08/24/dr-output-or-how-i-learned-to-stop-worrying-and-love-the-merge.aspx

I acheived what I was looking for by using a MERGE and its OUTPUT clause. Here is my sample code that I used to figure this out.

I started by creating 3 temporary tables, #Temp2, #Temp3 and #Temp4. #Temp2 is considered the source table. #Temp3 would be the target table and #Temp4 is a bridge. I then inserted a few rows of very simple data, in this case just one field - Value.

CREATE TABLE #Temp2(
OldID INT IDENTITY(1,1),
Value INT,
NewFK INT)

CREATE TABLE #Temp3(
NewerID INT IDENTITY(1,1),
Value INT)

CREATE TABLE #Temp4(
OldID INT NOT NULL,
NewerID INT NOT NULL,
Value INT)

INSERT INTO #Temp2(Value)
VALUES(30), (40), (50), (70)

INSERT INTO #Temp3(Value)
VALUES (333), (444), (555), (777)

Then comes the MERGE statement that does the dirty work. It will be taking the value from #Temp2 and putting it into #Temp3. It will then take the ID created in #Temp3, the ID from #Temp2 and the Value that was passed, and throw them all into #Temp4.

MERGE INTO #Temp3 AS tgt
USING #Temp2 AS src
ON 1=0
WHEN NOT MATCHED THEN
    INSERT(
    Value)
    VALUES(
    src.Value)
OUTPUT
    src.OldID,
    INSERTED.NewerID,
    src.Value
INTO #Temp4(OldID, NewerID, Value);

Then I ran an UPDATE to the staging table #Temp2 to update the NewFK field with the new ID. Lastly, do a simple SELECT to see the updated information.

UPDATE X
SET X.NewFK = Z.NewerID
FROM #Temp2 X
JOIN #Temp4 Z
ON X.OldID = Z.OldID

SELECT * FROM #Temp2

This acheived exactly what I needed and is a pretty streamlined way of doing things. I hope this will help some people who come across this question. Thanks everyone for your insight and responses.

NOTE: I believe MERGE was introduced in SQL Server 2008.

Jonathan

于 2013-02-07T20:52:55.337 回答
0

一种方法是将目标表的标识插入设置为“开启”(http://msdn.microsoft.com/en-us/library/ms188059.aspx)。然后在运行插入之前将该身份作为“源”数据的一部分。完成后请记住再次关闭身份插入。

编辑
不知道你的情况是什么,但我过去采用的一种方法是创建一个字段来保存“外部源 ID”,以防万一我需要在未来某个时候引用源。就我而言,这仅供参考,不是正常的交易用途。

于 2013-02-06T18:37:01.233 回答
0

If you can get a SharedExtPK in the target then this should work.
In this case logID is the PK of the source.
Tested:

DECLARE @MyTableVar table(
  TargetPK     int NOT NULL,
  SourcePK     int NOT NULL
  );

INSERT INTO IdenOutPut (someValue, sharedExtKey)
  OUTPUT INSERTED.iden, 
         INSERTED.sharedExtKey
  INTO @MyTableVar
    SELECT name, logID
    FROM CatID

update sPK 
set sPK.ExtPK = tTbl.TargetPK
FROM @MyTableVar as tTbl 
JOIN CatID as sPK 
  on sPK.logID = tTbl.SourcePK 
GO

If the values you insert are unique then could use that.
But it would get trickier.

于 2013-02-06T20:52:01.207 回答