2016-04-08 10 views
10

これは簡単な質問ですが、私は解決策を考えることができません。SQLストアドプロシージャLIKE

私は、この私のストアドプロシージャで定義されています:

@communityDesc varchar(255) = NULL 

@communityDescは "AAA、BBB、CCC"

と私はIN

WHERE AREA IN (@communityDesc) 
を使用しようとしています私の実際のクエリであります

しかし、この "aaa"、 "bbb"、 "ccc"の代わりにコンマが文字列の内側にあるため、これは機能しません

私の質問は、私が@communityDescにできることはありますか?それでは、文字列を再フォーマットするのと同じように、私のIN文でうまくいくでしょうか?

+0

これをSQLで実行しているのですか、または[テーブル値のパラメータ](https://msdn.microsoft.com/en-us/library/bb675163.aspx)を追加して複製しようとしていますか? –

+4

どのDBMSを使用していますか? –

+0

** [SQL IN句をパラメータ化する](http://stackoverflow.com/questions/337704/parameterize-an-sql-in-clause)** – lad2025

答えて

2

最初にあなたが最も、あなたは、この機能を使用することができます。このコードのように分割した文字列に

CREATE FUNCTION dbo.splitstring (@stringToSplit VARCHAR(MAX)) 
RETURNS 
@returnList TABLE ([Name] [nvarchar] (500)) 
AS 
BEGIN 

DECLARE @name NVARCHAR(255) 
DECLARE @pos INT 

WHILE CHARINDEX(',', @stringToSplit) > 0 
BEGIN 
    SELECT @pos = CHARINDEX(',', @stringToSplit) 
    SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1) 

    INSERT INTO @returnList 
    SELECT @name 

    SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)[email protected]) 
END 

INSERT INTO @returnList 
SELECT @stringToSplit 

RETURN 
END 

をいくつかのことを関数を作成し、この

WHERE AREA IN (dbo.splitstring(@communityDesc)) 
+0

これは、インラインテーブル値関数、マルチステートメントテーブル値関数またはスカラー値関数ですか? – user979331

+0

私はこの関数を作成しましたが、このエラーが発生しました。 'splitstring'は認識された組み込み関数名ではありません。 – user979331

2

hereの分割機能を使用して文字列を分割することで、これを行うことができます。この関数は、トークンを保持する単一の列(つまり、 'aaa'、 'bbb' ...)を持つ表を返します。

あなたのクエリは次のようになります。

-- get the splits 
SELECT Name INTO #someTemp 
FROM dbo.splitstring(@communityDesc) 

-- get data where area in within description 
SELECT 1 
FROM yourTable T 
WHERE EXISTS (SELECT 1 FROM #someTemp tmp WHERE T.Area = tmp.Name) 
+0

無効な列名 '名前'と無効なオブジェクトの2つのエラーが表示されますname 'dbo.splitstring' – user979331

+0

データベースに関数を持たせるには、提供されたリンクから 'dbo.splitstring'関数を実行してください。 – Alexei

3

Inだけではない文字列の文字を、値のセットで動作します。あなたの質問に技術的に答えるには、3つの値 'aaa'、 'bbb' & 'ccc'を表す一連の値を作成し、それら3つの値をテーブル(Temp TableまたはTable (SQL Serverの)変数、その後、テーブルに対する値のセット(抗して実行しますが、この値のセットを保持するために、空の一時テーブルまたはテーブル変数を作成する必要がありますセットを作成するには

declare @Vals table (value varchar(20)) 
insert @vals(Value) Values('aaa') 
insert @vals(Value) Values('bbb') 
insert @vals(Value) Values('ccc') 

select * from SomeOtherTable 
Where SomeColumn IN (Select value from @vals) 

コンマで区切られた文字列を個々の値に解析し、それらの個々の値を一時テーブルまたはテーブル変数に入力します。

SQL Serverを使用している場合、SQL Server ER区切られた文字列を解析し、各delimted値ごとに1行を持つテーブルを返します定義関数(UDF):あなたはUDFを作成する場合は、次のよう

は、その後、あなたがそれを使用します。

select * from SomeOtherTable 
Where SomeColumn IN 
     (Select sVal from 
      dbo.ParseSTring(@communityDesc, ',')) 

/****** Object: UserDefinedFunction [dbo].[ParseString]  
    Script Date:  4/8/2016 1:53:00 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER FUNCTION [dbo].[ParseString] (@S Text, @delim VarChar(5)) 
Returns @tOut Table 
(ValNum Integer Identity Primary Key, 
sVal VarChar(8000)) 
As 
Begin 
Declare @dLLen TinyInt -- Length of delimiter 
Declare @sWin VarChar(8000)-- Will Contain Window into text string 
Declare @wLen Integer -- Length of Window 
Declare @wLast TinyInt -- Boolean to indicate processing Last Window 
Declare @wPos Integer -- Start Position of Window within Text String 
Declare @sVal VarChar(8000)-- String Data to insert into output Table 
Declare @BtchSiz Integer -- Maximum Size of Window 
Set @BtchSiz = 7900 -- (Reset to smaller values to test routine) 
Declare @dPos Integer -- Position within Window of next Delimiter 
Declare @Strt Integer -- Start Position of each data value in Window 
-- -------------------------------------------------------------- 

-- --------------------------- 
If @delim is Null Set @delim = '|' 
If DataLength(@S) = 0 Or 
    Substring(@S, 1, @BtchSiz) = @delim Return 
-- --------------------------- 
Select @dLLen = Len(@delim), 
    @Strt = 1, @wPos = 1, 
    @sWin = Substring(@S, 1, @BtchSiz) 
Select @wLen = Len(@sWin), 
     @wLast = Case When Len(@sWin) = @BtchSiz 
       Then 0 Else 1 End, 
     @dPos = CharIndex(@delim, @sWin, @Strt) 
-- ---------------------------- 
While @Strt <= @wLen 
    Begin 
    If @dPos = 0 Begin -- No More delimiters in window 
     If @wLast = 1 Set @dPos = @wLen + 1 
     Else Begin 
      Set @wPos = @wPos + @Strt - 1 
      Set @sWin = Substring(@S, @wPos, @BtchSiz) 
       -- ------------------------------------- 
      Select @wLen = Len(@sWin), @Strt = 1, 
      @wLast = Case When Len(@sWin) = @BtchSiz 
       Then 0 Else 1 End, 
             @dPos = CharIndex(@delim, @sWin, 1) 
      If @dPos = 0 Set @dPos = @wLen + 1 
      End 
     End 
     -- ------------------------------- 
    Set @sVal = LTrim(Substring(@sWin, @Strt, @dPos - @Strt)) 
    Insert @tOut (sVal) Values (@sVal) 
    -- ------------------------------- 
    -- Move @Strt to char after last delimiter 
    Set @Strt = @dPos + @dLLen 
    Set @dPos = CharIndex(@delim, @sWin, @Strt) 
    End 
Return 
End 
2

異なるアプローチは、CHARINDEX()を使用することです。ただし、WHERE句で関数を使用すると、パフォーマンスが低下します。

WHERE CHARINDEX(','+area+',',','[email protected]+',')> 0 

エリアフィールドが常に3文字の場合、これを簡略化できます。

WHERE CHARINDEX(area,@CommunityDec)> 0 

これはすばやい解決策ですが、ストップギャップです。より良い解決策は、検索基準ごとに1行のテーブルを作成し、JOINまたはサブクエリを使用して文字列検索アプローチを変更することです。

5

この記事はあなたの問題であなたを助けることができる:

http://sqlperformance.com/2012/07/t-sql-queries/split-strings

をアーロン・ベルトランは、あなたの問題について書いているこの記事では。 これは本当に長くて細部です。あなただけ呼び出すこの機能により

CREATE FUNCTION dbo.SplitStrings_XML 
(
    @List  NVARCHAR(MAX), 
    @Delimiter NVARCHAR(255) 
) 
RETURNS TABLE 
WITH SCHEMABINDING 
AS 
    RETURN 
    ( 
     SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)') 
     FROM 
     ( 
     SELECT x = CONVERT(XML, '<i>' 
      + REPLACE(@List, @Delimiter, '</i><i>') 
      + '</i>').query('.') 
    ) AS a CROSS APPLY x.nodes('i') AS y(i) 
    ); 
GO 

一つの方法は、このことでしょう

WHERE AREA IN (SELECT Item FROM dbo.SplitStrings_XML(@communityDesc, N',')) 

ホープこれはあなたを助けることができます。

4

のようなクエリは、これを使用する最も簡単な方法です変数は次のようになります。これは、Oracleの使用||トンのために、TSQL用です

SELECT * 
FROM something 
WHERE ',' + @communityDesc + ',' Like '%,' + AREA + ',%' 

o文字列を連結する

+0

これは本当に素晴らしいです!!!! –

1

XMLを使用してこのcsvを分割し、これを使用してクエリ内でフィルタリングすることができます。ユーザ定義の関数や@Table_Valiableや#Temp_Tableを使う必要はありません。

DECLARE @xml as xml,@communityDesc varchar(255) = 'aaa,bbb,ccc' 

SET @xml = cast(('<X>'+replace(@communityDesc,',' ,'</X><X>')+'</X>') as xml) 

SELECT * FROM TABLE1 
WHERE AREA IN (
    SELECT N.value('.', 'varchar(10)') as value FROM @xml.nodes('X') as T(N) 
) 

あなたは、さらにプロセスのこの分割値を必要な場合は、#table_Variableまたは#Temp_Tableにこれを挿入し、それらを使用することができます。

+0

この分割値をさらに処理する必要がある場合は、これを#table_Variableまたは#Temp_Tableに挿入して使用するだけです(下のサンプルを参照してください) INSERT INTO @Table_variable SELECT N.value( '。'、 'varchar 10) ')の値をFROM @ xml.nodes(' X ')としてT(N) SELECT * FROM TABLE1 どこの領域(SELECT Col1 from @Table_variable) –