У меня есть таблица с 4 столбцами, одна из которых представляет собой строку с запятыми. Я использовал два подхода к щелевой и расширить этот список в виде таблицы:Почему XML-метод SPLITing, разделенный запятой, занимает больше времени, чем обычный метод цикла CURSOR или WHILE.
Подхожу> Использование XML:
declare @tbl TABLE (
id1 int,
id2 int,
id3 int,
str1 varchar(255)
)
INSERT INTO @tbl
SELECT p.n.value('@id1','INT'), p.n.value('@releaseId','INT'), p.n.value('@id3','INT'), '', p.n.value('.','nvarchar(150)')
FROM (SELECT CAST(('<r id1="'+CAST(id1 AS varchar(20))+'" id2="'+CAST(id2 AS varchar(20))+'" id3="'+CAST(id3 AS varchar(20))+'">'+REPLACE(CAST(str1 AS nvarchar(MAX)), ',', '</r><r id1="'+CAST(id1 AS varchar(20))+'" id2="'+CAST(id2 AS varchar(20))+'" id3="'+CAST(id3 AS varchar(20))+'">')+'</r>') AS XML) AS x
FROM SomeTable WITH(NOLOCK) WHERE CAST(str1 AS nvarchar(MAX)) <> '') R
CROSS APPLY R.x.nodes('/r') p(n)
select * from @tbl
II подход> Использование CURSOR и WHILE метода LOOP
CREATE FUNCTION dbo.fnSplit(
@sInputList VARCHAR(MAX) -- List of delimited items
, @sDelimiter VARCHAR(8000) = ',' -- delimiter that separates items
) RETURNS @List TABLE (item VARCHAR(100))
BEGIN
DECLARE @sItem VARCHAR(8000)
WHILE CHARINDEX(@sDelimiter,@sInputList,0) <> 0
BEGIN
SELECT
@sItem=RTRIM(LTRIM(SUBSTRING(@sInputList,1,CHARINDEX(@sDelimiter,@sInputList,0)-1))),
@sInputList=RTRIM(LTRIM(SUBSTRING(@sInputList,CHARINDEX(@sDelimiter,@sInputList,0)+LEN(@sDelimiter),LEN(@sInputList))))
IF LEN(@sItem) > 0
INSERT INTO @List SELECT @sItem
END
IF LEN(@sInputList) > 0
INSERT INTO @List SELECT @sInputList -- Put the last item in
RETURN
END
GO
-------------------------------------------
DECLARE @id1 INT
DECLARE @id2 INT
DECLARE @id3 INT
DECLARE @str1 nvarchar(MAX)
declare @tbl TABLE (
id1 int,
id2 int,
id3 int,
str1 varchar(255)
)
DECLARE getList CURSOR FOR
SELECT Id1, Id2, Id3, str1
FROM someTable
OPEN getaddUpdList
FETCH NEXT FROM getList INTO @id1, @id2, @id3, @str1
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO @tbl
SELECT @id1, @id2, @id3, '', _ID
FROM fnSplit(@str1, ',')
FETCH NEXT FROM getList INTO @id1, @id2, @id3, @sp, @str1
END
CLOSE getList
DEALLOCATE getList
select * from @tbl
Как то, что я читал онлайн, везде, CURSORS или WHILE, следует избегать. Но здесь, в этом случае, когда я пытаюсь использовать оба вышеупомянутых метода, подход I занимает около 15-20 секунд, в то время как подход II занимает менее секунды. Я не мог понять, почему так. Я пробовал это как в SQL SERVER 2008, так и в 2012 году, но результаты одинаковы.
Любая помощь в понимании такого непредсказуемого поведения будут оценены ..