我想运行这样的查询:
SELECT * FROM Studio WHERE Id IN (134, 144, 132, 138, 7432, 7543, 2566)
但传递给IN子句的 Id 的数量仅在运行时确定。
我是否必须使用动态SQL,还是可以使用存储过程来完成?
更新 如果有可用的选项,哪一个更好?
感谢。
答案 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
答案 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