我有一个SQL Server存储过程,我想在其中将一个varchar完整的逗号分隔值传递给一个IN函数。例如:
varchar
IN
DECLARE @Ids varchar(50); SET @Ids = '1,2,3,5,4,6,7,98,234'; SELECT * FROM sometable WHERE tableid IN (@Ids);
当然这是行不通的。我得到了错误:
将varchar值‘1,2,3,5,4,6,7,98,234’转换为数据类型int时转换失败。
如何在不借助动态SQL的情况下完成此任务(或相对类似的任务)?
不要使用循环拆分字符串的函数! ,我下面的函数将非常快速地拆分字符串,而且不会循环!
在使用我的函数之前,您需要设置一个“帮助器”表,每个数据库只需要执行一次此操作:
CREATE TABLE Numbers (Number int NOT NULL, CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] DECLARE @x int SET @x=0 WHILE @x<8000 BEGIN SET @x=@x+1 INSERT INTO Numbers VALUES (@x) END
使用此函数来拆分您的字符串,该字符串不会循环并且非常快:
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 @ParsedList table ( ListValue varchar(500) ) AS BEGIN /** Takes the given @List string and splits it apart based on the given @SplitOn character. A table is returned, one row per split item, with a column name "ListValue". This function workes for fixed or variable lenght items. Empty and null items will not be included in the results set. Returns a table, one row per item in the list, with a column name "ListValue" EXAMPLE: ---------- SELECT * FROM dbo.FN_ListToTable(',','1,12,123,1234,54321,6,A,*,|||,,,,B') returns: ListValue ----------- 1 12 123 1234 54321 6 A * ||| B (10 row(s) affected) **/ ---------------- --SINGLE QUERY-- --this will not return empty rows ---------------- INSERT INTO @ParsedList (ListValue) 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!='' RETURN END --Function FN_ListToTable
您可以将此函数用作联接中的表:
SELECT Col1, COl2, Col3... FROM YourTable INNER JOIN FN_ListToTable(',',@YourString) s ON YourTable.ID = s.ListValue
这是您的示例:
Select * from sometable where tableid in(SELECT ListValue FROM dbo.FN_ListToTable(',',@Ids) s)