web-dev-qa-db-ja.com

SQL Serverプロシージャはリストを宣言します

私のSQLコードはかなり単純です。私はこのようなデータベースからいくつかのデータを選択しようとしています:

SELECT * FROM DBTable
WHERE id IN (1,2,5,7,10)

選択の前に(変数、リスト、配列などで)リストを宣言し、選択内では次のような変数名のみを使用する方法を知りたい:

VAR myList = "(1,2,5,7,10)"
SELECT * FROM DBTable
WHERE id IN myList
34
Alex Doro

次のように変数を一時テーブルとして宣言できます。

declare @myList table (Id int)

つまり、insertステートメントを使用して値を設定できます。

insert into @myList values (1), (2), (5), (7), (10)

次に、selectステートメントでinステートメントを使用できます。

select * from DBTable
where id in (select Id from @myList)

または、次のように一時テーブルに参加できます。

select *
from DBTable d
join @myList t on t.Id = d.Id

そして、あなたがこのようなことをたくさんするなら、 ser-defined table type を定義することを検討することができます。それで、次のように変数を宣言できます:

declare @myList dbo.MyTableType
60
Peter Monks

in句には個別の値が必要であり、カンマ区切りリストを含む単一の値ではないため、通常のクエリでは不可能です。 1つの解決策は動的クエリです

declare @myList varchar(100)
set @myList = '(1,2,5,7,10)'
exec('select * from DBTable where id IN ' + @myList)
9
juergen d

入力としてカンマ区切りの文字列を入力し、そのクエリに適用する場合は、次のような関数を作成できます:

create FUNCTION [dbo].[Split](@String varchar(MAX), @Delimiter char(1))       
    returns @temptable TABLE (items varchar(MAX))       
    as       
    begin      
        declare @idx int       
        declare @slice varchar(8000)       

        select @idx = 1       
            if len(@String)<1 or @String is null  return       

        while @idx!= 0       
        begin       
            set @idx = charindex(@Delimiter,@String)       
            if @idx!=0       
                set @slice = left(@String,@idx - 1)       
            else       
                set @slice = @String       

            if(len(@slice)>0)  
                insert into @temptable(Items) values(@slice)       

            set @String = right(@String,len(@String) - @idx)       
            if len(@String) = 0 break       
        end   
    return 
    end;

次のように使用できます:

Declare @Values VARCHAR(MAX);

set @Values ='1,2,5,7,10';
Select * from DBTable
    Where id  in (select items from [dbo].[Split] (@Values, ',') )

または、入力としてコンマ区切りの文字列がない場合は、Table variable OR TableTypeまたはTemp table like: LISTを使用してストアドプロシージャに挿入

1
Pranav Singh

このような状況では、リストに対してテストを逆にする方が簡単であることが常にわかっています。例えば...

_SELECT 
    field0, field1, field2 
FROM 
    my_table 
WHERE 
    ',' + @mysearchlist + ',' LIKE '%,' + CAST(field3 AS VARCHAR) + ',%' 
_

つまり、探している値に複雑なミッシュマッシュは必要ありません。

例として、リストが_('1,2,3')_の場合、リストの最初と最後にカンマを追加します:_',' + @mysearchlist + ','_。

探しているフィールド値にも同じことを行い、ワイルドカードを追加します:'%,' + CAST(field3 AS VARCHAR) + ',%'(_%_および_,_文字に注意してください)。

最後に、LIKE演算子を使用して2つをテストします:',' + @mysearchlist + ',' LIKE '%,' + CAST(field3 AS VARCHAR) + ',%'

1
Paul

@Peter Monksの代替。

「in」ステートメントの数値が小さく、固定されている場合。

DECLARE @var1 varchar(30), @var2 varchar(30), @var3  varchar(30);

SET @var1 = 'james';
SET @var2 = 'same';
SET @var3 = 'dogcat';

Select * FROM Database Where x in (@var1,@var2,@var3);
1
Aaron C

渡された値のリストをテーブル値パラメーターに変換し、このリストに対して選択できます

DECLARE @list NVARCHAR(MAX)
SET @list = '1,2,5,7,10';

DECLARE @pos INT
DECLARE @nextpos INT
DECLARE @valuelen INT
DECLARE @tbl TABLE (number int NOT NULL)

SELECT @pos = 0, @nextpos = 1;

WHILE @nextpos > 0
BEGIN
    SELECT @nextpos = charindex(',', @list, @pos + 1)
    SELECT @valuelen = CASE WHEN @nextpos > 0
                            THEN @nextpos
                            ELSE len(@list) + 1
                        END - @pos - 1
    INSERT @tbl (number)
        VALUES (convert(int, substring(@list, @pos + 1, @valuelen)))
    SELECT @pos = @nextpos;
END

SELECT * FROM DBTable WHERE id IN (SELECT number FROM @tbl);

この例では、'1,2,5,7,10'で渡された文字列がコンマで分割され、各値が@tblテーブル変数内の新しい行として追加されます。これは、標準SQLの使用に対して選択できます。

この機能を再利用する場合は、さらに進んでこれを関数に変換できます。

0
Jonathan