2010-12-18 12 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を使用せずにデータベースのない値のリストを表す1つの変数を受け入れません。それ以外の場合は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

動的問合せは問合せオプティマイザでうまく処理されませんが、それは問題ではありませんでした。 –

+1

@PulsarBlow:「よく扱われる」は曖昧で、間違っています - オプティマイザに対する動的クエリと非動的クエリの間に違いはありません。しかし、 'EXEC'はクエリプランをキャッシュしないことが知られていますが、' sp_executesql'はクエリプランをキャッシュしません。私はあなたが動的SQLの呪いと祝福についてのリンクを読むことをお勧めします。 –

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:テーブル値関数の例 –

0

ようにあなたがここで何をしたいのかには2つの方法があります関数を作成します。 1つは、動的リストの代わりに '動的SQL'クエリを作成して実行することです。

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

これは、パフォーマンスの影響やその他の問題を引き起こす可能性があります。一般的に私はそれを避けようとします。

もう1つの方法は、ユーザー定義関数(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 
関連する問題