2009-05-17 14 views
1

"1,3,16、..、.."のように、関数の出力である文字列があります。SQLのCharindexで目的の結果が得られません

次のSQLクエリを使用してVisual Studioのクエリビルダーで実行しましたが、構文エラーが発生しませんでした。

SELECT ItemID, Name, RelDate, Price, Status FROM item_k WHERE (ItemID = cast(charindex(',', @itemIDs) as int)) 

@itemIDパラメータ値として3,16を指定しましたが、目的の結果が得られませんでした。

その後、私は(CHARINDEXなし)次のSQLクエリを使用:

SELECT ItemID, Name, RelDate, Price, Status FROM item_k WHERE (ItemID = @itemIDs) 

私は@itemIDパラメータ値として3を与えた、と私はそれのために結果を得ました。 また、@itemIDパラメータ値として16を(別の機会に)与えました。結果は得られました。私はItemID 3の値があると結論します。& 16.

なぜcharindexのSQLクエリで結果が得られないのですか?

ここで問題を把握できないようです。助けてください。

答えて

1

CHARINDEXは、文字列内で文字が見つかった位置を返します。

そう@ItemIDsが...その後'3,16'あなたWHERE句に

WHERE (ItemID = CAST(CHARINDEX(',', @ItemIDs) AS INT)) 

に設定されている場合... ... ...

WHERE ItemID = 2 

と同等であるため、CHARINDEX戻り2理由コンマ文字は文字列'3,16'の位置2にあります。

私はItemID2です(a)のあなたがテーブルの行を持っていない、と(b)はあなたが本当にコンマの位置がどの行を指示したくないことを推測しています返されます。

+0

(A)私はアイテムIDは、私は、クエリは私にレコードを取得したい2. (b)は、レコードを持っていけません。 注:@ItemIDには、毎回「3,16」ではなく異なる値を含めることができます。 これをどうすれば実現できますか? ありがとう – pier

0

アイテムIDが(@itemIDs)

+0

hmm。私はパラメータとして1つの値を与える場合に動作します。パラメータとして「3,12」を入力すると、タイプの不一致が発生します。 – pier

1

にあなたはそれがinオペレータ使用する動的クエリを作成することができますitem_k FROM SELECTアイテムID、名前、RelDate、価格、ステータスを試してみてください。

declare @Sql varchar(1000) 
set @Sql = 'select ItemID, Name, RelDate, Price, Status from item_k where ItemID in (' + @itemIDs + ')' 
exec(@Sql) 

は注意が必要ですがあなたが手続きに送るものと一緒に。動的SQLの場合と同様に、データが検証なしでユーザー入力から得られた場合、プロシージャはSQLインジェクションのために広く開かれています。

編集:
これは、クエリで何が起こるかです:

まず我々は、動的クエリを保持する変数を宣言します。これは、十分に大きい変数varcharです。

変数には、@itemIDs変数を2つの文字列の間に入れてクエリを構成します。カンマ区切りの値は、オペレータのかっこの間に置かれ、次のような式を構成します。where ItemID in (1,3,16)

最後にexecコマンドが変数でクエリを実行します。

+0

あなたはplsです。このクエリで何が起こったのかを説明してください。 – pier

+0

私は上記の説明を追加しました。 – Guffa

3

もう1つの解決策があります。私の経験上、コンマで区切られた値の文字列としてItemIdsのリストがあるときは、分割関数が必要です。これは非常に便利です。これが最初で、複雑に見えるかもしれないが

DECLARE @ItemIDs varchar(100) 
SET @ItemIDs = '1,3,16,22,34,35' 

SELECT 
    ItemID, Name, RelDate, Price, Status 
FROM item_k 
    INNER JOIN dbo.UTILfn_Split(@ItemIDs,',') itemIds 
     ON itemIds.Value = item_k.ItemID 

:スプリット機能付き

、あなたは単にINNERは、split関数を呼び出すと、次のようにアイテムIDと関連付けられている区切り文字のリストを渡すの結果とJOINを行うことができそれはよりエレガントで維持しやすいソリューションです。 dbo.UTILfn_Split機能を作成するためのコードは次のとおりです。あなたが最初にこれを実行する必要があります。

IF EXISTS (SELECT * FROM sysobjects WHERE id = 
object_id(N'[dbo].[UTILfn_Split]') AND xtype IN (N'FN', N'IF', N'TF')) 
DROP FUNCTION [dbo].[UTILfn_Split] 
GO 

CREATE FUNCTION dbo.UTILfn_Split 
(
    @String nvarchar (4000), 
    @Delimiter nvarchar (10) 
) 
RETURNS @ValueTable TABLE ([Value] nvarchar(4000)) 
BEGIN 
DECLARE @NextString nvarchar(4000) 
DECLARE @Pos int 
DECLARE @NextPos int 
DECLARE @CommaCheck nvarchar(1) 

--Initialize 
SET @NextString = '' 
SET @CommaCheck = RIGHT(@String,1) 
--Check for trailing Comma, if not exists, INSERT 
--if (@CommaCheck <> @Delimiter) 
SET @String = @String + @Delimiter 

--Get position of first Comma 
SET @Pos = CHARINDEX(@Delimiter,@String) 
SET @NextPos = 1 

--Loop while there is still a comma in the String of levels 
WHILE (@pos <> 0) 
BEGIN 
    SET @NextString = SUBSTRING(@String,1,@Pos - 1) 

    INSERT INTO @ValueTable ([Value]) Values (@NextString) 

    SET @String = SUBSTRING(@String,@pos +1,LEN(@String)) 

    SET @NextPos = @Pos 
    SET @pos = CHARINDEX(@Delimiter,@String) 
END 
RETURN 
END 
関連する問題