2016-05-31 27 views
-1

テーブルからアイテムをコピーするストアドプロシージャを作成し、従属テーブルのサブアイテムを作成します。 私の例では、 "InstanceID"というキーを持ち、テーブル "CustomField"に複数のサブアイテムがある "Instance"というテーブルがあります。 "CustomField"には、テーブル "CustomFieldData"に複数のサブアイテムがあり、キーフィールド "CustomFieldID"で結合されています。T-SQLストアドプロシージャでサブセレクトから値を選択することができます

私はインスタンスをコピーし、新しいInstanceIDを返しますストアドプロシージャの後に実行されるCustomFieldとCustomFieldDataからエントリをコピーするストアドプロシージャを作成しました。 最初の部分 - CustomFieldのコピーが動作します。 しかし、CustomFieldDataのコピーが付属しています。 ここでは、次のサブ選択から値(= customfieldidentity)をINSERTに使用したいと考えています。 これは可能ですか? 実際の名前customfieldidentityは機能しません。

ありがとうございます! EXISTS (Sub-Query)は、外側のクエリのために見えないよう

USE OneWhoIsWho; 

IF OBJECT_ID('dbo.sp_CopyCustomFieldsToInstance') IS NULL -- Check if SP Exists 
    EXEC ('CREATE PROCEDURE dbo.sp_CopyCustomFieldsToInstance AS SET NOCOUNT ON;') -- Create dummy/empty SP 
GO 

ALTER PROCEDURE dbo.sp_CopyCustomFieldsToInstance 
@instanceId int, 
@newInstanceId int 
AS 
BEGIN 
    BEGIN TRANSACTION T1 

    BEGIN TRY 

    -- Copy custom fields 
    INSERT INTO [dbo].[CustomField] 
     ([InstanceID] 
     ,[iFieldType] 
     ,[iFieldPosition] 
     ,[iVisibility] 
     ,[txtGUIDescription]) 
    SELECT 
     @newInstanceId 
     ,[iFieldType] 
     ,[iFieldPosition] 
     ,[iVisibility] 
     ,[txtGUIDescription] 
    FROM [dbo].[CustomField] 
    WHERE [dbo].[CustomField].[InstanceID][email protected] 

    -- Copy custom field data 
    INSERT INTO [dbo].[CustomFieldData] 
     ([CustomFieldID] 
     ,[txtCustomFieldData]) 
    SELECT 
     customfieldidentity 
     ,[txtCustomFieldData] 
    FROM dbo.CustomFieldData 
    WHERE EXISTS 
     (SELECT [CustomFieldID] AS customfieldidentity 
       ,[InstanceID] 
       ,[iFieldType] 
       ,[iFieldPosition] 
       ,[iVisibility] 
       ,[txtGUIDescription] 
     FROM [dbo].[CustomField] 
     WHERE dbo.CustomField.InstanceID = @newInstanceId) 

     COMMIT TRANSACTION T1 
    END TRY 

    BEGIN CATCH 
     ROLLBACK TRANSACTION T1 
    END CATCH 
END; 
GO 
+2

「動作しませんか?」と定義できますか?また、私はここでtry-squelchのアンチパターンと呼んでいるものを持っています。エラーが発生した場合は、トランザクションをロールバックするだけです。エラーをログに記録したり、システムやユーザーに何か問題があったことを知らせたりしない限り、失敗したことは決して分かりません。あなたは本当にsp_接頭辞を避けるべきです(または接頭辞を完全に避けるべきです)。 http://sqlperformance.com/2012/10/t-sql-queries/sp_prefix –

+0

「機能しません」とは、サブセレクトから列customfieldidentityを取得したいので、そのストアドプロシージャを実行できないことを意味します。 –

+1

あなたのINSERTのEXISTSステートメントでフィールドを使用することはできません – JamieD77

答えて

0

私はこの問題を解決しました。 私の場合、私はカーソルでループし、ループ内の実際のキーに単一のエントリを追加する他のストアドプロシージャを呼び出す必要があります。

例: "Instance"テーブルからインスタンスをコピーしたいと思います。 インスタンスには、 "CustomField"テーブルに複数のカスタムフィールドがあります。 「たCustomField」あなたが見ることができるように、私はテーブルからエントリをコピーするには、ストアドプロシージャのsp_CopyCustomFieldsインスタンスのコピー後に呼び出す

ALTER PROCEDURE [dbo].[sp_CopyInstance] 
@instanceId int, 
@txtInstanceDescription nvarchar(100), 
@iHidden int, 
@newInstanceId int OUTPUT 
AS 
BEGIN 
    BEGIN TRANSACTION TranCopyInstance 

    BEGIN TRY 
     -- Inserts a new instance with the given data 
     INSERT INTO [dbo].[Instance] 
      ([txtInstanceDescription] 
      ,[iHidden]) 
     VALUES 
      (@txtInstanceDescription 
      ,@iHidden) 

     -- Gets the InstanceID of the new instance 
     SELECT @newInstanceId = SCOPE_IDENTITY() 
     SELECT @newInstanceId AS InstanceID 

     -- Tries to copy the customfields which belong to the original instance 
     EXECUTE [dbo].[sp_CopyCustomFields] @instanceId, @newInstanceId 

     COMMIT TRANSACTION TranCopyInstance 
    END TRY 

    BEGIN CATCH 
     ROLLBACK TRANSACTION TranCopyInstance 
    END CATCH 
END; 

: は、最初に私が選択したインスタンスの指定したIDでインスタンスをコピーします元のインスタンスに属しています。ここで

ALTER PROCEDURE [dbo].[sp_CopyCustomFields] 
@instanceId int, 
@newInstanceId int 
AS 
BEGIN 
    BEGIN TRANSACTION TranCopyCustomFields 

    BEGIN TRY 
     DECLARE customFieldCursor CURSOR 
     FOR 
     SELECT [dbo].[CustomField].[CustomFieldID] 
     FROM [dbo].[CustomField] 
     WHERE [dbo].[CustomField].[InstanceID] = @instanceId 

     DECLARE @customFieldId int 

     -- Loops through all custom fields with the old InstanceID and makes a copy 
     OPEN customFieldCursor 
     FETCH NEXT FROM customFieldCursor INTO @customFieldId 
     WHILE @@FETCH_STATUS = 0 
     BEGIN 
      EXECUTE [dbo].[sp_CopyCustomField] @instanceId, @newInstanceId, @customFieldId 
      FETCH NEXT FROM customFieldCursor INTO @customFieldId 
     END 
     CLOSE customFieldCursor 
     DEALLOCATE customFieldCursor 

     COMMIT TRANSACTION TranCopyCustomFields 
    END TRY 

    BEGIN CATCH 
     ROLLBACK TRANSACTION TranCopyCustomFields 
    END CATCH 
END; 

私は、元のインスタンスIDを使用してテーブル内のすべてのエントリを探し、それから私は、ストアドプロシージャsp_CopyCustomField各エントリをコピーします。

ALTER PROCEDURE [dbo].[sp_CopyCustomField] 
@instanceId int, 
@newInstanceId int, 
@customFieldId int 
AS 
BEGIN 
    BEGIN TRANSACTION TranCopyCustomField 

    BEGIN TRY 
     -- Placeholder for the new CustomFieldID from the new row after the copy action 
     DECLARE @newCustomFieldId int 

     -- Makes a copy of the customfield with the old InstanceID and the CustomFieldID 
     INSERT INTO [dbo].[CustomField] 
      ([InstanceID] 
      ,[iFieldType] 
      ,[iFieldPosition] 
      ,[iVisibility] 
      ,[txtGUIDescription]) 
     SELECT 
      @newInstanceId 
      ,[iFieldType] 
      ,[iFieldPosition] 
      ,[iVisibility] 
      ,[txtGUIDescription] 
     FROM [dbo].[CustomField] 
     WHERE [dbo].[CustomField].[InstanceID] = @instanceId 
     AND [dbo].[CustomField].[CustomFieldID] = @customFieldId 

     -- Finds out the new CustomFieldID 
     SELECT @newCustomFieldId = SCOPE_IDENTITY() 
     SELECT @newCustomFieldId AS CustomFieldID 

     -- Loops through all custom lists with the old CustomFieldID and makes a copy 
     DECLARE customListCursor CURSOR 
     FOR 
     SELECT [dbo].[CustomList].[CustomListID] 
     FROM [dbo].[CustomList] 
     WHERE [dbo].[CustomList].[CustomFieldID] = @customFieldId 

     DECLARE @customListId int 

     OPEN customListCursor 
     FETCH NEXT FROM customListCursor INTO @customListId 
     WHILE @@FETCH_STATUS = 0 
     BEGIN 
      EXECUTE [dbo].[sp_CopyCustomList] @customFieldId, @newCustomFieldId, @customListId 
      FETCH NEXT FROM customListCursor INTO @customListId 
     END 
     CLOSE customListCursor 
     DEALLOCATE customListCursor 

     COMMIT TRANSACTION TranCopyCustomField 
    END TRY 

    BEGIN CATCH 
     ROLLBACK TRANSACTION TranCopyCustomField 
    END CATCH 
END; 
+0

私はどんな費用でもループを避けるでしょう。私はあなたが何をしているのかは完全には分かっていませんが、customfieldidentityを使用しているので、INSERTではOUTPUT節を追加できます。 INSERTED.customfieldidentityを新しい@Tableに取り込みます。これはINSERTの後に処理できます。 –

+0

問題は、複数のカスタムフィールド(コピーする必要がある)を持つテーブル "インスタンス"から特定のインスタンスアイテムをコピーしたいということです。各カスタムフィールドには複数のカスタムリストがあり、各カスタムリストには複数のカスタムリスト項目があります。 –

2

に使用されているサブクエリ内のすべてのデータは、オペレータが存在します。

existsオペレータは行/レコードの存在をチェックし、TrueまたはFalseを返します。実際にはデータは返されません。次のクエリでEXISTSの代わりにJOINを実行する必要があります。

-- Copy custom field data 
INSERT INTO [dbo].[CustomFieldData] 
    ([CustomFieldID] 
    ,[txtCustomFieldData]) 
SELECT 
    customfieldidentity 
    ,[txtCustomFieldData] 
FROM dbo.CustomFieldData 
WHERE EXISTS    --<-- Replace this with a join 
    (SELECT [CustomFieldID] AS customfieldidentity 
      ,[InstanceID] 
      ,[iFieldType] 
      ,[iFieldPosition] 
      ,[iVisibility] 
      ,[txtGUIDescription] 
    FROM [dbo].[CustomField] 
    WHERE dbo.CustomField.InstanceID = @newInstanceId) 
関連する問題