0

C#で開発されたWebアプリケーションがあり、ページにSQLクエリの出力が表示されています。クエリはストアドプロシージャへのlinq呼び出しであり、SQLServer2008を使用しています。

列の1つには、結果行に関連付けられたタグが表示されます。同じページにチェックボックスのリストが表示され、各チェックボックスはタグに対応しています。ユーザーが1つまたは複数のチェックボックスをオンまたはオフにした場合、クエリをフィルタリングします。

私の最も単純なSQLソリューションは、次のように「NOTIN」になります。

select * from [mytable] where [tags] not in ('tag1','tag2, etc...)

FORM POSTを、値がコンマで区切られた文字列に変換するとします。例:

string tags = ParseFormAndConvertCheckBoxToCSV(Page.Request.Form);
string sqlcmd = "select * from [mytable] where [tags] not in (" + tags + ")";

しかし、私が知る限り、それは悪いことになるので、SQLを動的に構築したくありません。

SQLで値のコンマ区切りリストを使用して文字列を分割し、値をメモリ内のテーブルに格納するいくつかの方法を想像できます。

declare @tagscsv nvarchar(MAX)
declare @notags TABLE(Value nvarchar(50))

set @tagscsv = 'taxi,ivf'

Declare @x XML 
select @x = cast('<A>'+ replace(@tagscsv,',','</A><A>')+ '</A>' as xml)

insert into @notags
select t.value('.', 'nvarchar(50)') as v from @x.nodes('/A') as x(t)

select * from [mytable] where [tags] not in (select * from @notags)

...しかし、これも汚いトリックのように聞こえます。

私にはこれは非常に一般的な状況であるように見えます、そして私はそこに多くの人々が過去にこの問題に直面したことを理解します、しかしグーグルで検索して私はエレガントな解決策を見つけることができませんでした。

誰でも助けることができますか?

4

1 に答える 1

1

編集:ストアドプロシージャの部分がありません。ストアドプロシージャを使用すると、多くのオプションがありません。私は通常、あなたがしたことを行い、コンマで区切られた文字列を分割し、値を一時テーブル(またはテーブル変数)に保存します。

CREATE PROCEDURE SplitAndStuff
    @List nvarchar(MAX) = NULL,
    @SplitOn nvarchar(5) = ','  --This can be replaced with a literal if it is always a comma.
AS
BEGIN
    DECLARE @Pos int;
    DECLARE @SplitOnLength int;
    DECLARE @Results TABLE (value nvarchar(MAX))
    SET @SplitOnLength = DATALENGTH(@SplitOn) / 2;

    IF (RIGHT(@List, @SplitOnLength) <> @SplitOn) SET @List = @List + @SplitOn; --Add trailling split string if there is not one already.

    SET @Pos = CHARINDEX(@SplitOn, @List, 1)                                    --Initalize for loop.  (The starting position returned is 1-based, not 0-based.)

    WHILE @Pos > 0
    BEGIN
        INSERT INTO @Results (value) SELECT CAST(SUBSTRING(@List,1,@Pos-1)AS int);

        SET @List = SUBSTRING(@List, @Pos+@SplitOnLength, DATALENGTH(@List) / 2);
        SET @Pos = CHARINDEX(@SplitOn, @List, 1);
    END
END
GO

ストアドプロシージャが(ルックアップ以外に)何もしていない場合は、以下の元のLINQ回答を使用できます。

LINQをtagscsv使用しているため、結果の配列を分割して使用し、「wherein」クエリを実行する必要があります。

string[] tags = tagscsv.Split(',');
var output = from q in db.Table where !tags.Contains(q) select q;

参照:

于 2012-04-27T19:05:59.890 に答える