SQL Server过程声明一个列表

问题描述 投票:32回答:6

我的SQL代码非常简单。我正在尝试从数据库中选择一些数据,如下所示:

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

我想知道如何在select之前声明列表(在变量,列表,数组或其他东西中),而select中只使用变量名,如下所示:

VAR myList = "(1,2,5,7,10)"
SELECT * FROM DBTable
WHERE id IN myList
sql sql-server sql-server-2008-r2
6个回答
56
投票

您可以将变量声明为临时表,如下所示:

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

如果你做了很多这样的事情,那么你可以考虑定义一个user-defined table type,这样你就可以像这样声明你的变量:

declare @myList dbo.MyTableType

8
投票

这对于普通查询是不可能的,因为in子句需要单独的值而不是包含逗号分隔列表的单个值。一种解决方案是动态查询

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

1
投票

如果你想输入逗号分隔的字符串作为输入并在查询中应用,那么你可以使函数像:

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 variableTableTypeTemp table像:INSERT using LIST into Stored Procedure


1
投票

在这种情况下,我总是发现在列表中反转测试更容易。例如...

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

这意味着您正在寻找的值不需要复杂的混搭。

举个例子,如果我们的列表是('1,2,3'),那么我们在列表的开头和结尾添加一个逗号,如下所示:',' + @mysearchlist + ','

我们也为我们正在寻找的字段值做同样的事情并添加通配符:'%,' + CAST(field3 AS VARCHAR) + ',%'(注意%,字符)。

最后,我们使用LIKE运算符测试这两个:',' + @mysearchlist + ',' LIKE '%,' + CAST(field3 AS VARCHAR) + ',%'


1
投票

@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);

0
投票

您可以将传递的值列表转换为表值参数,然后针对此列表进行选择

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来选择它。

如果您打算重用此功能,可以进一步将其转换为函数。

© www.soinside.com 2019 - 2024. All rights reserved.