2010-12-18 82 views
2

我在IN SQL語句有一個小問題。我只是想知道有人能幫助我嗎?TSQL聲明IN

@Ids = "1,2,3,4,5" 

SELECT * FROM Nav WHERE CONVERT(VARCHAR,NavigationID) IN (CONVERT(VARCHAR,@Ids)) 

這回來了,下面的錯誤,我相信這很簡單!

Conversion failed when converting the varchar value '1,' to data type int. 

回答

4

SQL IN子句不接受單個變量來表示值列表 - 沒有使用動態SQL,數據庫沒有。否則,可以使用use a Table Valued Function(SQL Server 2000+)將值從列表中提取出來。&將它們返回爲您可以加入的表。

動態SQL例如:

EXEC('SELECT * 
     FROM Nav 
     WHERE NavigationID IN ('+ @Ids +')') 

我建議使用SQL Server上的動態SQL之前閱讀The curse and blessings of dynamic SQL

+0

作爲一個側面說明,動態查詢不能很好地處理查詢優化器,但這不是問題。 – 2010-12-18 20:39:14

+1

@PulsarBlow:「處理得好」是模糊的,而且不正確 - 動態和非動態查詢與優化器沒有區別。但是'EXEC'已知不會緩存查詢計劃,而'sp_executesql'確實不會。我建議你閱讀關於動態sql的詛咒和祝福的鏈接。 – 2010-12-18 20:44:21

0

您正在做的事情對於SQL IN語句不可行。您無法將字符串傳遞給它,並期望該字符串被解析。 IN用於特定的硬編碼值。

1

傑森:

首先創建這樣

Create  FUNCTION [dbo].[ftDelimitedAsTable](@dlm char, @string varchar(8000)) 
RETURNS 
--------------------------------------------------------------------------*/ 
/*------------------------------------------------------------------------ 
declare @dlm char, @string varchar(1000) 
set @dlm=','; set @string='t1,t2,t3'; 
-- tHIS FUNCION RETUNRS IN THE ASCENDING ORDER 
-- 19TH Apr 06 
------------------------------------------------------------------------*/ 
--declare 
    @table_var TABLE 
    (id int identity(1,1), 
     r varchar(1000) 
    ) 
AS 
BEGIN 
    declare @n int,@i int 
    set @n=dbo.fnCountChars(@dlm,@string)+1 
    SET @I =1 
    while @I <= @N 
     begin 
      insert @table_var 
       select dbo.fsDelimitedString(@dlm,@string,@i) 
      set @I= @I+1 

     end 
    if @n =1 insert @TABLE_VAR VALUES(@STRING) 
    delete from @table_var where r='' 
    return 
END 

一個函數,然後

set quoted_identifier off 
declare @ids varchar(max) 
select @Ids = "1,2,3,4,5" 
declare @nav table (navigationid int identity(1,1),theother bigint) 
insert @nav(theother) select 10 union select 11 union select 15 
SELECT * FROM @Nav WHERE CONVERT(VARCHAR,NavigationID) IN (select id from dbo.ftDelimitedAsTable(',',@Ids)) 

select * from dbo.ftDelimitedAsTable(',',@Ids) 
+0

+1:對於表值函數示例 – 2010-12-18 20:47:07

0

有兩種方法可以做到你想在這裏做什麼。 一個是創建一個'動態sql'查詢並執行它,代入IN列表後。

DECLARE @query varchar(max); 
SET @query = 'SELECT * FROM Nav WHERE CONVERT(VARCHAR,NavigationID) IN (' + @Ids + ')' 
exec (@query) 

這會產生性能影響和其他併發症。通常我會盡量避免它。

另一種方法是使用用戶定義函數(UDF)將字符串拆分爲其組成部分,然後對其進行查詢。 有一個帖子詳細介紹瞭如何一旦函數存在創建功能here

,是微不足道的加入到它

SELECT * FROM Nav 
CROSS APPLY dbo.StringSplit(@Ids) a 
WHERE a.s = CONVERT(varchar, Nav.NavigationId) 

NB-的「作爲」字段引用基於鏈接的功能,哪些商店名爲's'的列中的拆分值。這可能會因您的字符串分割函數的實現而有所不同

這很好,因爲它使用基於集合的方法查詢而不是IN子查詢,但CROSS JOIN可能有點複雜,所以如果你想保持IN語法,那麼下面的應該工作:

SELECT * FROM Nav 
WHERE Nav.NavigationId IN 
    (SELECT CONVERT(int, a.s) AS Value 
    FROM dbo.StringSplit(@Ids) a