У меня есть следующая хранимая процедура, предназначенная для итерации по списку строк, который содержит несколько подстрок формы prefix.bucketName
.Я хочу перебрать каждую строку и каждое имя сегмента и заменить старый префикс новым префиксом, но сохранить то же имя блока.
В качестве примера рассмотрим следующую исходную строку:
"(OldPrefix.BucketA)(OldPrefix.BucketB)"
Так, например, я хотел бы получить:
"(NewPrefix.BucketA)(NewPrefix.BucketB)"
Что я на самом деле получаю так:
"(OldPrefix.BucketA)(NewPrefix.BucketB)"
Таким образом, в общем случае обновляется только один из префиксов, и не предсказать, какой именно.На основании проведенного мною исследования выясняется, что обе замены действительно работают, но фактически сохраняется только последняя.Кажется, что SQL должен блокировать этот столбец, но вместо этого оба читаются одновременно, применяется замена, а затем оба записываются, оставляя последнюю запись, как показано в столбце.
Здесьзапрос - все имена переменных были изменены для обеспечения конфиденциальности - некоторые коды обработки ошибок и проверки данных были опущены для краткости:
DECLARE @PrefixID INT = 1478,
DECLARE @PrefixName_OLD NVARCHAR(50) = 'OldPrefix',
DECLARE @PrefixName_NEW NVARCHAR(50) = 'NewPrefix'
BEGIN TRAN
-- Code to rename the section itself here not shown for brevity
UPDATE
dbo.Component
SET
AString= REPLACE(AString,'('+@Prefix_OLD+'.'+b.BucketName+')', '('+@PrefixName_NEW+'.'+b.BucketName+')'),
FROM
dbo.Component sc
JOIN
dbo.ComponentBucketFilterInString fis
ON
sc.ComponentID = fis.ComponentID
JOIN
dbo.Buckets b
ON
fis.BucketID = b.BucketID
WHERE
b.PrefixID = @PrefixID
COMMIT
RETURN 1
Когда я пишу тот же запрос, используя цикл while, он работает как ожидалось:
DECLARE @BucketsToUpdate TABLE
(
BucketID INT,
BucketName VARCHAR(256)
)
INSERT INTO @BucketsToUpdate
SELECT BucketID, BucketName
FROM Buckets WHERE PrefixID = @PrefixID
WHILE EXISTS(SELECT 1 FROM @BucketsToUpdate)
BEGIN
DECLARE @currentBucketID INT,
@currentBucketName VARCHAR(256)
SELECT TOP 1 @currentBucketID = bucketID, @currentBucketName = bucketName FROM @BucketsToUpdate
UPDATE
dbo.Component
SET
AString = REPLACE(AString,'('+@PrefixName_OLD+'.'+@currentBucketName+')', '('+@PrefixName_NEW+'.'+@currentBucketName+')')
FROM
dbo.Component sc
JOIN
dbo.ComponentBucketFilterInString fis
ON
sc.ComponentID = fis.ComponentID
WHERE fis.BucketID = @currentBucketID
DELETE FROM @BucketsToUpdate WHERE BucketID = @currentBucketID
END
Почему отказывает первая версия?Как я могу это исправить?