SQL Server 过程声明一个列表

Posted

技术标签:

【中文标题】SQL Server 过程声明一个列表【英文标题】:SQL Server procedure declare a list 【发布时间】:2014-01-16 11:25:37 【问题描述】:

我的 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

【问题讨论】:

你使用的是哪个 sql server 版本? 我正在使用 Microsoft SQL Server 2008 R2 ***.com/questions/6369/…的可能重复 ^不相关的 IMO,尽管肯定存在重复。 mysql but might be helpful 【参考方案1】:

您可以像这样将变量声明为临时表:

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

【讨论】:

谢谢!我最后使用了你的解决方案:)【参考方案2】:

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

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

【讨论】:

谢谢!我正要问你如何正确声明它!我试试这个。【参考方案3】:

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

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

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

【讨论】:

【参考方案4】:

我一直发现在这种情况下,根据列表反转测试更容易。比如……

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) + ',%'

【讨论】:

【参考方案5】:

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

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 TableTypeTemp table 喜欢:INSERT using LIST into Stored Procedure

【讨论】:

这适用于所有类型吗?您不需要将函数的输出转换为INT吗? @Westie,比较的类型必须相同。因此,如果 dbtable 中的 id 是 int 类型,那么是的,它需要强制转换。【参考方案6】:

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

【讨论】:

以上是关于SQL Server 过程声明一个列表的主要内容,如果未能解决你的问题,请参考以下文章

在SQL Server存储过程中声明变量列表

如何在 SQL Server 存储过程/函数中声明输入输出参数?

SQL server简单的存储过程问题?

如何从 SQL Server 中的存储过程中检索参数列表

如何将数组传递到 SQL Server 存储过程

如何在SQL Server存储过程/函数中声明输入输出参数?