У вас есть две возможности приблизиться к необязательным параметрам ввода.
Более простой способ состоит в использовании статического SQL и предоставлении значения default для отсутствующих параметров, поэтомучто вы получаете все совпадения.
Здесь вы просто устанавливаете границы минимальной и максимально возможной ДАТЫ.
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')
Более продвинутый продвинутый способ был популяризирован Tom Kyte и основан на использовании динамического SQL.
Если заданы параметры , вы генерируете обычный SQL с предикатом BETWEEN
:
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 вы используете один и тот же оператор для более разных запросов - здесь один для доступа с даннымидиапазон и один для доступа без диапазон данных.
Динамическая опция создает разные 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)
Оба оператора дают разныеплан выполнения, оптимизированный для входного параметра.В статическом параметре необходимо использовать один и тот же план выполнения для всех входных данных, которые могут вызвать проблемы.