【问题标题】:SQL Server procedure declare a listSQL Server 过程声明一个列表
【发布时间】: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 sql-server sql-server-2008-r2


【解决方案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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-05
        • 2012-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多