4

行とそのすべての子を複製する SQL 2008 R2 ストアド プロシージャを作成しています。

親、子、子の 3 層のセットアップです。親の ID を指定すると、複製を作成する必要があります。

を使って解決しましたfast_forward cursor

行を while ループしても実行できることはわかっていますが、このカーソル方法よりも高速になるとは思いません。あなたの考えは何ですか?

カーソルを使用せずにこのタスクを達成するためのより良い方法はありますか?

編集:私が検討した別のオプションは、TBLACSstages レコードの古い/新しい PKID を保持する一時テーブルを作成することでした。

TBLACSstages には、1 ~ 20 の対応する行が含まれる場合があります (また、TBLACUpgrade には、TBLACSstages の行ごとに 3 つの行が含まれる可能性があります)。

CREATE PROCEDURE [dbo].[spDuplicateACUnit]
@pACUnitID bigint = 0 
AS BEGIN
SET NOCOUNT ON;

DECLARE @NewACUnitID bigint = 0

INSERT INTO TBLACUnits ([col1] ,[col2] ,[...] ,[coln]) SELECT [col1] ,[col2] ,[...] ,[coln] FROM TBLACUnits WHERE ACUnitID = @pACUnitID

SELECT @NewACUnitID = SCOPE_IDENTITY()

DECLARE @ACStageID bigint = 0 
    DECLARE @NewACStageID bigint = 0

DECLARE @ACUnitCursor CURSOR

SET @ACUnitCursor = CURSOR LOCAL FAST_FORWARD FOR SELECT ACStageID FROM TBLACStages WHERE TBLACStages.ACUnitID = @pACUnitID

OPEN @ACUnitCursor

FETCH NEXT FROM @ACUnitCursor INTO @ACStageID

WHILE @@FETCH_STATUS = 0 
BEGIN

INSERT INTO TBLACStages ([ACUnitID] ,[col1] ,[col2] ,[...] ,[coln]) SELECT @NewACUnitID ,[col1] ,[col2] ,[...] ,[coln] FROM TBLACStages WHERE TBLACStages.ACStageID = @ACStageID

SELECT @NewACStageID = SCOPE_IDENTITY()

INSERT INTO TBLACUpgrade ([ACStageID] ,[col1] ,[col2] ,[...] ,[coln]) SELECT @NewACStageID ,[col1] ,[col2] ,[...] ,[coln] FROM TBLACUpgrade WHERE TBLACUpgrade.[ACStageID] = @ACStageID

FETCH NEXT FROM @ACUnitCursor INTO @ACStageID 
END

CLOSE @ACUnitCursor DEALLOCATE @ACUnitCursor

END

GO
4

4 に答える 4

6

これにより、次のことがわかります。

CREATE TABLE t_parent (id INT NOT NULL PRIMARY KEY IDENTITY, value VARCHAR(100))
CREATE TABLE t_child (id INT NOT NULL PRIMARY KEY IDENTITY, parent INT NOT NULL, value VARCHAR(100))
CREATE TABLE t_grandchild (id INT NOT NULL PRIMARY KEY IDENTITY, child INT NOT NULL, value VARCHAR(100))

INSERT
INTO    t_parent (value)
VALUES  ('Parent 1')

INSERT
INTO    t_parent (value)
VALUES  ('Parent 2')

INSERT
INTO    t_child (parent, value)
VALUES  (1, 'Child 2')

INSERT
INTO    t_child (parent, value)
VALUES  (2, 'Child 2')

INSERT
INTO    t_grandchild (child, value)
VALUES  (1, 'Grandchild 1')

INSERT
INTO    t_grandchild (child, value)
VALUES  (1, 'Grandchild 2')

INSERT
INTO    t_grandchild (child, value)
VALUES  (2, 'Grandchild 3')

DECLARE @parent TABLE (oid INT, nid INT)
DECLARE @child TABLE (oid INT, nid INT)

MERGE
INTO    t_parent
USING   (
        SELECT  id, value
        FROM    t_parent
        ) p
ON      1 = 0
WHEN NOT MATCHED THEN
INSERT  (value)
VALUES  (value)
OUTPUT  p.id, INSERTED.id
INTO    @parent;
SELECT  *
FROM    @parent
MERGE
INTO    t_child
USING   (
        SELECT  c.id, p.nid, c.value
        FROM    @parent p
        JOIN    t_child c
        ON      c.parent = p.oid
        ) c
ON      1 = 0
WHEN NOT MATCHED THEN
INSERT  (parent, value)
VALUES  (nid, value)
OUTPUT  c.id, INSERTED.id
INTO    @child;
SELECT  *
FROM    @child;
INSERT
INTO    t_grandchild (child, value)
SELECT  c.nid, gc.value
FROM    @child c
JOIN    t_grandchild gc
ON      gc.child = c.oid
SELECT  *
FROM    t_grandchild
于 2010-08-31T22:35:02.257 に答える
1

これは、MERGEQuassnoi のソリューションに基づいて思いついたものです。私は適切に働くべきですCURSOR

DECLARE @parent TABLE (oid BIGINT, nid BIGINT)
DECLARE @child TABLE (oid BIGINT, nid BIGINT)

MERGE
INTO    TBLACUnits T
USING   (SELECT [col1], [...], [coln] FROM TBLACUnits WHERE ID = @pID) S

ON      1 = 0
WHEN NOT MATCHED THEN
INSERT  ([ACUnitID]
   ,[col1]
   ,[...]
   ,[coln])
VALUES  (S.[ACUnitID]
   ,S.[col1]
   ,S.[...]
   ,S.[coln]])
OUTPUT  S.ACUnitID, INSERTED.ACUnitID
INTO    @parent;

MERGE
INTO    TBLACStages T
USING   (
  SELECT  tt.[nid] 
                       ,TBLACStages.[col1]
                       ,TBLACStages.[...]
                       ,TBLACStages.[coln]
  FROM TBLACStages
  JOIN @parent tt ON tt.oid = TBLACStages.ACUnitID
  ) S
ON      1 = 0
WHEN NOT MATCHED THEN
INSERT  ([ACUnitID]
   ,[col1]
   ,[...]
   ,[coln])
VALUES  ([nid]
   ,[col1]
   ,[...]
   ,[coln])
OUTPUT  S.[ACStageID], INSERTED.[ACStageID]
INTO    @child;

INSERT INTO TBLACUpgrade 
([ACStageID]
   ,[col1]
   ,[...]
   ,[coln])
SELECT  c.[nid]
   ,TBLACUpgrade.[col1]
   ,TBLACUpgrade.[...]
   ,TBLACUpgrade.[coln]
FROM    @child c
JOIN    TBLACUpgrade
 ON      TBLACUpgrade.ACStageID  = c.oid
于 2010-09-01T00:22:29.793 に答える
0

SPの速度を上げるには、別のステートメントを追加できますFOR READ ONLY

したがって、SPは次のよ​​うになります。

    ...

SET @ACUnitCursor = CURSOR LOCAL FAST_FORWARD FOR 

SELECT ACStageID FROM TBLACStages WHERE TBLACStages.ACUnitID = @pACUnitID

FOR READ ONLY  -- add this to increase the speed

OPEN @ACUnitCursor

FETCH NEXT FROM @ACUnitCursor INTO @ACStageID

...
于 2010-08-31T22:21:37.413 に答える