0

テーブル内の行をコピーするストアド プロシージャを作成しています。

これがテーブルです

例

これをコピーしたいのですが、ParentId を新しい行にリンクする必要があります。単純な INSERT INTO > SELECT FROM を実行すると、上記のように、ParentId は新しい ProductId ではなく ProductId 22 にリンクされます。

なにか提案を?

4

2 に答える 2

1

あなたの質問は完全に明確ではありませんが、正しく理解できれば、その階層を維持しながら階層を構築するいくつかの行をコピーしようとしています。

これは、1 つのステップで行うことはできません。最初に行をコピーし、新しい ID と一致する古い 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 に答える