我编写了一个存储过程来复制表中的行。
这是桌子
我想复制它,但 ParentId 应该链接到新行。如果我执行简单的 INSERT INTO > SELECT FROM,ParentId 将链接到 ProductId 22 而不是新的 ProductId,如上所示。
有什么建议吗?
我编写了一个存储过程来复制表中的行。
这是桌子
我想复制它,但 ParentId 应该链接到新行。如果我执行简单的 INSERT INTO > SELECT FROM,ParentId 将链接到 ProductId 22 而不是新的 ProductId,如上所示。
有什么建议吗?
您的问题并不完全清楚,但如果我理解正确,您正在尝试复制几行来构建层次结构,同时保留该层次结构。
这不能一步完成。您需要首先复制行并记录新的和它们匹配的旧 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 包装在事务中,以防止其他人读取新的和尚未完成的记录。
您可以使用它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
这有帮助吗?