我想创建一个存储过程,该过程将复制表中的项和子表中的子项。 在我的例子中,我有一个名为" 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
答案 0 :(得分:2)
外部查询看不到用于EXISTS运算符的子查询中的任何数据,如EXISTS (Sub-Query)
。
exists运算符仅检查是否存在行/记录并返回True
或False
它实际上不返回任何数据。您需要在以下查询中执行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;