Спасибо за этот вопрос - я только что узнал что-то новое.Следующий код является адаптацией статьи , написанной Робом Волком именно на эту тему.Это очень умный запрос!Я не буду копировать весь контент здесь.Я адаптировал его для создания результатов, которые вы ищете в своем примере.
CREATE TABLE #nums (n INT)
DECLARE @i INT
SET @i = 1
WHILE @i < 8000
BEGIN
INSERT #nums VALUES(@i)
SET @i = @i + 1
END
CREATE TABLE #tmp (
id INT IDENTITY(1,1) not null,
plist VARCHAR(MAX) null
)
INSERT INTO #tmp
VALUES('10,11,15,17,19'),('22,34,44,25'),('5,6,8,9')
CREATE TABLE #tmpprod (
oldid INT NULL,
newid INT NULL
)
INSERT INTO #tmpprod VALUES(5, 109),(9, 110),(10, 111),(15, 112),(19, 113),(30, 114),(34, 222),(44, 333)
;WITH cte AS (SELECT ID, NULLIF(SUBSTRING(',' + plist + ',' , n , CHARINDEX(',' , ',' + plist + ',' , n) - n) , '') AS prod
FROM #nums, #tmp
WHERE ID <= LEN(',' + plist + ',') AND SUBSTRING(',' + plist + ',' , n - 1, 1) = ','
AND CHARINDEX(',' , ',' + plist + ',' , n) - n > 0)
UPDATE t SET plist = (SELECT CAST(CASE WHEN tp.oldid IS NULL THEN cte.prod ELSE tp.newid END AS VARCHAR) + ','
FROM cte LEFT JOIN #tmpprod tp ON cte.prod = tp.oldid
WHERE cte.id = t.id FOR XML PATH(''))
FROM #tmp t WHERE id = t.id
UPDATE #tmp SET plist = SUBSTRING(plist, 1, LEN(plist) -1)
WHERE LEN(plist) > 0 AND SUBSTRING(plist, LEN(plist), 1) = ','
SELECT * FROM #tmp
DROP TABLE #tmp
DROP TABLE #tmpprod
DROP TABLE #nums
Таблица #nums - это таблица последовательных целых чисел, длина которой должна быть больше самой длинной CSV, которую вы имеетев вашем столе.Первые 8 строк сценария создают эту таблицу и заполняют ее.Затем я скопировал ваш код, за которым следует основная часть этого запроса - очень умный синтаксический анализатор с одним запросом, более подробно описанный в статье, указанной выше.Общее табличное выражение (WITH cte ...) выполняет синтаксический анализ, а скрипт обновления перекомпилирует результаты в CSV и обновляет # tmp.