sql >> データベース >  >> RDS >> Oracle

パラメータが入力されていない場合、where句の日付範囲パラメータを無視します

    オプションの入力パラメータにアプローチするには、2つの可能性があります。

    よりシンプル 静的SQLを使用し、デフォルトを提供する方法があります 欠落しているパラメータの値。これにより、すべての一致が得られます。

    ここでは、境界を可能な最小および最大のDATEに設定するだけです。

    select * 
    from customer
    where customer_id = $P{CLIENT_ID}
    and datetrx between nvl($P{DATE_START},date'1900-01-01') 
                    and nvl($P{DATE_END},date'2200-01-01')
    

    より高度な WayはTomKyteによって普及し、動的SQLの使用に基づいています。

    パラメータが提供されている場合BETWEENを使用して通常のSQLを生成します 述語

    select * 
    from customer
    where customer_id = $P{CLIENT_ID}
    and datetrx between $P{DATE_START} and $P{DATE_END}
    

    パラメータが欠落している場合 (つまり、NULL 渡されます)異なるSQLを生成します 以下に示すように。

    select * 
    from customer
    where customer_id = $P{CLIENT_ID}
    and (1=1 or datetrx between $P{DATE_START} and $P{DATE_END})
    

    に注意してください

    1)バインド変数の数は、クエリの両方のバリアントで同じです。これは、同じsetXXXXを使用できるため重要です。 ステートメント

    2)ショートカットによる 1 = 1 or between 述語は無視されます。つまり、すべての日付が考慮されます。

    どのオプションを使用する必要がありますか?

    単純なクエリの場合はわずかな違いがありますが、パラメータが欠落していてデータが大きいといういくつかのオプションがある複雑なクエリの場合は、動的SQLアプローチが推奨されます

    その理由は、静的SQLを使用すると、より多くの異なるクエリに同じステートメントを使用するためです。ここでは、 withにアクセスするためのステートメントです。 データ範囲とアクセス用の1つなし データ範囲。

    動的オプションは、アクセスごとに異なるSQLを生成します。

    実行計画に表示される場合があります:

    日付範囲でのアクセス

    -------------------------------------------------------------------------------
    | Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    -------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |           |     1 |    22 |     1   (0)| 00:00:01 |
    |*  1 |  FILTER           |           |       |       |            |          |
    |*  2 |   INDEX RANGE SCAN| CUST_IDX1 |     1 |    22 |     1   (0)| 00:00:01 |
    -------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - filter(TO_DATE(:1)<=TO_DATE(:2))
       2 - access("CUSTOMER_ID"=1 AND "DATETRX">=:1 AND "DATETRX"<=:2)
    

    データ範囲なしのアクセス

    ------------------------------------------------------------------------------
    | Id  | Operation        | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT |           |     1 |    22 |     1   (0)| 00:00:01 |
    |*  1 |  INDEX RANGE SCAN| CUST_IDX1 |     1 |    22 |     1   (0)| 00:00:01 |
    ------------------------------------------------------------------------------
    
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - access("CUSTOMER_ID"=1)
    

    どちらのステートメントも、入力パラメーター用に最適化された異なる実行プランを生成します。静的オプションでは、同じ実行プランを共有する必要があります 問題を引き起こす可能性のあるすべての入力に対して。




    1. mysqliまたはPDO-長所と短所は何ですか?

    2. インデックスはデータベースのパフォーマンスにどのように影響しますか?

    3. OracleのREGEXP_SUBSTR()関数

    4. SQLエスケープを使用した動的mysqlクエリは、プリペアドステートメントと同じくらい安全ですか?