2016-09-27 8 views
0

ソフトウェアの更新後に一部のデータを変換するスクリプトを作成しています。私は新しいテーブルを導入しており、既存のテーブルからこの新しいテーブルにデータを抽出する必要があります。あるテーブルから既存のvarchar(max)フィールドを取り出し、別のテーブルに親子レコードを作成し、別のテーブルに新しい親レコードのIDを挿入する必要があります。 レコードを挿入するために使用されているSELECTステートメントにストアドプロシージャの結果を返す方法

は、だから、ちょっとだけ新しいテーブルに直接移行されている上記の例のval1とval2の分野では、この

INSERT INTO NEWTABLE (val1, val2, val3) 
SELECT 
    val1, 
    val2, 
    EXEC AStoredProc(val3) -- this obviosuly doesnt work 
FROM EXISTINGTABLE 

CREATE PROCEDURE AStoredProc 
    @Value nvarchar(max), 
    @NewID int OUTPUT 

    DECLARE @ParentID int 

    INSERT INTO AnotherTable ([Text], ParentNodeID) 
    VALUES ('',NULL) 

    SELECT @ParentID = SCOPE_IDENTITY() 

    INSERT INTO AnotherTable ([Text], ParentNodeID) 
    VALUES (@Value,@ParentID) 

    SELECT @ParentID 

END 

に見えるようにしたいです。新しいテーブルのval3はintで、AStoredProcの結果から挿入されています。これは、Existingテーブルのvarchar(max)val3値を取ると、別のテーブルにいくつかのレコードが作成され、新しい親IDが返されます。新しいテーブルにval3として挿入されます。

デザインの面倒を気にすることなく、基本的にStored Procでいくつかの挿入物を実行し、その結果を外部Select文に直接戻すことができますか?

答えて

1

私は考えることができる2つのオプションがあります。

  1. CURSORを使用します。

    DECLARE @val1 datatype1, 
         @val2 datatype2, 
         @val3 NVARCHAR(MAX), 
         @ParentID INT; 
    
    DECLARE migrate CURSOR LOCAL STATIC 
    FOR SELECT et.val1, et.val2, et.val3 
        FROM EXISTINGTABLE et 
        WHERE NOT EXISTS (
            SELECT * 
            FROM NEWTABLE nt 
            WHERE nt.val1 = et.val1 
            AND nt.val2 = et.val2 
             ); 
    
    BEGIN TRY 
    
    OPEN migrate 
    
    FETCH NEXT 
    FROM migrate 
    INTO @val1, @val2, @val3; 
    
    WHILE (@@FETCH_STATUS <> 0) 
    BEGIN 
        BEGIN TRAN; 
    
        EXEC dbo.AStoredProc 
          @Value = @val3, 
          @NewID = @ParentID OUTPUT; 
    
        INSERT INTO NEWTABLE (val1, val2, val3) 
        VALUES (@val1, @val2, @ParentID); 
    
        COMMIT; 
    END; 
    
    CLOSE migrate; 
    DEALLOCATE migrate; 
    
    END TRY 
    BEGIN CATCH 
        ROLLBACK TRAN; 
        -- catch block stuff goes here 
    END CATCH; 
    
  2. にストアドプロシージャに記載されている、少なくとも最初のAnotherTableに「一時的」の列を作成します。新しく作成されたレコードの関連付けを保持するサンプルコード(つまり、@ParentID値を生成するテーブル)。これにより、クエリが別のステップとして実行できるため、セットベースの操作を実行できます。 EXISTINGTABLEにすでにIDENTITY値/ PKを使用している場合は、それをそのまま使用してください。そうしないと、一時的な列がUNIQUEIDENTIFIERで、新しい値を容易に作成できます。NEWID()を使用してください。しかし、(すなわちEXISTINGTABLEINT PKを持っている)、それはようなものになるだろう瞬間のために幸せなパスを想定して:

    -- set up temporary association column 
    ALTER TABLE dbo.AnotherTable 
        ADD [TempAssociationID] INT NOT NULL; 
    
    BEGIN TRY 
    
    BEGIN TRAN; 
    
    -- populate initial "parent" records 
    INSERT INTO dbo.AnotherTable ([Text], [TempAssociationID]) 
        SELECT '', et.PK_column 
        FROM dbo.EXISTINGTABLE et; 
    
    -- populate "child" records 
    INSERT INTO dbo.AnotherTable ([Text], [TempAssociationID], ParentNodeID) 
        SELECT et.val3, et.PK_column, anthr.ID_column AS [ParentNodeID] 
        FROM dbo.EXISTINGTABLE et 
        INNER JOIN dbo.AnotherTable anthr 
          ON anthr.[TempAssociationID] = et.PK_column 
         AND anthr.[ParentNodeID] IS NULL; 
    
    -- combine existing and secondary tables for "new" table 
    INSERT INTO dbo.NEWTABLE (val1, val2, val3) 
        SELECT et.val1, et.val2, anthr.ID_column AS [val3] 
        FROM dbo.EXISTINGTABLE et 
        INNER JOIN dbo.AnotherTable anthr 
          ON anthr.[TempAssociationID] = et.PK_column 
         AND anthr.[ParentNodeID] IS NULL; 
    
    COMMIT TRAN; 
    
    END TRY 
    BEGIN CATCH 
        ROLLBACK TRAN; 
        -- other catch block stuffs 
    END CATCH; 
    
    ALTER TABLE dbo.AnotherTable 
        DROP COLUMN [TempAssociationID]; 
    
+0

ええ、私は一種の彼らは私のオプションも考えました。私はカーソルアプローチのために行くつもりだと思う。私は簡単にロールバック可能なトランザクションで行うことができると期待していました。 –

+0

@StewartAlan ...オプション2 ;-)を終了させることができます。 –

+0

@StewartAlanは競合オプション#2を参照してください:) –

関連する問題