6

我有以下代码,问题是我的变量列表@LocationList 本质上是一个csv字符串。当我在 (@LocationList) 中将它用作 where LocationID 的一部分时,它说它不是 int (LocationID 是 int)。如何让这个 csv 字符串被 in 子句接受?

Declare @LocationList varchar(1000)
Set @LocationList = '1,32'

select Locations from table where Where LocationID in (@LocationList)
4

3 回答 3

7

最有效的方法是使用动态 SQL,例如 rt2800 提及(Michael Allen 的注入警告)

但是,您可以创建一个函数:

ALTER  FUNCTION [dbo].[CSVStringsToTable_fn] ( @array VARCHAR(8000) )
RETURNS @Table TABLE ( value VARCHAR(100) )
AS 
    BEGIN
        DECLARE @separator_position INTEGER,
            @array_value VARCHAR(8000)  

        SET @array = @array + ','

        WHILE PATINDEX('%,%', @array) <> 0 
            BEGIN
                SELECT  @separator_position = PATINDEX('%,%', @array)
                SELECT  @array_value = LEFT(@array, @separator_position - 1)

                INSERT  @Table
                VALUES  ( @array_value )

                SELECT  @array = STUFF(@array, 1, @separator_position, '')
            END
        RETURN
    END

并从中选择:

DECLARE @LocationList VARCHAR(1000)
SET @LocationList = '1,32'

SELECT  Locations 
FROM    table
WHERE   LocationID IN ( SELECT   *
                           FROM     dbo.CSVStringsToTable_fn(@LocationList) )

或者

SELECT  Locations
FROM    table loc
        INNER JOIN dbo.CSVStringsToTable_fn(@LocationList) list
            ON list.value = loc.LocationID

当您尝试将多值列表从 SSRS 发送到 PROC 时,这非常有用。

于 2012-04-26T12:38:43.600 回答
1

我经常有这个要求,有时,如果您非常了解要搜索的列[大小/格式/长度],您可以做一种正则表达式。

像这样的东西:

  DECLARE @MyListOfLocation varchar(255)
  set @MyListOfLocation  = '|1|32|36|24|3|'

  Select LocationID 
  from  Table 
  where @MyListOfLocation like '%|' +  LocationID + '|%'

注意:PIPE 字符用于保护查询不返回任何包含单个字符(例如“1”)的 LocationID。

这是一个完整的工作示例:

DECLARE @MyListOfLocation varchar(255)
set @MyListOfLocation  = '|1|11|21|'

SELECT LocationName
FROM (
        select '1' as LocationID, 'My Location 1' as LocationName
        union all
        select '11' as LocationID, 'My Location 11' as LocationName
        union all
        select '12' as LocationID, 'My Location 12' as LocationName
        union all
        select '13' as LocationID, 'My Location 13' as LocationName
        union all
        select '21' as LocationID, 'My Location 21' as LocationName
    ) as MySub
where @MyListOfLocation like '%|' + LocationID + '|%'

警告!这种方法对索引不友好!

如果您想在所有这些中添加一些 IN(@MyListOfLocation) 以利用 INDEXES,您可以将脚本修改为:

SELECT MyDATA.* 
FROM   HugeTableWithAnIndexOnLocationID as MyDATA 
WHERE  LocationID in (
      Select LocationID 
      from  Table 
      where @MyListOfLocation like '%|' +  LocationID + '|%')
于 2014-06-12T15:49:26.363 回答
0
declare @querytext Nvarchar(MAX)

set @querytext = 'select Locations from table where Where LocationID in (' + @LocationList + ');';

exec sp_executesql @querytext;
于 2012-04-26T12:30:55.883 回答