1

varchar フィールドを含むテーブルがあるとします。

CREATE TABLE [MyTable] (
    [MyId]    varchar(3)    NOT NULL,
    .....
)

[MyId]列には、A1、A2... A99、B1、B2..B99、C1 など (Z99 まで) のような連続した英数字の値が含まれます。

私がしたいのは、MyIdフィールドが特定のプレフィックスに一致するテーブルから行を抽出することです...たとえば、シリーズ A、C、P、および X から行をフェッチしたいと思います。

そして、引数で指定されたプレフィックスのアルファベットに基づいてクエリを動的に構築する sproc を使用してこれを行いたいと思います。

なんかこんなこと考えてる…

CREATE PROCEDURE [dbo].[uspFilterMyTable]
  @prefixArray varchar(max)
AS
  ... -- split individual characters from @prefixArray into an array

  SELECT * FROM [MyTable] 
  WHERE 
    [MyId] LIKE ....
    OR
    [MyId] LIKE ....  -- iterate all characters from @prefixArray

ストアド プロシージャの主な部分は、次の疑似コードのようになると思います。

DECLARE @sql nvarchar(max)
-- iterate through all the characters
SET @sql = 'SELECT * FROM [MyTable] WHERE [MyId] LIKE ' + @charInTheArray + '%'
SET @sql = @sql + ' OR [MyId] LIKE ' + @nextCharInArray + '%'


EXEC (@sql)

上記の手順は次のように呼び出されます。

EXEC uspFilterMyTable("A,C,P,X")

...またはおそらく次のようになります(アルファベットの分割が簡単になる場合):

EXEC uspFilterMyTable("ACPX")

何か案は?ポインタ?


更新: OK、これは私が思いついたものです ([Split] 関数は Chhatrapati Sharma から借用):

-- [MyTable] contains these rows: 'A7', 'A87', 'B16', 'C51', 'H99', 'X12'

-- the "input" parameter
DECLARE @prefixArray NVARCHAR(100)= 'H,A,C'

-- split the string into SQL wild-card patterns
DECLARE charCursor CURSOR FOR
    select items + N'%' from dbo.Split(@prefixArray, ',')


OPEN charCursor;
DECLARE @pattern CHAR(2)

-- create temp table if necessary
IF NOT EXISTS(SELECT * FROM TEMPDB.SYS.TABLES WHERE NAME LIKE '#tmpTable%')
    CREATE TABLE #tmpTable ([Id] VARCHAR(3) NOT NULL)

-- purge old data
DELETE FROM #tmpTable

FETCH NEXT FROM charCursor into @pattern
WHILE @@FETCH_STATUS = 0
BEGIN
      --SELECT * INTO #tmpTable FROM [MyTable] WHERE [MyId] LIKE @pattern   
      Insert Into #tmpTable Select * FROM [MyTable] WHERE [MyId] LIKE @pattern  
    FETCH NEXT FROM charCursor into @pattern
END

CLOSE charCursor;
DEALLOCATE charCursor;

-- return the values
SELECT * FROM #tmpTable    

醜いことはわかっていますが、機能します...コードを即興で作成するためのヒントはありますか?

4

3 に答える 3

2

最初に以下の関数を作成してから、これを次のようなクエリで使用する必要があります

SELECT * FROM [MyTable] WHERE  [MyId] in (select items from dbo.split(@prefixArray,','))



CREATE FUNCTION [dbo].[Split](@String varchar(8000), @Delimiter char(1))         
returns @temptable TABLE (items varchar(8000))         
as         
begin         
    declare @idx int         
    declare @slice varchar(8000)         

    select @idx = 1         
    if len(@String)<1 or @String is null  return         

    while @idx!= 0         
     begin         
      set @idx = charindex(@Delimiter,@String)         
      if @idx!=0         
      set @slice = left(@String,@idx - 1)         
     else         
      set @slice = @String         

      if(len(@slice)>0)    
       insert into @temptable(Items) values(@slice)         

       set @String = right(@String,len(@String) - @idx)         
       if len(@String) = 0 break         
       end     
    return         
    end 
于 2012-09-20T06:53:41.873 に答える
2

ここでは、XML に基づいた便利で高速な分割方法を示します。

DECLARE @str NVARCHAR(100)= 'A1,B3,C4,B12,K19', @separator VARCHAR(1)= ','
DECLARE @SplitedList  TABLE (code NVARCHAR(30))

DECLARE @XMLList XML
SET @XMLList=CAST('<i>'+REPLACE(@str, @separator,'</i><i>')+'</i>' AS XML)

INSERT INTO @SplitedList
SELECT x.i.value('(./text())[1]','varchar(100)')
FROM @XMLList.nodes('i') x(i)

SELECT * FROM @SplitedList

結果は、分割された値を含むテーブルになります。

code
A1
B3
C4
B12
K19

ここから、手順でこのテーブルを続行して使用し、提案したとおりに使用して元のテーブルと結合できLIKEます。

于 2012-09-20T07:03:47.103 に答える
1

テーブル値パラメーターを使用してストアド プロシージャを呼び出すことをお勧めします。.net から呼び出すと思います。しかし、チェックするかもしれませんが、EFはそれを処理できないと思います。そうでない場合、最初に文字列を一時テーブルまたはテーブル値に解析し、その後で結合するのが最善の方法だと思います。

TVP の場合:

CREATE PROCEDURE [dbo].[uspFilterMyTable]
  @prefixArray tvp_idlist readonly
as
  select 
   t.* 
  from MyTable t
  join @prefixArray pa on pa.id = t.myid

分割機能を使用する (選択したものについては、ネット上で多くの例を見つけることができます)

CREATE PROCEDURE [dbo].[uspFilterMyTable]
  @prefixArray varchar(max)
as

  create @prefixArray tvp_idlist
  insert into @prefixArray (id)
  select id from dbo.myCustomSplit(@prefixArray,',')


  select 
   t.* 
  from MyTable t
  join @prefixArray pa on pa.id = t.myid

どちらの場合も、@prefixArray はテーブル変数であり、Id = varchar(3) です。

編集として、少し掘り下げた後、少しの作業でEFはTVPで正常に動作するようです. これを確認してください:エンティティ フレームワーク ストアド プロシージャ テーブル値パラメータ。したがって、最善の方法は、テーブルをストアド プロシージャに直接送信してから、文字列を送信して解析することです。

于 2012-09-20T06:59:31.510 に答える