以下は、整数のリストを分割するためのもう少し効率的な方法です。まず、数値表を作成します (まだ作成していない場合)。これにより、100,000 個の一意の整数を含むテーブルが作成されます (これより多い場合も少ない場合もあります):
;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);
プレ>次に関数:
CREATE FUNCTION [dbo].[SplitInts_Numbers]( @List NVARCHAR(MAX), @Delimiter NVARCHAR(255))RETURNS TABLEWITH SCHEMABINDINGAS 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 );コード> プレ>
ここでパフォーマンスを反復アプローチと比較できます:
http://sqlfiddle.com/#!3/960d2/1
数値テーブルを避けるために、関数の XML ベース バージョンを試すこともできます。これはよりコンパクトですが、効率は低くなります。
CREATE FUNCTION [dbo].[SplitInts_XML]( @List VARCHAR(MAX), @Delimiter CHAR(1))RETURNS TABLEWITH SCHEMABINDINGAS RETURN ( SELECT Item =CONVERT(INT, Item) FROM ( SELECT Item =x.i. value('(./text())[1]', 'int') FROM ( SELECT [XML] =CONVERT(XML, '' + REPLACE(@List, @Delimiter, '<) i>') + '').query('.') ) AS a CROSS APPLY [XML].nodes('i') AS x(i)) AS y WHERE Item IS NOT NULL );コード> プレ>
とにかく、関数ができたら、次のように簡単に言うことができます:
WHERE ID IN (SELECT Item FROM dbo.SplitInts_Numbers(@MyList, ','));
プレ>