Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Ignorieren Sie den Datumsbereichsparameter in der Where-Klausel, wenn der Parameter nicht eingegeben wird

Sie haben zwei Möglichkeiten, an die optionalen Eingabeparameter heranzukommen.

Je einfacher Eine Möglichkeit besteht darin, statisches SQL zu verwenden und default bereitzustellen Wert für die fehlenden Parameter, damit Sie alle Übereinstimmungen erhalten.

Hier legt man einfach die Grenzen auf das minimal und maximal mögliche DATE fest.

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

Je mehr Fortgeschritten Methode wurde von Tom Kyte populär gemacht und basiert auf der Verwendung von dynamischem SQL.

Wenn die Parameter bereitgestellt werden , generieren Sie normales SQL mit dem BETWEEN Prädikat :

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

Falls die Parameter fehlen (d.h. NULL übergeben wird) erzeugen Sie ein anderes SQL wie unten gezeigt.

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

Beachten Sie, dass

1) Die Anzahl der Bind-Variablen ist in beiden Varianten der Abfrage gleich, was wichtig ist, da Sie identische setXXXX verwenden können Aussagen

2) wegen der Verknüpfung 1 = 1 or ist der between Prädikat ignoriert, d.h. alle Daten werden berücksichtigt.

Welche Option soll verwendet werden?

Nun, bei einfachen Abfragen wird es kleine Unterschiede geben, aber bei komplexen Abfragen mit mehreren Optionen fehlender Parameter und großen Datenmengen wird der dynamische SQL-Ansatz bevorzugt .

Der Grund dafür ist, dass Sie mit statischem SQL dieselbe Anweisung für mehrere unterschiedliche Abfragen verwenden - hier eine für den Zugriff mit Datenbereich und einen für den Zugriff ohne Datenbereich.

Die dynamische Option erzeugt für jeden Zugriff eine andere SQL.

Sie können es auf den Ausführungsplänen sehen:

Zugriff mit Zeitraum

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

Zugriff ohne Datenbereich

------------------------------------------------------------------------------
| 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 Anweisungen erzeugen einen unterschiedlichen Ausführungsplan, der für den Eingabeparameter optimiert ist. Bei der statischen Option muss die Verwendung denselben Ausführungsplan teilen für alle Eingaben, die Probleme verursachen könnten.