Masz dwie możliwości podejścia do opcjonalnych parametrów wejściowych.
prostsze sposobem jest użycie statycznego SQL i podanie domyślnego wartość dla brakujących parametrów, aby uzyskać wszystkie dopasowania.
Tutaj po prostu ustawiasz granice na minimalną i maksymalną możliwą datę.
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')
Im bardziej zaawansowany sposób został spopularyzowany przez Toma Kyte i opiera się na wykorzystaniu dynamicznego SQL.
Jeśli parametry są podane , generujesz normalny kod SQL z BETWEEN
orzeczenie :
select *
from customer
where customer_id = $P{CLIENT_ID}
and datetrx between $P{DATE_START} and $P{DATE_END}
W przypadku braku parametru (np. NULL
jest przekazany) generujesz inny kod SQL jak pokazano poniżej.
select *
from customer
where customer_id = $P{CLIENT_ID}
and (1=1 or datetrx between $P{DATE_START} and $P{DATE_END})
Zwróć uwagę, że
1) liczba zmiennych wiązania jest taka sama w obu wariantach zapytania, co jest ważne, ponieważ możesz użyć identycznego setXXXX
oświadczenia
2) ze względu na skrót 1 = 1 or
jest between
predykat ignorowany, tj. wszystkie daty są brane pod uwagę.
Której opcji należy użyć?
Cóż, w przypadku prostych zapytań będzie niewielka różnica, ale w przypadku złożonych zapytań z kilkoma opcjami brakujących parametrów i dużymi danymi, preferowane jest dynamiczne podejście SQL .
Powodem jest to, że używając statycznego SQL, używasz tej samej instrukcji dla większej liczby różnych zapytań - tutaj jedno dla dostępu za pomocą zakres danych i jeden dla dostępu bez zakres danych.
Opcja dynamiczna generuje inny kod SQL dla każdego dostępu.
Możesz to zobaczyć na planach wykonania:
Dostęp z zakresem dat
-------------------------------------------------------------------------------
| 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)
Dostęp bez zakresu danych
------------------------------------------------------------------------------
| 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)
Obie instrukcje tworzą inny plan wykonania, który jest zoptymalizowany pod kątem parametru wejściowego. W opcji statycznej użycie musi współdzielić ten sam plan wykonania dla wszystkich danych wejściowych, które mogą powodować problemy.