0

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

这是桌子

例子

我想复制它,但 ParentId 应该链接到新行。如果我执行简单的 INSERT INTO > SELECT FROM,ParentId 将链接到 ProductId 22 而不是新的 ProductId,如上所示。

有什么建议吗?

4

2 回答 2

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 包装在事务中,以防止其他人读取新的和尚未完成的记录。

于 2013-01-24T14:29:57.183 回答
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

这有帮助吗?

于 2013-01-24T14:15:26.377 回答