sql >> データベース >  >> RDS >> Sqlserver

SQL 関数内の IN 句に変数を渡しますか?

    以下は、整数のリストを分割するためのもう少し効率的な方法です。まず、数値表を作成します (まだ作成していない場合)。これにより、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, ','));  

    1. BEFOREINSERTトリガーでIFEXISTS(SELECT ...)を使用する(Oracle)

    2. utl ファイルの名前変更操作に失敗しました

    3. FROMキーワードが予期された場所に見つかりません(Oracle SQL)

    4. PostgreSQLスキーマのテーブルを一覧表示します