sql >> Databasteknik >  >> RDS >> Oracle

Ignorera datumintervallsparametern i where-satsen när parametern inte anges

Du har två möjligheter att närma dig de valfria indataparametrarna.

Det enklare sättet är att använda statisk SQL och tillhandahålla standard värde för de saknade parametrarna, så att du får alla matchningar.

Här sätter du enkelt gränserna till lägsta och högsta möjliga 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')

Ju mer avancerat Way populariserades av Tom Kyte och är baserad på att använda dynamisk SQL.

Om paramatrarna tillhandahålls , genererar du normal SQL med BETWEEN predikat :

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

Om parametern saknas (dvs NULL är godkänd) genererar du en annan SQL som visas nedan.

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

Observera att

1) antalet bindningsvariabler är detsamma i båda varianterna av frågan, vilket är viktigt eftersom du kan använda identiska setXXXX uttalanden

2) på grund av genvägen 1 = 1 or är between predikat ignoreras, d.v.s. alla datum beaktas.

Vilket alternativ ska användas?

För enkla frågor kommer det att finnas små skillnader, men för komplexa frågor med flera alternativ med saknade parametrar och stora data är den dynamiska SQL-metoden att föredra .

Anledningen är att med statisk SQL använder du samma sats för fler olika frågor - här en för åtkomst med dataintervall och ett för åtkomst utan dataintervall.

Det dynamiska alternativet producerar olika SQL för varje åtkomst.

Du kan se det på utförandeplanerna:

Åtkomst med datumintervall

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

Åtkomst utan dataintervall

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

Båda satserna producerar olika exekveringsplan, som är optimerad för indataparametern. I det statiska alternativet måste användning dela samma exekveringsplan för all inmatning som kan orsaka problem.




  1. Hur kan jag returnera pivottabellutdata i MySQL?

  2. Fixar för SQL Server 2012 &2014 Online Index Rebuild Issue

  3. Hur man använder HAVING-satsen i SQL

  4. Importera filer i Oracle Apex med wwv_flow_files