Oracle
 sql >> Database >  >> RDS >> Oracle

Il timestamp Oracle con il fuso orario locale valorizza la traduzione trasparente

TIMESTAMP WITH LOCAL TIME ZONE funziona in questo modo:quando devi lavorare con i fusi orari nella tua applicazione, un approccio comune è

Ecco esattamente come TIMESTAMP WITH LOCAL TIME ZONE funziona - l'unica differenza è

Per questo motivo non puoi modificare DBTIMEZONE (con ALTER DATABASE SET TIME_ZONE='...'; ) sul tuo database più se il database contiene una tabella con un TIMESTAMP WITH LOCAL TIME ZONE colonna e la colonna contiene dati.

SYSTIMESTAMP viene ripristinato nel fuso orario del sistema operativo del server di database. DBTIMEZONE è non il fuso orario di SYSTIMESTAMP o SYSDATE .

DBTIMEZONE definisce il formato di memoria interna di TIMESTAMP WITH LOCAL TIME ZONE colonne del tipo di dati. Dimentica questo, non riesco a immaginare nessun caso d'uso in cui ne avresti bisogno.

In realtà la tua tabella è equivalente a questa selezione:

select 
   CAST(systimestamp AS timestamp(0) with local time zone) as SYSTIMESTAMP_COL,
   CAST(sysdate AS timestamp(0) with local time zone) as SYSDATE_COL,
   CAST(current_timestamp AS timestamp(0) with local time zone) as CURRENT_TIMESTAMP_COL,
   CAST(timestamp '2017-03-15 19:02:00' AS timestamp(0) with local time zone) as DATE_COL
from dual;

Quando crei CAST({time without time zone} with local time zone) quindi si tenta di convertire un valore di data/ora senza alcuna informazione sul fuso orario in un valore di data/ora con fuso orario. In linea di principio ciò non è possibile perché Oracle non dispone delle informazioni sul fuso orario, quindi Oracle presume un fuso orario. Se esegui tale cast, Oracle considera sempre {time without time zone} come indicato in SESSIONTIMEZONE (nel momento della conversione).

Quindi CAST(sysdate AS timestamp(0) with local time zone) è equivalente a

CAST(FROM_TZ(TO_TIMESTAMP(SYSDATE), SESSIONTIMEZONE) AS TIMESTAMP(0) WITH LOCAL TIME ZONE)` 

risp. CAST(timestamp '2017-03-15 19:02:00' AS timestamp(0) with local time zone) significa

CAST(FROM_TZ(TIMESTAMP '2017-03-15 19:02:00', SESSIONTIMEZONE) AS TIMESTAMP(0) WITH LOCAL TIME ZONE)

Per SYSDATE questo è effettivamente sbagliato, perché SYSDATE viene fornito nel fuso orario del sistema operativo del server di database non in SESSIONTIMEZONE. Per il secondo dipende dalla tua intenzione se il risultato è corretto o meno.

SYSTIMESTAMP restituisce il valore TIMESTAMP WITH TIME ZONE , è sempre indipendente dal tuo SESSIONTIMEZONE corrente . Ma se converti in TIMESTAMP WITH LOCAL TIME ZONE viene convertito nel tuo attuale fuso orario locale, ovviamente. Puoi anche usare CURRENT_TIMESTAMP o SYSTIMESTAMP AT LOCAL che fa più o meno lo stesso.

Questo codice

sembra essere sbagliato. Il risultato dovrebbe essere

-- SYSTIMESTAMP_COL                   15/03/2017 16:01:14
-- SYSDATE_COL                        15/03/2017 19:01:14
-- CURRENT_TIMESTAMP_COL              15/03/2017 16:01:14
-- DATE_COL                           15/03/2017 19:02:00

Le differenze sembrano come dovrebbero essere ma i valori assoluti sembrano essere "falsi" (o c'è un vero problema con il tuo database).