存储过程是否可以在“IN”子句中使用动态参数?

时间:2009-06-10 17:24:47

标签: tsql stored-procedures dynamic-sql

我想运行这样的查询:

 SELECT * FROM Studio WHERE Id IN (134, 144, 132, 138, 7432, 7543, 2566)

但传递给IN子句的 Id 的数量仅在运行时确定。

我是否必须使用动态SQL,还是可以使用存储过程来完成?

更新 如果有可用的选项,哪一个更好?

感谢。

6 个答案:

答案 0 :(得分:8)

根据您的Sql Server版本,您可以采用以下两种方式之一。

对于Sql 2000/2005,您可以使用具有ID分隔列表的参数(类型varchar)。创建一个UDF,它将解析varchar并返回包含这些项的表。然后让你的IN子句反对表(即...... IN(选择ID FROM @ReturnTable))。

以下是UDF内容的示例: http://pietschsoft.com/post/2006/02/03/T-SQL-Parse-a-delimited-string.aspx

对于Sql 2008,你可以做同样的事情;但是,不是传入varchar参数,而是可以切换到追逐并传入Table参数。 IN子句仍然有一个子查询,但它可以完全相同。或者,一旦你有了表,你就可以对它进行内连接,并避免对IN子句的需要。

编辑:添加UDF以解析分隔的字符串链接。

答案 1 :(得分:5)

此处描述的解决方案:

SQL Server 2005中的数组和列表

Erland Sommarskog的SQL文本,SQL Server MVP

http://www.sommarskog.se/arrays-in-sql-2005.html

答案 2 :(得分:3)

您绝对可以在存储过程中执行此操作。

在存储过程中创建临时表,并在逗号或任何分隔符上插入拆分值,然后执行此操作

SELECT * FROM Studio WHERE Id IN (select id from temptable)

然后删除表格。

答案 3 :(得分:1)

这是我自MSSQL 2000以来一直使用的UDF。我在某个地方找到了这个 - 抱歉,不记得在哪里。

基本上,你可以在UDF上进行连接,其中第一个参数是分隔字符串,第二个参数是分隔符。

SELECT t1.somecolumn FROM sometable t1 INNER JOIN dbo.Split(@ delimitedVar,',')t2 ON t1.ID = t2.Element

CREATE FUNCTION [dbo].[Split]
(
@vcDelimitedString varchar(max),
@vcDelimiter varchar(100)
)
RETURNS @tblArray TABLE
   (
    ElementID smallint  IDENTITY(1,1), --Array index
    Element varchar(1000) --Array element contents
   )
AS
BEGIN
    DECLARE @siIndex smallint, @siStart smallint, @siDelSize smallint
    SET @siDelSize  = LEN(@vcDelimiter)
    --loop through source string and add elements to destination table array
    WHILE LEN(@vcDelimitedString) > 0
    BEGIN
        SET @siIndex = CHARINDEX(@vcDelimiter, @vcDelimitedString)
        IF @siIndex = 0
        BEGIN
            INSERT INTO @tblArray VALUES(@vcDelimitedString)
            BREAK
        END
        ELSE
        BEGIN
            INSERT INTO @tblArray VALUES(SUBSTRING(@vcDelimitedString, 1,@siIndex - 1))
            SET @siStart = @siIndex + @siDelSize
            SET @vcDelimitedString = SUBSTRING(@vcDelimitedString, @siStart , LEN(@vcDelimitedString) - @siStart + 1)
        END
    END
    RETURN
END

答案 4 :(得分:0)

在SQL 2008中,您可以使用table valued parameter

在SQL 2005中,除非要将列表作为XML传递并在过程中使用XML处理将XML重新分解为表变量,否则必须使用动态SQL。

答案 5 :(得分:0)

声明一个@temp表并将值拆分为它。那么你可以做到

从Studio的内连接中选择* @temptable tb 在s.ID = tb.ID