T-SQL存储过程可以从子选择中选择一个值

时间:2016-05-31 14:38:57

标签: sql-server tsql stored-procedures

我想创建一个存储过程,该过程将复制表中的项和子表中的子项。 在我的例子中,我有一个名为" Instance"其中包含密钥" InstanceID"表格中有多个子项目" CustomField"。 就其本身而言#CustomField"表格中有多个子项目" CustomFieldData"由关键字段" CustomFieldID"。

加入

所以我创建了一个存储过程来复制CustomField和CustomFieldData中的条目,后者在复制实例的存储过程之后运行并返回新的InstanceID。 第一部分 - CustomField的复制工作。 但随后是带有CustomFieldData副本的部分。 这里我想在INSERT中使用来自以下子选择的值(= customfieldidentity)。 这可能吗? 实际名称customfieldidentity不起作用。

提前致谢!

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]=@instanceId

    -- 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 个答案:

答案 0 :(得分:2)

外部查询看不到用于EXISTS运算符的子查询中的任何数据,如EXISTS (Sub-Query)

exists运算符仅检查是否存在行/记录并返回TrueFalse它实际上不返回任何数据。您需要在以下查询中执行JOIN而不是EXISTS

-- 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)

答案 1 :(得分:0)

我已经解决了这个问题。 在我的情况下,我必须使用游标循环并调用其他存储过程,这将向循环中的实际键添加单个条目。

每个例子: 我想从表格中复制一个实例&#34; Instance&#34;。 一个实例在表格中有多个自定义字段&#34; CustomField&#34;。 首先,我按所​​选实例的给定ID复制实例:

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;

正如您所看到的,我在复制实例之后调用存储过程sp_CopyCustomFields来复制表中的条目&#34; CustomField&#34;属于原始实例。

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;

这里我查找表中包含原始InstanceID的所有条目,然后使用存储过程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;