SQL - 使用IN的Select语句存储过程(@Variable_CommaDelimitedListOfIDS)

时间:2010-04-06 13:08:59

标签: sql sql-server sql-server-2008 stored-procedures

我正在创建一个存储过程,我想将其作为变量传递给逗号分隔的ID列表。我想将Ids用于select语句,例如:

Create Procedure up_TEST
@Ids VARCHAR(MAX)
AS
SELECT * FROM ATable a
WHERE a.Id IN(@Ids)

显然我得到@Ids是varchar而不是INT的错误,但是如何转换逗号分隔列表?

7 个答案:

答案 0 :(得分:4)

由于您使用的是SQL Server 2008,请查看table-valued parameters

答案 1 :(得分:3)

对于这些情况,我使用此表函数,您可以根据自己的需要进行调整:

CREATE FUNCTION dbo.f_params_to_list (@par VARCHAR(500))
returns @result TABLE (value VARCHAR(30))
AS  
begin
     DECLARE @TempList table
          (
          value VARCHAR(30)
          )

     DECLARE @Value varchar(30), @Pos int

     SET @par = LTRIM(RTRIM(@par))+ ','
     SET @Pos = CHARINDEX(',', @par, 1)

     IF REPLACE(@par, ',', '') <> ''
     BEGIN
          WHILE @Pos > 0
          BEGIN
               SET @Value = LTRIM(RTRIM(LEFT(@par, @Pos - 1)))
               IF @Value <> ''
               BEGIN
                    INSERT INTO @TempList (value) VALUES (@Value) --Use Appropriate conversion
               END
               SET @par = RIGHT(@par, LEN(@par) - @Pos)
               SET @Pos = CHARINDEX(',', @par, 1)

          END
     END    
     INSERT @result
     SELECT value 
        FROM @TempList
     RETURN
END    

在您的存储过程中,您可以像这样使用它:

Create Procedure up_TEST
@Ids VARCHAR(MAX)
AS
SELECT * FROM ATable a
WHERE a.Id IN(SELECT value FROM dbo.f_params_to_list(@Ids))

答案 2 :(得分:2)

使用表值参数(SQl Server 2008中的新增功能)。通过创建实际的表参数类型来设置它:

CREATE TYPE IntTableType AS TABLE (ID INTEGER PRIMARY KEY)

您的程序将是:

Create Procedure up_TEST
    @Ids IntTableType READONLY
AS

SELECT * 
    FROM ATable a
    WHERE a.Id IN (SELECT ID FROM @Ids)

RETURN 0
GO

如果您不能使用表值参数,请参阅:"Arrays and Lists in SQL Server 2008 Using Table-Valued Parameters" by Erland Sommarskog ,那么有很多方法可以在SQL Server中拆分字符串。本文涵盖几乎所有方法的PRO和CON:

"Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it" by Erland Sommarskog

您需要创建拆分功能。这就是如何使用拆分功能:

SELECT
    *
    FROM YourTable                               y
    INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value

I prefer the number table approach to split a string in TSQL但是有很多方法可以在SQL Server中拆分字符串,请参阅上一个链接,该链接解释了每个链接的PRO和CON。

要使Numbers Table方法起作用,您需要进行一次性表设置,这将创建一个包含1到10,000行的表Numbers

SELECT TOP 10000 IDENTITY(int,1,1) AS Number
    INTO Numbers
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)

设置Numbers表后,创建此拆分功能:

CREATE FUNCTION [dbo].[FN_ListToTable]
(
     @SplitOn  char(1)      --REQUIRED, the character to split the @List string on
    ,@List     varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN 
(

    ----------------
    --SINGLE QUERY-- --this will not return empty rows
    ----------------
    SELECT
        ListValue
        FROM (SELECT
                  LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
                  FROM (
                           SELECT @SplitOn + @List + @SplitOn AS List2
                       ) AS dt
                      INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
                  WHERE SUBSTRING(List2, number, 1) = @SplitOn
             ) dt2
        WHERE ListValue IS NOT NULL AND ListValue!=''

);
GO 

您现在可以轻松地将CSV字符串拆分为表格并加入其中:

Create Procedure up_TEST
@Ids VARCHAR(MAX)
AS
SELECT * FROM ATable a
WHERE a.Id IN (SELECT ListValue FROM dbo.FN_ListToTable(',',@Ids))

答案 3 :(得分:1)

如果您遇到此问题,请阅读Sommarskog的文章。

http://www.sommarskog.se/index.html

我建议:

  • Sql Server中的数组和列表
  • 动态SQL的诅咒和祝福。

答案 4 :(得分:1)

今天似乎每个人都在做这样的事情!

看一下http://www.sqlteam.com/article/parsing-csv-values-into-multiple-rows - 这是一种处理分隔输入变量的方法,通过连接数字/统计表来提供包含分割项的结果集(这是一个很好的事情。数据库无论如何你还没有)。然后,这会为您提供一个简单的结果集,您可以按照正常情况加入。

答案 5 :(得分:1)

CREATE PROCEDURE PROCEDURENAME
@Id Numeric(18,0)
AS
BEGIN
    SELECT * FROM tableName
    WHERE tableName.Id IN (@Id)
END

答案 6 :(得分:0)

可以拆分一种方法并将id插入临时表,而不是使用SQL IN子句......