Hier ist ein etwas effizienterer Weg, um eine Liste von ganzen Zahlen aufzuteilen. Erstellen Sie zunächst eine Zahlentabelle, falls Sie noch keine haben. Dadurch wird eine Tabelle mit 100.000 eindeutigen Ganzzahlen erstellt (möglicherweise benötigen Sie mehr oder weniger):
;WITH x AS
(
SELECT TOP (1000000) Number = ROW_NUMBER() OVER
(ORDER BY s1.[object_id])
FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
ORDER BY s1.[object_id]
)
SELECT Number INTO dbo.Numbers FROM x;
CREATE UNIQUE CLUSTERED INDEX n ON dbo.Numbers(Number);
Dann eine Funktion:
CREATE FUNCTION [dbo].[SplitInts_Numbers]
(
@List NVARCHAR(MAX),
@Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT Item = CONVERT(INT, SUBSTRING(@List, Number,
CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number))
FROM dbo.Numbers
WHERE Number <= CONVERT(INT, LEN(@List))
AND SUBSTRING(@Delimiter + @List, Number, 1) = @Delimiter
);
Hier können Sie die Leistung mit einem iterativen Ansatz vergleichen:
http://sqlfiddle.com/#!3/960d2/1
Um die Zahlentabelle zu vermeiden, können Sie auch eine XML-basierte Version der Funktion ausprobieren - sie ist kompakter, aber weniger effizient:
CREATE FUNCTION [dbo].[SplitInts_XML]
(
@List VARCHAR(MAX),
@Delimiter CHAR(1)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN ( SELECT Item = CONVERT(INT, Item) FROM (
SELECT Item = x.i.value('(./text())[1]', 'int') FROM (
SELECT [XML] = CONVERT(XML, '<i>' + REPLACE(@List, @Delimiter, '</i><i>')
+ '</i>').query('.') ) AS a CROSS APPLY [XML].nodes('i') AS x(i)) AS y
WHERE Item IS NOT NULL
);
Wie auch immer, sobald Sie eine Funktion haben, können Sie einfach sagen:
WHERE ID IN (SELECT Item FROM dbo.SplitInts_Numbers(@MyList, ','));