Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle-Zeitstempel mit transparenter Übersetzung der lokalen Zeitzonenwerte

TIMESTAMP WITH LOCAL TIME ZONE funktioniert so:Wenn Sie in Ihrer Anwendung mit Zeitzonen arbeiten müssen, dann ist ein üblicher Ansatz

Genau so funktioniert TIMESTAMP WITH LOCAL TIME ZONE funktioniert - der einzige Unterschied ist

Aus diesem Grund können Sie DBTIMEZONE nicht ändern (mit ALTER DATABASE SET TIME_ZONE='...'; ) in Ihrer Datenbank nicht mehr, wenn die Datenbank eine Tabelle mit einem TIMESTAMP WITH LOCAL TIME ZONE enthält Spalte und die Spalte enthält Daten.

SYSTIMESTAMP wird in der Zeitzone des Betriebssystems des Datenbankservers zurückgegeben. DBTIMEZONE ist nicht die Zeitzone von SYSTIMESTAMP oder SYSDATE .

DBTIMEZONE definiert das interne Speicherformat von TIMESTAMP WITH LOCAL TIME ZONE Datentypspalten. Vergiss das, ich kann mir keinen Anwendungsfall vorstellen, in dem du es brauchen würdest.

Eigentlich entspricht Ihre Tabelle dieser Auswahl:

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;

Wenn Sie CAST({time without time zone} with local time zone) machen dann versuchen Sie, einen Datums-/Uhrzeitwert ohne Zeitzoneninformationen in einen Datums-/Uhrzeitwert mit Zeitzone umzuwandeln. Dies ist prinzipiell nicht möglich, da Oracle die Zeitzoneninformationen fehlen, Oracle also von einer Zeitzone ausgeht. Wenn Sie eine solche Umwandlung vornehmen, betrachtet Oracle immer {Zeit ohne Zeitzone} als in SESSIONTIMEZONE angegeben (im Moment der Umwandlung).

Also CAST(sysdate AS timestamp(0) with local time zone) entspricht

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

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

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

Für SYSDATE das ist eigentlich falsch, weil SYSDATE wird in der Zeitzone des Betriebssystems des Datenbankservers angegeben, nicht in SESSIONTIMEZONE. Bei der zweiten hängt es von Ihrer Absicht ab, ob das Ergebnis richtig ist oder nicht.

SYSTIMESTAMP gibt den Wert TIMESTAMP WITH TIME ZONE zurück , es ist immer unabhängig von Ihrer aktuellen SESSIONTIMEZONE . Aber wenn Sie in TIMESTAMP WITH LOCAL TIME ZONE umwandeln es wird natürlich in Ihre aktuelle lokale Zeitzone umgerechnet. Sie können auch CURRENT_TIMESTAMP verwenden oder SYSTIMESTAMP AT LOCAL was mehr oder weniger dasselbe tut.

Dieser Code

scheint falsch zu sein. Ergebnis sollte

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

Die Unterschiede sehen so aus, wie sie sein sollten, aber die absoluten Werte scheinen "gefälscht" zu sein (oder es gibt ein echtes Problem mit Ihrer Datenbank).