2

単一のレコードまたはすべてのレコードを選択するために使用される tquery (BDE または BDE エミュレート コンポーネントを経由する) があります。

従来、これは次のように行われてきました。

select * from clients where (clientid = :clientid or :clientid = -1) 

そして、クエリですべての値を返すようにするには、フィールドに -1 を入力します。ただし、このコードを調べてみると、クエリがテーブルに対して適切なインデックスを使用せず、自然な読み取りしか行わないことがわかりました。

これを達成するためのベストプラクティスの方法はありますか? おそらく、すべての値を返すようにパラメーターに指示する方法ですか、それともすべての値が必要な場合は、where 句を完全に削除するようにスクリプトを変更する必要がありますか?

編集:ちなみに、これはDelphi 7です(そして、Firebird 1.5に反対して、それを省略して申し訳ありません)

4

5 に答える 5

2

非推奨の BDE を使用しているため、BDE からサードパーティ ソリューションに移行するもう 1 つの理由になる可能性があります。AnyDAC (UniDAC、おそらく他のものも。ほとんどが商用ライブラリ) にはマクロがあり、マクロの値に応じて SQL コマンド テキストを動的に変更できます。したがって、クエリは次のように記述できます。

ADQuery1.SQL.Text := 'select * from clients {IF &clientid} where clientid = &clientid {FI}';

if clientid >= 0 then
  // to get a single record
  ADQuery1.Macros[0].AsInteger := clientid
else
  // to get all records
  ADQuery1.Macros[0].Clear;

ADQuery1.Open;
于 2012-09-14T05:30:20.993 に答える
0

「オプションの」パラメータを使用するクエリでは、常にISNULL(MSSQL、またはNVL Oracle)を使用します。

SELECT * FROM clients WHERE ISNULL(:clientid, clientid) = clientid

次にパラメータを設定するとNULL、すべてのレコードが選択されます。また、テーブルフィールドのNULL値にも注意する必要がありますNULL <> NULL。これは、わずかな変更で克服できます。

SELECT * FROM clients WHERE COALESCE(:clientid, clientid, -1) = ISNULL(clientid, -1)
于 2012-09-14T06:27:01.830 に答える
0

Remyの回答は、単一のクエリとして再定式化される場合があります。一度準備してから、何度も再度開くとよいでしょう。

select * from clients where (clientid = :clientid)
                        and (:clientid is not null)
  UNION ALL
select * from clients where (:clientid is null)

これは、2つの異なるクエリ(同じ結果ベクトルを持つ)を一緒に集約するだけです。そして、状態はそれらの1つをオフにするだけです。使用は次のようになります。

 DBComp.Prepare.
   ...
 DBComp.Close;
 DBComp.ParamByName('clientid').Value := clientid;
 DBComp.Open;
   ...
 DBComp.Close;
 DBComp.ParamByName('clientid').Clear;
 DBComp.Open;

ただし、このクエリはSQL Serverオプティマイザー機能に依存して、クエリ不変条件を抽出し(:clientidは[not] null)、クエリを完全に有効/無効にします。しかし、まあ、あなたの元のクエリもそれに依存しています。


なぜまだ時代遅れのFB1.5を使用するのですか?FB 2.5.2はそこでうまく機能しませんか?あなたの元のクエリはうまく定式化されていないと思います。

  select * from clients where (:clientid = -1) or  ((clientid = :clientid) and (:clientid <> -1))

SQLServerオプティマイザの方がおそらく簡単でしょう。それでも、FBはそこでより良い仕事をすることができると思います。後でFBをダウンロードして、IBExpertやFlameRobinなどのIDEを使用してクエリを実行してみてください。括弧を再配置し、-1をNULLに変更することは、試してみるべき明らかなアイデアです。


現在、BDEの使用は脆弱です。それほど高速ではなく、データ型と接続性が制限されます(たとえば、FB / IBイベントはありません)。そして、Vista/Win7とWin64とのあらゆる種類の互換性の問題があります。FB / IBを選択するサーバーの場合は、最新のコンポーネントセットに切り替えることを検討してください。


また、テーブルとインデックスの定義とそれらのインデックスの選択性を示すのも良いことです。

于 2012-09-17T06:15:44.047 に答える
0

2 つのクエリを使用するのが最適です。

if (clientid <> -1) then
begin
  DBComp.SQL.Text := 'select * from clients where (clientid = :clientid)';
  DBComp.ParamByName('clientid').Value := clientid;
end else
begin
  DBComp.SQL.Text := 'select * from clients';
end;
DBComp.Open;
...

または:

DBComp.SQL.BeginUpdate;
try
  DBComp.SQL.Clear;
  DBComp.SQL.Add('select * from clients');
  if (clientid <> -1) then
    DBComp.SQL.Add('where (clientid = :clientid)');
finally
  DBComp.SQL.EndUpdate;
end;

if (clientid <> -1) then
  DBComp.ParamByName('clientid').Value := clientid;

DBComp.Open;
...
于 2012-09-14T00:50:21.777 に答える
0

私はこれを使用します:

SELECT * FROM CLIENTS WHERE clientid = :clientid or :clientid IS NULL
于 2012-09-14T13:06:05.023 に答える