0

複数の選択が可能な 3 つのリストボックスを含むドキュメント検索ページがあります。それらは次のとおりです。

カテゴリーA

カテゴリーB

カテゴリ A のみが必須で、その他はオプションのパラメータであり、空の場合があります。

各ドキュメントは、カテゴリ A の複数のオプションと複数のオプション カテゴリ B に属することができますが、各ドキュメントに関連付けられている年は 1 つだけです。

動的SQL文字列を構築することでこれが機能するようになりましたが、面倒で使いたくないので、誰かがこれを行う簡単な方法を見つけられるかどうかここで尋ねたいと思いました. 最終的に次のような動的SQLクエリの例を示します。

 select * 
from library
where libraryID in
(select distinct libraryID from categoryAdocs where categoryAdocID in (4))
or year in (2004)

追加の詳細:

次のDBテーブルをセットアップしました:

ライブラリー (YEAR パラメーターを含む)

CategoryADocs (各ドキュメントがカテゴリ A の複数のオプションに属する可能性があるため、リンク テーブル)

CategoryBDocs (各ドキュメントがカテゴリ B の複数のオプションに属する可能性があるため、リンク テーブル)

CategoryA (Cat A カテゴリーのリスト)

CategoryB (Cat B カテゴリーのリスト)

これを行う「より簡単な」方法について言及します。理想的には、これを行うための最良の方法を探しています。SQLを介して動的に構築するよりも簡単であればクールですが、より複雑な場合は問題ありません。

4

1 に答える 1

1

現在のクエリの表現方法とパラメーターの動的リストの入力は、メモリ内でクエリを大幅に構築して実行していることを意味します。その場合、構築するクライアント言語を使用するのがおそらく最善です。とにかく必要なときに要素をドロップするクエリ。私が知っているどの方言でも、SQL パラメーターまたは変数を介してリストを直接挿入することはできません。

つまり、これをコンパイルする方法でより一定のクエリ構造を使用したい場合は、INT Identity(1,1) として宣言された CategoryBdocID フィールドを持つ CategoryBdocs テーブルがあると仮定すると、実行することにより、現在のクエリの行

select * 
from library
where libraryID in
    (select distinct libraryID from categoryAdocs where categoryAdocID in (4))
or LibraryID in
    (select distinct libraryID from categoryBdocs where categoryBdocID in (-1))

-1 - の後にカテゴリ B リストを連結すると、常に何も返されないので安全です。年がリストとして入っていない場合は、次のようなものを使用してオプションのパラメーターとして機能させることができます

or Year in (COALESCE(2004, Year))

そして、2004 の代わりに NULL が出てくると、それ自体と一致して戻ります。ただし、リストを使用してそれを行うことはできません。オプションのリストを使用して SQL でそれを行うクリーンな方法は考えられません。

これはすべて、メモリ内にクエリを作成して実行しているという前提に基づいていますが、それはあなたがしているように見えるものです。これを行うのは好きではないとおっしゃいましたが、私も同意します。理想的には効率的ではなく、リストを渡してクエリに連結すると、SQL インジェクションにさらされやすくなります。

これを回避するには、これをストアド プロシージャにラップすることをお勧めします。次に、3 つのリストのそれぞれに ID を含む区切り文字列を渡すと、数値/集計テーブルに対して結合することで、それらを個々の値のテーブルに分割できます (詳細は別の私の回答 - SQL select from data in query where this dataまだデータベースにありませんか? )。ここから、次の行に沿って書くことができます

SELECT L.* 

FROM Library L
    INNER JOIN CategoryADocs A
        ON L.LibraryID=A.LibraryID

    INNER JOIN ([CategoryA Derived table]) ADocs 
        ON A.CategoryAdocID=ADocs.CategoryADocID

    LEFT JOIN (SELECT B.* FROM CategoryBDocs B
                INNER JOIN [CategoryB Derived Table] BDocs
                    ON B.CategoryBdocID=BDocs.CategoryBDocID) B
        ON L.LibraryID=B.LibraryID

    LEFT JOIN ([Years Derived table]) Y
        ON L.Year=Y.Year

WHERE
    COALESCE(B.LibraryID,-1)=CASE WHEN Len(@BIDs) > 1 THEN B.LibraryID ELSE -1
    AND COALESCE(L.Year,-1)=CASE WHEN Len(@Years) > 1 THEN L.Year ELSE -1

私が認めているのは、長くて複雑な方法ですが、動的なクエリを構築する必要なく、すべてのロジックを SQL に入れることができます。それが複雑さに見合う価値があると思うかどうかは、あなた次第です!

于 2010-04-06T11:40:36.577 に答える