Вы должны стараться избегать курсоров, где это возможно, они являются базовым циклом, который приводит к построчным решениям, которые могут быть очень медленными на больших наборах данных SQL.Курсоры также резервируют пространство в буфере (памяти) и могут похищать ресурсы из других процессов.Если вам нужно выполнить цикл, вы должны использовать конструкцию WHILE.
SQL предлагает другие решения на основе SET, которые могут заменить решение CURSOR.
Ваша цель может быть более эффективно достигнута с помощью Рекурсивного CTE.
Вот пример Рекурсивного CTEэто может заменить необходимость вашего курсора:
CREATE TABLE #Splitter
(
Id INT
,Vals VARCHAR(10)
)
INSERT INTO #Splitter VALUES
(1,'A,B,C'),
(2,'D,E,F')
;WITH cte AS
(
--Anchor point, the first Value from each ID
SELECT
Id
,LEFT(Vals,CHARINDEX(',',Vals)-1) AS Val
,RIGHT(Vals,LEN(Vals)-CHARINDEX(',',Vals)) AS Remainder
FROM #Splitter
WHERE
Vals IS NOT NULL AND CHARINDEX(',',Vals)>0
UNION ALL
--Central Recursion for each value
SELECT
Id,LEFT(Remainder,CHARINDEX(',',Remainder)-1)
,RIGHT(Remainder,LEN(Remainder)-CHARINDEX(',',Remainder))
FROM cte
WHERE Remainder IS NOT NULL AND CHARINDEX(',',Remainder)>0
UNION ALL
--Error prevention, handling the end of the string
SELECT
Id,Remainder,null
FROM cte
WHERE Remainder IS NOT NULL AND CHARINDEX(',',Remainder)=0
)
SELECT ID,VAL FROM cte
Если ваш столбец [Vals] всегда имеет заданный формат, вы можете использовать CROSS APPLY со значениями VALUES для более эффективного решения.
SELECT
ID
,v.Val
FROM
#Splitter S
CROSS APPLY (VALUES (left(S.Vals,1)),(SUBSTRING(Vals,3,1)),(RIGHT(Vals,1))) v(Val)