2011-03-01 79 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,','))