sql >> Base de Datos >  >> RDS >> Oracle

Ignore el parámetro de rango de fechas en la cláusula where cuando no se ingresa el parámetro

Tiene dos posibilidades para acercarse a los parámetros de entrada opcionales.

El más simple La forma es usar SQL estático y proporcionar predeterminado valor para los parámetros que faltan, de modo que obtenga todas las coincidencias.

Aquí simplemente establece los límites para la FECHA mínima y máxima posible.

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

Cuanto más avanzado fue popularizado por Tom Kyte y se basa en el uso de SQL dinámico.

Si se proporcionan los parámetros , genera SQL normal con BETWEEN predicado :

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

En caso de que falte el parámetro (es decir, NULL se pasa) se genera un SQL diferente como se muestra a continuación.

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

Tenga en cuenta que

1) el número de variables de vinculación es el mismo en ambas variantes de la consulta, lo cual es importante ya que puede usar setXXXX idénticos declaraciones

2) debido al atajo 1 = 1 or es el between predicado ignorado, es decir, se consideran todas las fechas.

¿Qué opción se debe usar?

Bueno, para consultas simples habrá una pequeña diferencia, pero para consultas complejas con varias opciones de parámetros faltantes y datos grandes, se prefiere el enfoque de SQL dinámico .

La razón es que al usar SQL estático, usa la misma declaración para más consultas diferentes:aquí una para acceder con rango de datos y uno para acceso sin rango de datos.

La opción dinámica produce SQL diferente para cada acceso.

Puede verlo en los planes de ejecución:

Acceso con intervalo de fechas

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

Acceso sin rango de datos

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

Ambas declaraciones producen un plan de ejecución diferente, que está optimizado para el parámetro de entrada. En la opción estática, el uso debe compartir el mismo plan de ejecución para todas las entradas que puedan causar problemas.