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

Tsql 存储过程是否可以在“in”子句中使用动态参数?,tsql,stored-procedures,dynamic-sql,Tsql,Stored Procedures,Dynamic Sql,我想运行如下查询: SELECT * FROM Studio WHERE Id IN (134, 144, 132, 138, 7432, 7543, 2566) 但传递给IN子句的Id量仅在运行时确定 我必须使用动态SQL,还是可以通过存储过程来实现 更新: 如果有两种选择,哪一种更好 谢谢。此处介绍的解决方案: SQLServer2005中的数组和列表 由Erland Sommarskog编写的SQL文本,SQL Server MVP 根据您的Sql Server版本,您可以使用两种不同

我想运行如下查询:

 SELECT * FROM Studio WHERE Id IN (134, 144, 132, 138, 7432, 7543, 2566)
但传递给IN子句的Id量仅在运行时确定

我必须使用动态SQL,还是可以通过存储过程来实现

更新: 如果有两种选择,哪一种更好


谢谢。

此处介绍的解决方案:

SQLServer2005中的数组和列表

由Erland Sommarskog编写的SQL文本,SQL Server MVP


根据您的Sql Server版本,您可以使用两种不同的方法之一来执行此操作

对于Sql 2000/2005,可以使用具有分隔ID列表的参数类型varchar。创建一个UDF,解析varchar并返回一个包含项的表。然后使IN子句与表格相对应,即从@ReturnTable中选择ID

下面是一个UDF内容的示例:

对于Sql 2008,您可以做同样的事情;但是,您不必传入varchar参数,只需转到chase并传入一个表参数即可。IN子句仍然有一个子查询,但它仍然可以工作。或者,一旦有了表,就可以对其进行内部联接,从而避免使用IN子句

编辑:添加了用于解析分隔字符串链接的自定义项。

在SQL 2008中,您可以使用


在SQL2005中,必须使用动态SQL,除非您希望将列表作为XML传递,并在将XML分解回表变量的过程中使用XML处理

声明一个@temp表并将值拆分到其中。那你就可以做了

从Studio的内部联接中选择* @易感结核病
在s.ID=tb.ID上,您完全可以在存储过程中执行此操作

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

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

然后删除该表。

这是自MSSQL 2000以来我一直使用的自定义项。我在某处找到了这个-对不起,不记得在哪里了

基本上,您可以在UDF上执行联接,其中第一个参数是分隔字符串,第二个参数是分隔符

从sometable t1内部联接dbo中选择t1.somecolumn。Split@delimitedVart1.ID=t2.Element上的、'、't2

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

id是由用户输入生成的吗?用户通过复选框选择要搜索的记录,但它们无法控制实际id是什么。如果动态sql不受注入的影响,那么这不是个坏主意……但请尝试我发布的答案,以确保安全。如果复选框的值在执行时未以某种方式进行验证返回到服务器,然后任何人都可以更新复选框的值,以在此处插入假定为web应用程序的值。如果值来自winforms或类似wpf的东西,那么您应该可以。用户检查winform应用程序上的复选框。感谢这些指针,您不需要动态SQL来解析分隔列表。参见Alex提到的Erland Sommarskog的页面。嘿,Remus,我不同意。我在2005年工作,我把数字塞进一个图像,然后用UDF解析它们:是的,我认为字符串处理是一个可行的选择,我应该提到它。因为你的链接不再工作了,我将分享一个这样的链接:如果你使用表值参数,那么使用内部连接而不是IN子句。这可能是最好的解决方案,因为你永远不知道你将有多少糟糕的数据传递到存储过程中。如果数量很大,使用这样的临时表可以显著提高性能。