问题
I've run into a weird situation. Could someone explain why comparison between timestamp and timestamp behaves as below (it depends on session timezone...). In addition outputed values are identical in all cases. It looks like timestamp inherits timezone from the session for comparison purposes, but for printing it does not?
Queries:
alter session set time_zone = '-6:0';
select cast(systimestamp as timestamp), systimestamp, case when cast(systimestamp as timestamp) < systimestamp then 'timestamp < systm' else 'timestamp >= systm' end as cmp from dual;
alter session set time_zone = '1:0';
select cast(systimestamp as timestamp), systimestamp, case when cast(systimestamp as timestamp) < systimestamp then 'timestamp < systm' else 'timestamp >= systm' end as cmp from dual;
output:
CAST(SYSTIMESTAMPASTIMESTAMP) SYSTIMESTAMP CMP
----------------------------- ----------------------------------- ------------------
14/02/06 21:22:05,319973000 14/02/06 21:22:05,319973000 -06:00 timestamp >= systm
session SET altered.
CAST(SYSTIMESTAMPASTIMESTAMP) SYSTIMESTAMP CMP
----------------------------- ----------------------------------- ------------------
14/02/06 21:22:06,057183000 14/02/06 21:22:06,057183000 -06:00 timestamp < systm
Database is in -6 timezone. Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
回答1:
Look at this: https://docs.oracle.com/cd/B12037_01/server.101/b10749/ch4datet.htm#1006334
When you compare date and timestamp values, Oracle converts the data to the more precise datatype before doing the comparison. For example, if you compare data of TIMESTAMP WITH TIME ZONE datatype with data of TIMESTAMP datatype, Oracle converts the TIMESTAMP data to TIMESTAMP WITH TIME ZONE, using the session time zone. The order of precedence for converting date and timestamp data is as follows: 1. DATE 2. TIMESTAMP 3. TIMESTAMP WITH LOCAL TIME ZONE 4. TIMESTAMP WITH TIME ZONE For any pair of datatypes, Oracle converts the datatype that has a smaller number in the preceding list to the datatype with the larger number.
回答2:
SYSTIMESTAMP
returns a TIMESTAMP WITH TIME ZONE
datatype. Looks like Oracle converts the TIMESTAMP
to an TIMESTAMP WITH TIME ZONE
datatype for comparison, actualy Oracle performs this:
SELECT
CASE
WHEN CAST(CAST(SYSTIMESTAMP AS TIMESTAMP) AS TIMESTAMP WITH TIME ZONE) < SYSTIMESTAMP
THEN 'timestamp < systm'
ELSE 'timestamp >= systm'
END AS cmp
FROM dual;
For conversion it takes the SESSION Timezone, you can check it with this query:
SELECT
EXTRACT(TIMEZONE_HOUR FROM CAST(CAST(SYSTIMESTAMP AS TIMESTAMP) AS TIMESTAMP WITH TIME ZONE)) AS TZ_HOUR
FROM dual;
You can discuss if this makes sense or not. For a correct conversion you better use FROM_TZ
function, then it is under your control. SYSTIMESTAMP
returns timestamp in DB timezone, so proper statement would be this one:
SELECT FROM_TZ(LOCALTIMESTAMP, DBTIMEZONE), SYSTIMESTAMP,
CASE FROM_TZ(LOCALTIMESTAMP, DBTIMEZONE) < SYSTIMESTAMP THEN
...
来源:https://stackoverflow.com/questions/21618732/timezone-dependant-systimestamp-and-timestamp-comparison-on-oracle