sql >> Database >  >> RDS >> Oracle

Is gelijk aan(=) vs. LIKE voor datumgegevenstype

Ervan uitgaande dat LAST_TRANSACTION_DATE is een DATE kolom (of TIMESTAMP ) dan zijn beide versies een zeer slechte gewoonte.

In beide gevallen de DATE kolom wordt impliciet geconverteerd naar een letterlijke letter op basis van de huidige NLS-instellingen. Dat betekent dat je met verschillende klanten verschillende resultaten krijgt.

Bij gebruik van letterlijke datums altijd gebruik to_date() met(!) een formaatmasker of gebruik een letterlijke ANSI-datum. Op die manier vergelijk je datums met datums en niet strings met strings. Dus voor de gelijke vergelijking moet je gebruiken:

LAST_TRANSACTION_DATE = to_date('30-JUL-07', 'dd-mon-yy')

Merk op dat het gebruik van 'MON' nog steeds kan leiden tot fouten met verschillende NLS-instellingen ('DEC' vs. 'DEZ' of 'MAR' vs. 'MRZ' ). Het is veel minder foutgevoelig bij het gebruik van maandnummers (en viercijferige jaren):

LAST_TRANSACTION_DATE = to_date('30-07-2007', 'dd-mm-yyyy')

of een ANSI-datum letterlijk gebruiken

LAST_TRANSACTION_DATE = DATE '2007-07-30'

De reden waarom de bovenstaande query zeer waarschijnlijk niets zal opleveren, is dat in Oracle DATE kolommen bevatten ook de tijd. De bovenstaande letterlijke datums bevatten impliciet de tijd 00:00 . Als de tijd in de tabel anders is (bijv. 19:54 ) dan zijn de data natuurlijk niet gelijk.

Om dit probleem te omzeilen heeft u verschillende opties:

  1. gebruik trunc() in de tabelkolom om de tijd te "normaliseren" naar 00:00 trunc(LAST_TRANSACTION_DATE) = DATE '2007-07-30 dit voorkomt echter het gebruik van een index gedefinieerd op LAST_TRANSACTION_DATE
  2. gebruik between
    LAST_TRANSACTION_DATE between to_date('2007-07-30 00:00:00', 'yyyy-mm-dd hh24:mi:ss') and to_date('2007-07-30 23:59:59', 'yyyy-mm-dd hh24:mi:ss')

Het prestatieprobleem van de eerste oplossing kan worden omzeild door een index te maken op trunc(LAST_TRANSACTION_DATE) die door die uitdrukking zou kunnen worden gebruikt. Maar de uitdrukking LAST_TRANSACTION_DATE = '30-JUL-07' voorkomt ook een indexgebruik omdat het intern wordt verwerkt als to_char(LAST_TRANSACTION_DATE) = '30-JUL-07'

De belangrijke dingen om te onthouden:

  1. Vertrouw nooit op impliciete conversie van gegevenstypes. Het zal op een gegeven moment problemen geven. Vergelijk altijd de juiste gegevenstypen
  2. Oracle DATE kolommen bevatten altijd een tijd die deel uitmaakt van de vergelijkingsregels.


  1. Verbinding maken met een Oracle-database met behulp van SQLAlchemy

  2. Docker wacht tot postgresql actief is

  3. Excel-datumnummer wijzigen in Oracle-datum

  4. Oracle Dynamic Pivoting