Reputation: 87
Current code:
DECLARE thisLoop CURSOR FOR
SELECT IdOld, IdNew
FROM @fieldNewOld;
OPEN thisLoop;
FETCH NEXT FROM thisLoop INTO @fIdOld, @fIdNew;
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE dbo.mel
SET melCode = REPLACE(melCode, '_' + CONVERT(varchar(50),@fIdOld), '_' + CONVERT(varchar(50),@fIdNew))
where fID = (select IdNew from @newForm) and melCode LIKE ('%_' + CONVERT(varchar(50), @fIdOld) + '%')
FETCH NEXT FROM thisLoop INTO @fIdOld, @fIdNew
END;
CLOSE thisLoop;
DEALLOCATE thisLoop;
There is more going on around this, but basically I'm making a copy of a data set. @fieldNewOld contains the old id's and new id's. melCode in dbo.mel contains code written (in a proprietary language) that can reference all of the old id's. It would be referenced something like "myVar_1234" where 1234 would be one of the old id's. When copying, I'm wanting to replace all of the old id's with the new id's in melCode.
I can do it with the cursor loop shown above, but it is VERY slow when there is a large data set. I've also tried the code below, but if there is more than one old id in melCode, it will try to update the same row multiple times and throw an error:
MERGE INTO dbo.mel b
USING @fieldNewOld a
ON b.fID = (select IdNew from @newForm) and b.melCode LIKE ('%_' + CONVERT(varchar(50), a.IdOld) + '%')
WHEN MATCHED THEN
UPDATE
SET b.melCode = REPLACE(b.melCode, '_' + CONVERT(varchar(50),a.IdOld), '_' + CONVERT(varchar(50),a.IdNew));
Is there any way to accomplish this in a set based fashion, or am I stuck with the slowness of the cursor loop?
Example Data:
@fieldNewOld
IdOld | IdNew
1234 | 5678
1235 | 5679
1236 | 5680
melCode (all of this would be in one row)
userok("My variable: " + myVar_1234)
myVar_1234 = "this is a test"
newVar_1236 = "here is some more data"
After copying I would want melCode to look like this:
userok("My variable: " + myVar_5678)
myVar_5678 = "this is a test"
newVar_5680 = "here is some more data"
Upvotes: 2
Views: 76
Reputation: 107577
Consider an update with JOIN
of your final table and table variables:
UPDATE m
SET m.melCode = REPLACE(m.melCode, '_' + CONVERT(varchar(50), f.IdOld),
'_' + CONVERT(varchar(50), f.IdNew))
FROM dbo.mel m
JOIN @fieldNewOld f
ON m.melCode LIKE ('%_' + CONVERT(varchar(50), f.IdOld) + '%')
JOIN @newForm n
ON m.fID = n.IdNew
Since you need to update the same text multiple times, consider wrapping above in an iterative update running across the number of rows in fieldNewOld
IDs:
DECLARE @Counter INT
DECLARE @ID_Count INT
SET @Counter = 0
SET @ID_Count = (SELECT COUNT(*) FROM @fieldNewOld)
WHILE @Counter <= @ID_Count
BEGIN
UPDATE m
SET m.melCode = REPLACE(m.melCode, '_' + CONVERT(varchar(50), f.IdOld),
'_' + CONVERT(varchar(50), f.IdNew))
FROM dbo.mel m
JOIN @fieldNewOld f
ON m.melCode LIKE ('%_' + CONVERT(varchar(50), f.IdOld) + '%')
JOIN @newForm n
ON m.fID = n.IdNew
SET @Counter += 1
END
Upvotes: 1
Reputation: 3585
You can use JOINs in an UPDATE.
UPDATE m
SET melCode = REPLACE(melCode, '_' + CONVERT(varchar(50),IdOld), '_' + CONVERT(varchar(50),fIdNew))
FROM dbo.mel m
JOIN @fieldNewOld fno ON m.melCode LIKE ('%_' + CONVERT(varchar(50), IdOld) + '%')
where fID = (select IdNew from @newForm) ;
This seems like you have a composite value in melCode. My suggestion would be to split the value into 2 or more columns and have melCode as a computed column.
Upvotes: 1