0

私はデータベース アプリケーション (Oracle 10g データベースに基づき、Delphi で記述) を「継承」しました。これは、次のようにいくつかの決定を行う必要があります。

Do Query1.
If the result set is empty, do Query2.

クエリはSELECT、同じ出力列を持つクエリであり、入力 (FROM) と条件 (WHERE) が似ている場合 (ケース 1) と異なる場合 (ケース 2) があります。

ケース 1:違いがcol like 'x'(または col = 'x') になる場合がありcol like '%'ます。

  • パフォーマンス: おそらく、2 つの異なるクエリ (およびそれを使用しないクエリ) を使用するのが最善でしょうcol = 'x'
  • 保守性: col like :param2 つのクエリを必要としないので優れています。
  • 妥協案:AND (col = 'x' OR :param = 1)

ケース 2:別の機会に、Query1 の結果セットにデータがない場合、完全に異なる Query2 を使用する必要があります。


stackoverflowとインターネットの検索から、私の問題に対するいくつかの解決策を認識しています。

  1. 2 つの SQL クエリを使用する: データベースの代わりにプログラムに作業を任せます (ただし、データベースを 1 回だけではなく 2 回クエリする必要があります)。

    result = executeQuery(Query1)
    if (isEmpty(result))
    result = executeQuery(Query2)
    
  2. UNION の使用: Oracle にすべての作業を任せます (ただし、Query1 を 2 回実行する必要があります)。

    Query1 UNION ALL Query 2 WHERE NOT EXISTS (Query 1)
    
  3. PL/SQL の使用: Oracle にほとんどの作業を任せます (ただし、この方法で毎回クエリがコンパイルされることをどこかで読みました)。

    begin
     Query1;
    exception when no_data_found then
     Query2;
    end;
    

私の質問は次のとおりです。

  1. 他の(より良い)解決策はありますか?
  2. (私よりも経験豊富なデータベース ユーザーとして) 何を使用しますか?
  3. (欠点)利点は何ですか?
  4. 注意事項は何ですか?
4

1 に答える 1

1

多くの場合、UNIONより厳密でないWHERE句を使用することで回避できますが、ORDER BY句を含めて、より一致する結果が最初に表示されるようにします。必要に応じて、ROWNUM疑似列を使用して結果を最初のものに制限できます。

たとえば、代わりに

 BEGIN
   SELECT * INTO myrec FROM mytable WHERE xxx = 'x';
 EXCEPTION
   WHEN NO_DATA_FOUND THEN
     SELECT * INTO myrec FROM mytable WHERE xxx like '%x%';
 END;

あなたが書くことができます

 SELECT * INTO myrec FROM (
   SELECT * FROM mytable WHERE X like '%x%'
     ORDER BY CASE when xxx='x' THEN 1 ELSE 2 END
 ) WHERE ROWNUM=1;

ネストされたSELECTステートメントに注意してください。WHERE ROWNUM=1そうしないと、句が実行前に結果セットを制限するため、これが必要ですORDER BY

于 2012-08-08T11:55:05.957 に答える