2011-03-01 89 views
0

我有一个存储过程存储过程 - 执行查询与NOT IN where子句

Create PROCEDURE abc  
    @sRemovePreviouslySelectedWhereClause nvarchar(max) 
AS 
BEGIN 

SELECT * 
     FROM table 
    WHERE nId NOT IN (@sRemovePreviouslySelectedWhereClause) 

END; 

参数@sRemovePreviouslySelectedWhereClause可以具有像0,1的值。但是,这会失败并显示错误消息:

将nvarchar值'0,1'转换为数据类型为int时转换失败。

除动态查询之外,还有其他方法可以实现吗?

+1

没有被我所知道的任何供应商支持的SQL它支持使用变量为IN/NOT IN子句提供逗号分隔列表。使用动态SQL,或将值列表转换为表值函数/等进行比较。 – 2011-03-01 06:07:15

+0

[SQL Server SP - 传递参数为“IN”数组列表?]的可能的重复(http://stackoverflow.com/questions/537087/sql-server-sp-pass-parameter-for-in-array-list) – onedaywhen 2011-03-01 08:16:35

+0

这是最常见的问题之一。你会发现许多重复(或非常接近的问题)。 – onedaywhen 2011-03-01 08:17:31

回答

0

您必须将@sRemovePreviouslySelectedWhereClause参数拆分为','并将结果值放入临时表中。然后您的选择看起来像

select * from table where nId not in (select nId from #tempIds) 
+0

我不明白为什么这是downvoted ... – 2011-03-01 08:48:01

-1

您将需要使用动态sql进行此类查询。

第一构造查询和

SET @sql = 'select * from table 
where nId not in (' + @sRemovePreviouslySelectedWhereClause+ ')' 

然后使用EXEC(@sql)运行查询。

+0

这恰恰是_not_使用动态sql的地方。你不只是像这样连接sql ...这是危险的,并受sql注入。看到我上面的解决方案动态sql最适合用于参数化的时尚ala'sp_executesql'。不过,我没有投票给你。 – canon 2011-03-01 22:48:58

0

您尝试的这种方法不起作用。但是,如果您使用SQL Server 2008,则可以使用名为Table Valued Parameters的新功能。

基本上,创建用户定义的表型

CREATE TYPE dbo.nIdTable AS TABLE(nID INT) 

并且可以在多个值从外面然后传递在于TVP(例如,从ADO.NET或例如):

CREATE PROCEDURE abc(@idValues dbo.nIdTable READONLY) 

和使用您的存储过程内部的表变量:

SELECT * 
FROM table 
WHERE nId NOT IN (SELECT nID FROM @idValues) 
+0

似乎有人已经低估了包括问题本身在内的所有答案。 – 2011-03-01 09:18:21

1
Create FUNCTION [dbo].[fn_Split] ( 
@List nvarchar(2000), @SplitOn nvarchar(5) 
) 
RETURNS @RtnValue table ( 
    Value nvarchar(100)) 
AS 
BEGIN 
While (Charindex(@SplitOn,@List)>0) 
Begin 
Insert Into @RtnValue (value) 
Select Value = ltrim(rtrim(Substring(@List,1,Charindex(@SplitOn,@List)-1))) 
Set @List = Substring(@List,Charindex(@SplitOn,@List)+len(@SplitOn),len(@List)) 
End 
Insert Into @RtnValue (Value) 
    Select Value = ltrim(rtrim(@List)) 

    Return 
END 

********** 
Create PROCEDURE abc  
    @sRemovePreviouslySelectedWhereClause nvarchar(max) 
AS 
BEGIN 

SELECT * 
     FROM Table 
    WHERE nId NOT IN (select * from dbo.fn_Split(@sRemovePreviouslySelectedWhereClause,',')) 

END; 
2

首先,创建分割功能,将您的分隔字符串转换成表格:

CREATE FUNCTION [dbo].[Split] 
( 
@String varchar(max) 
,@Delimiter char 
) 
RETURNS @Results table 
(
Ordinal int 
,StringValue varchar(max) 
) 
as 
begin 

    set @String = isnull(@String,'') 
    set @Delimiter = isnull(@Delimiter,'') 

    declare 
    @TempString varchar(max) = @String 
    ,@Ordinal int = 0 
    ,@CharIndex int = 0 

    set @CharIndex = charindex(@Delimiter, @TempString) 
    while @CharIndex != 0 begin  
     set @Ordinal += 1  
     insert @Results values 
     (
     @Ordinal 
     ,substring(@TempString, 0, @CharIndex) 
     )  
     set @TempString = substring(@TempString, @CharIndex + 1, len(@TempString) - @CharIndex)  
     set @CharIndex = charindex(@Delimiter, @TempString) 
    end 

    if @TempString != '' begin 
     set @Ordinal += 1 
     insert @Results values 
     (
     @Ordinal 
     ,@TempString 
     ) 
    end 

    return 
end 

然后改变你的where子句如下:

select 
t.* 
from [yourTable] t 
where t.[ID] not in (select cast([StringValue] as int) from dbo.Split(@sRemovePreviouslySelectedWhereClause,','))