使用存储过程复制复杂表

时间:2013-01-24 13:26:41

标签: sql-server stored-procedures

我编写了一个存储过程来复制表中的行。

这是表格

Example

我想复制此内容,但ParentId应链接到新行。 如果我做一个简单的INSERT INTO>如上所示,从ParentId中选择将链接到ProductId 22而不是新的ProductId。

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

您的问题并不完全清楚,但如果我理解正确,您正在尝试复制构建层次结构的多个行,同时保留该层次结构。

这不能一步完成。您需要先复制行并记录新的及其匹配的旧ID。然后,您可以更新新行中的引用以指向新父项。

最简单的方法是使用MERGE语句:

 CREATE TABLE dbo.tst(id INT IDENTITY(1,1), parent_id INT, other INT);

 INSERT INTO dbo.tst(parent_id, other)VALUES(NULL,1);
 INSERT INTO dbo.tst(parent_id, other)VALUES(1,2);
 INSERT INTO dbo.tst(parent_id, other)VALUES(1,3);
 INSERT INTO dbo.tst(parent_id, other)VALUES(3,4);
 INSERT INTO dbo.tst(parent_id, other)VALUES(NULL,5);
 INSERT INTO dbo.tst(parent_id, other)VALUES(5,6);

 CREATE TABLE #tmp(old_id INT, new_id INT);

 MERGE dbo.tst AS trg
 USING dbo.tst AS src
 ON (0=1)
 WHEN NOT MATCHED 
 AND (src.id >= 1) --here you can put your own WHERE clause.
 THEN
 INSERT(parent_id, other)
 VALUES(src.parent_id, src.other)
 OUTPUT src.id, INSERTED.id INTO #tmp(old_id, new_id);

 UPDATE trg SET
   parent_id = tmp_translate.new_id
 FROM dbo.tst AS trg
 JOIN #tmp AS tmp_filter
 ON trg.id = tmp_filter.new_id
 JOIN #tmp AS tmp_translate
 ON trg.parent_id = tmp_translate.old_id;

 SELECT * FROM dbo.tst;

带注释的行是您可以放置​​自己的where子句以选择要复制的行的位置。确保实际复制所有引用的父母。如果您复制没有父项的子项,则更新将无法捕获它,并且最终将指向旧父项。

您还应该在事务中包装MERGE和UPDATE,以防止其他人读取新的和尚未完成的记录。

答案 1 :(得分:0)

您可以使用SELECT执行此操作,只需手动指定列的顺序即可。下面是一个示例,假设您的表名为Product并且ProductId是自动递增的。请注意,SELECT中返回的第一列是旧行的主键。

INSERT dbo.Product
SELECT
    ProductId,
    ArtNo,
    [Description]
    Specification,
    Unit,
    Account,
    NetPrice
    OhTime
FROM dbo.Product AS P
WHERE P.ParentId = 22

这有帮助吗?