sql >> Databáze >  >> RDS >> Oracle

Pokud parametr není zadán, ignorujte parametr časového období v klauzuli where

Máte dvě možnosti, jak přistoupit k volitelným vstupním parametrům.

Jednodušší způsob je použít statické SQL a poskytnout výchozí hodnotu pro chybějící parametry, abyste získali všechny shody.

Zde jednoduše nastavíte hranice na minimální a maximální možné 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')

Čím více pokročilých way byl popularizován Tomem Kytem a je založen na použití dynamického SQL.

Pokud jsou uvedeny parametry , vygenerujete normální SQL pomocí BETWEEN predikát :

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

V případě, že chybí parametr (tj. NULL je předán) vygenerujete jiné SQL jak je uvedeno níže.

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

Všimněte si, že

1) počet proměnných vazby je stejný v obou variantách dotazu, což je důležité, protože můžete použít identické setXXXX prohlášení

2) kvůli zkratce 1 = 1 or je between predikát ignorován, tj. všechna data jsou brána v úvahu.

Kterou možnost použít?

U jednoduchých dotazů bude malý rozdíl, ale u složitých dotazů s několika možnostmi chybějících parametrů a velkých dat je upřednostňován dynamický SQL přístup .

Důvodem je, že při použití statického SQL použijete stejný příkaz pro více různých dotazů – zde jeden pro přístup s datový rozsah a jeden pro přístup bez datový rozsah.

Dynamická volba vytváří různé SQL pro každý přístup.

Můžete to vidět na prováděcích plánech:

Přístup s časovým obdobím

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

Přístup bez datového rozsahu

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

Oba příkazy vytvářejí odlišný plán provádění, který je optimalizován pro vstupní parametr. Ve statické možnosti použití musí sdílet stejný plán provádění pro všechny vstupy, které mohou způsobit problémy.




  1. Příkazy nejsou synchronizovány; tento příkaz nyní nemůžete spustit

  2. Jak získat velikosti tabulek databáze MySQL?

  3. java.security.AccessControlException:přístup odepřen (java.security.SecurityPermission authProvider.SunMSCAPI)

  4. Automatické zvýšení na částečném primárním klíči s Entity Framework Core