I am creating a SQL 2008 R2 stored procedure to duplicate a row and all it's children.
It's a 3-tiered setup with a Parent, Child and Sub-Child Given the ID of the parent I need to create a duplicate.
I have solved it using a fast_forward
cursor
.
I know I can also do it with a while loop through rows but I do not believe that will be faster than this cursor method. What are your thoughts?
Is there a better way to accomplish this task without using cursors?
EDIT: Another option I considered was creating a temp table holding the old / new PKID's of the TBLACStages records.
TBLACStages may have anywhere from 1 to 20 corresponding rows (and TBLACUpgrade will likely have 3 rows per TBLACStages row)
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
This should give you the idea:
I saw this post I nearly gasped at the complexity, but sure it looks good. When I need to clone or copy tables with children or grandchildren I simply add a new column to the table called
PreCloneControl
, then reference this field in the child query of the new table to quickly and easily look up the old parent data. Easy. But if you do not have access to add columns to the table a quick hack can often serve. One example is a Last Modified User field, often an nvarchar of 100 or so character. Typically we need to update this field anyway, so drop your old control number in there and away you go. Just remember to perform a quick update on the Last Modified User field when you are done. Here is sample, I am using Temp Tables for Testing but you should use real tables.To increase the speed of your SP you can add another statement
FOR READ ONLY
So your SP will be like that:
Ok, this is the
MERGE
I've come up with based on Quassnoi's solution. I should work appropriately without theCURSOR