sql >> Database >  >> RDS >> Oracle

Negeer de datumbereikparameter in de waar-clausule wanneer de parameter niet is ingevoerd

U heeft twee mogelijkheden om de optionele invoerparameters te benaderen.

De eenvoudiger manier is om statische SQL te gebruiken en standaard . te geven waarde voor de ontbrekende parameters, zodat u alle overeenkomsten krijgt.

Hier stelt u eenvoudig de grenzen in op de minimaal en maximaal mogelijke DATUM.

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')

Hoe meer geavanceerd way werd gepopulariseerd door Tom Kyte en is gebaseerd op het gebruik van dynamische SQL.

Als de parameters zijn opgegeven , genereert u normale SQL met de BETWEEN predikaat :

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

In het geval dat de parameter ontbreekt (d.w.z. NULL is doorgegeven) genereert u een andere SQL zoals hieronder weergegeven.

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

Merk op dat

1) het aantal bindvariabelen is hetzelfde in beide varianten van de query, wat belangrijk is omdat je identieke setXXXX kunt gebruiken verklaringen

2) vanwege de snelkoppeling 1 = 1 or is de between predikaat genegeerd, d.w.z. alle datums worden in aanmerking genomen.

Welke optie moet worden gebruikt?

Welnu, voor eenvoudige query's zal er een klein verschil zijn, maar voor complexe query's met verschillende opties voor ontbrekende parameters en grote gegevens, de dynamische SQL-aanpak heeft de voorkeur .

De reden is dat je met statische SQL dezelfde instructie gebruikt voor meer verschillende zoekopdrachten - hier een voor toegang met gegevensbereik en één voor toegang zonder gegevensbereik.

De dynamische optie produceert verschillende SQL voor elke toegang.

Je ziet het misschien op de uitvoeringsplannen:

Toegang met datumbereik

-------------------------------------------------------------------------------
| 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)

Toegang zonder gegevensbereik

------------------------------------------------------------------------------
| 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)

Beide verklaringen produceren een ander uitvoeringsplan, dat is geoptimaliseerd voor de invoerparameter. In de statische optie moet het gebruik hetzelfde uitvoeringsplan delen voor alle invoer die problemen kan veroorzaken.




  1. MySQL - Gegevens uit meerdere tabellen selecteren, allemaal met dezelfde structuur maar met verschillende gegevens

  2. Wijzigingen in de gegevensconnector in 2020.24

  3. JSON_ARRAY() – Maak een JSON-array van een lijst met waarden in MySQL

  4. Hoe PBKDF2 te gebruiken in Oracle 12c?