Fer*_*min 2 t-sql sql-server sql-server-2008
我有4个相关的表,每个表与下一个表有1:N的关系,例如
One (OneID pk)
Two (TwoID pk, OneID fk)
Three (ThreeID pk, TwoID fk)
Four (FourID pk, ThreeID fk)
Run Code Online (Sandbox Code Playgroud)
当用户想要复制"One"中的记录以及表2,3和4中的所有相关记录时,我需要实现功能.
从前端开始,这样就可以使用户可以在现有记录上建立新记录.做这个的最好方式是什么?我有新插入的'OneID'和原始的'OneID'.
我想到这样做的一种方法是为每个表都有一个"复制"存储过程,每个表都有一个调用它的子表的游标为每行复制一次SP.
我想到的唯一另一种方法是让一个临时表记录每个表的原始+新ID,但这看起来很混乱,并且可能会失控.
有什么建议?
如果你的PK IDENTITY列,你可以使用涉及技术MERGE,在说明这个问题.
以下是整个过程的编写方式:
DECLARE @OldID int, @NewID int;
SET @OldID = some_value;
DECLARE @TwoMapping TABLE (OldID int, NewID int);
DECLARE @ThreeMapping TABLE (OldID int, NewID int);
INSERT INTO One
SELECT columns
FROM One
WHERE OneID = @OldID;
SET @NewID = SCOPE_IDENTITY();
/*
That one was simple: one row is copied, so just reading SCOPE_IDENTITY()
after the INSERT. The actual mapping technique starts at this point.
*/
MERGE Two tgt
USING (
SELECT
@NewID AS OneID,
other columns
FROM Two t
WHERE OneID = @OldID
) src
ON 0 = 1
WHEN NOT MATCHED THEN
INSERT (columns) VALUES (src.columns)
OUTPUT src.TwoID, INSERTED.TwoID INTO @TwoMapping (OldID, NewID);
/*
As you can see, MERGE allows us to reference the source table in the
OUTPUT clause, in addition to the pseudo-tables INSERTED and DELETED,
and that is a great advantage over INSERT and the core of the method.
*/
Run Code Online (Sandbox Code Playgroud)
MERGE Three tgt
USING (
SELECT
map.NewID AS TwoID,
t.other columns
FROM Three t
INNER JOIN @TwoMapping map ON t.TwoID = map.OldID
) src
ON 0 = 1
WHEN NOT MATCHED THEN
INSERT (columns) VALUES (src.columns)
OUTPUT src.ThreeID, INSERTED.ThreeID INTO @ThreeMapping (OldID, NewID);
/*
Now that we've got a mapping table, we can easily substitute new FKs for the old
ones with a simple join. The same is repeated once again in the following MERGE.
*/
MERGE Four tgt
USING (
SELECT
map.NewID AS ThreeID,
t.columns
FROM Four t
INNER JOIN @ThreeMapping map ON t.ThreeID = map.OldID
) src
ON 0 = 1
WHEN NOT MATCHED THEN
INSERT (columns) VALUES (src.columns);
/*
The Four table is the last one in the chain of dependencies, so the last MERGE
has no OUTPUT clause. But if there were a Five table, we would go on like above.
*/
Run Code Online (Sandbox Code Playgroud)
或者你可能不得不使用游标,这似乎是在SQL Server 2005和早期版本中执行此操作的唯一(理智)方式.