В этом сценарии возможна установка на основе вместо курсора? - PullRequest
2 голосов
/ 01 мая 2019

Текущий код:

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;

Вокруг этого происходит больше, но в основном я делаю копию набора данных. @fieldNewOld содержит старые и новые идентификаторы. melCode в dbo.mel содержит код, написанный (на проприетарном языке), который может ссылаться на все старые идентификаторы. На него будет ссылаться что-то вроде «myVar_1234», где 1234 будет одним из старых идентификаторов. При копировании я хочу заменить все старые идентификаторы новыми идентификаторами в melCode.

Я могу сделать это с помощью курсора, показанного выше, но он ОЧЕНЬ медленный, когда есть большой набор данных. Я также попробовал приведенный ниже код, но если в melCode более одного старого идентификатора, он будет пытаться обновить одну и ту же строку несколько раз и выдать ошибку:

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

Есть ли способ сделать это способом, основанным на множестве, или я застрял с медлительностью цикла курсора?

Пример данных:

@ fieldNewOld

IdOld | IdNew
1234 | 5678
1235 | 5679
1236 | 5680

melCode (все это будет в одном ряду)

userok("My variable: " + myVar_1234)
myVar_1234 = "this is a test"
newVar_1236 = "here is some more data"

После копирования я бы хотел, чтобы melCode выглядел так:

userok("My variable: " + myVar_5678)
myVar_5678 = "this is a test"
newVar_5680 = "here is some more data"

Ответы [ 2 ]

1 голос
/ 01 мая 2019

Рассмотрим обновление с JOIN вашей финальной таблицы и переменных таблицы:

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 

Так как вам нужно обновлять один и тот же текст несколько раз, рассмотрите возможность переноса выше в итеративное обновление, выполняемое по числу строк в fieldNewOld ID:

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

Rextester Demo

1 голос
/ 01 мая 2019

Вы можете использовать СОЕДИНЕНИЯ в ОБНОВЛЕНИИ.

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

Похоже, у вас есть составное значение в melCode.Я предлагаю разделить значение на 2 или более столбцов и использовать melCode в качестве вычисляемого столбца.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...