感謝這個問題 - 我剛剛學到新的東西。以下代碼正是關於該主題的一個article written by Rob Volk的改編。這是一個非常聰明的查詢!我不會在這裏複製所有內容。我已經調整它來創建你在你的例子中尋找的結果。
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。
查看此鏈接中的解決方案:http://blogs.msdn.com/b/amitjet/archive/2009/12/11/sql-server-comma-separated-string-to-table。 aspx – diaho 2012-03-06 01:39:10
你能否指定你使用的是哪個版本的SQL Server? – 2012-03-06 03:30:24
此外,如果訂單很重要(例如,替換後111必須首先在列表中),我認爲唯一支持和保證的方式是使用遊標。 – 2012-03-06 03:39:56