Zde je o něco efektivnější způsob, jak rozdělit seznam celých čísel. Nejprve vytvořte číselnou tabulku, pokud ji ještě nemáte. Tím vytvoříte tabulku se 100 000 jedinečnými celými čísly (možná budete potřebovat více nebo méně):
;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);
Poté funkce:
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
);
Výkon můžete porovnat s iterativním přístupem zde:
http://sqlfiddle.com/#!3/960d2/1
Chcete-li se vyhnout tabulce čísel, můžete také vyzkoušet verzi funkce založenou na XML – je kompaktnější, ale méně efektivní:
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
);
Každopádně jakmile máte funkci, můžete jednoduše říct:
WHERE ID IN (SELECT Item FROM dbo.SplitInts_Numbers(@MyList, ','));