3

ユーザーがプロシージャに渡されたパラメータに基づいてOracleテーブルのレコードを検索および編集できるWebフォームがあります。これが私のデータです:

CAE_SEC_ID  SEC_CODE  APPR_STATUS
1           ABC1      100
2           ABC2      100
3           ABC3      101
4           (null)    101
5           (null)    102
6           ABC4      103

そして、ここにwhere句があります:

select foo 
  from bar 
 where CAE_SEC_ID = NVL(p_cae_sec_id,CAE_SEC_ID)
   and Upper(SEC_CODE) like '%' || Upper(NVL(p_sec_code,SEC_CODE)) || '%'
   and APPR_STATUS = NVL(p_appr_status, APPR_STATUS)

パラメータでnvlを使用すると、いずれかのパラメータに値がある場合は一致したレコードのみが返され、どのパラメータにも値がない場合はすべてのレコードが返されます。すべてかなり標準的かそこらだと思いました。ただし、パラメータ値を指定せずに検索を実行すると、クエリはSEC_CODEがnullのレコードを返しません。つまり、レコード1、2、3、および6のみが返されます。上記のwhere句には、SEC_CODE値がnullのレコードを含めるべきではありませんか?

4

4 に答える 4

7

問題はSEC_CODE、テーブルの値がNULLであるということです。つまり、それUPPER(sec_code)はNULLであり、2番目の述語は次のように単純化されます。

and NULL LIKE '%%'

NULLが何にも等しくなく、何にも等しくないのと同じように、それは何にも似ていません。おそらく、あなたは次のようなものが欲しい

and (Upper(SEC_CODE) like '%' || Upper(NVL(p_sec_code,SEC_CODE)) || '%' or
     (sec_code is null and p_sec_code is null))

NULLの場合はすべての行が返されP_SEC_CODEますが、NULL以外の場合はフィルターが適用されP_SEC_CODEます。

于 2011-03-02T23:18:57.707 に答える
4

いいえ、すべきではありません。

データベース内のSEC_CODEはnullであるため、UPPER(SEC_CODE)はnullであり、LIKE一致またはISNULL以外のほとんどすべての比較で失敗します。技術的には、FALSEではなくUNKNOWNですが、テストに合格するには十分ではありません。

于 2011-03-02T23:16:10.803 に答える
3

NULL = NULLはと評価されますが、そうNULLではないtrueため、これらの行は返されません。要件を正しく理解している場合は、パラメーターがnullと異なる場合にのみフィルター処理する必要があるため、次のようにクエリを書き直して、フィルターをより明示的にします。

select foo from bar 
where (p_cae_sec_id is null or CAE_SEC_ID = p_cae_sec_id)
and (p_sec_code is null or Upper(SEC_CODE) like '%' || Upper(p_sec_code) || '%')
and (p_appr_status is null or APPR_STATUS = p_appr_status)

p_sec_codeパラメーターをnullに設定すると、SEC_CODE列の値を無視して、すべての行が返されるようになりました。

于 2011-03-02T23:33:01.750 に答える
0

Jornのクエリを次のように書くこともできます

select foo from bar 
where (CASE WHEN p_cae_sec_id is null THEN 'Y'
            WHEN CAE_SEC_ID = p_cae_sec_id THEN 'Y'
                    ELSE 'N'
                    END)='Y'
and   (CASE WHEN p_sec_code is null THEN 'Y'
            WHEN Upper(SEC_CODE) like '%' || Upper(p_sec_code) || '%' THEN 'Y'
                    ELSE 'N'
                    END)='Y'
and (CASE WHEN p_appr_status is null THEN 'Y'
                    WHEN APPR_STATUS = p_appr_status THEN 'Y'
                ELSE 'N'
                END)='Y'

具体的にしてパフォーマンスを向上させます。

于 2011-03-03T19:09:43.950 に答える