根據H2 檔案,在Oracle兼容模式下:
DATE 資料型別被視為 TIMESTAMP(0) 資料型別。
同時,DATEOracleTIMESTAMP(0)中的資料型別也不一樣。比較:
SELECT CAST(SYSDATE AS TIMESTAMP(0)), CAST(SYSDATE AS DATE) from dual
給
25-MAR-22 13.07.42.000000000 25-MAR-22
分別。
特別是,這種奇怪的DATEas處理會TIMESTAMP(0)影響 H2 如何計算兩個日期之間的差異。同樣,在 Oracle 中:
SELECT CAST(TO_DATE('2022-01-05', 'YYYY-MM-DD') AS TIMESTAMP(0)) - CAST(TO_DATE('2022-01-01', 'YYYY-MM-DD') AS TIMESTAMP(0)) from dual
給
04 00:00:00.000000
和
SELECT CAST(TO_DATE('2022-01-05', 'YYYY-MM-DD') AS DATE) - CAST(TO_DATE('2022-01-01', 'YYYY-MM-DD') AS DATE) from dual
只產生:
4
顯然,對于 H2,上述兩個查詢都會以納秒而不是預期的天數產生結果。
那么,這是一個 H2 錯誤還是我遺漏了什么?
uj5u.com熱心網友回復:
同時,
DATEOracleTIMESTAMP(0)中的資料型別不一樣
Oracle 與許多其他 RDBMS 的不同之處在于其DATE資料型別始終包含日期和時間組件。它的實施早于 ANSI 標準。
在 Oracle 中,如果您有表:
CREATE TABLE table_name (ts TIMESTAMP(0), dt DATE);
并插入資料:
INSERT INTO table_name (ts, dt) VALUES (SYSDATE, SYSDATE);
然后您可以查看使用該DUMP函式存盤的二進制資料:
SELECT DUMP(ts) AS dump_ts,
DUMP(dt) AS dump_dt
FROM table_name;
哪個輸出:
DUMP_TS DUMP_DT Typ=180 Len=7: 120,122,3,25,15,13,??37 Typ=12 Len=7: 120,122,3,25,15,13,??37
然后您可以看到它們都存盤為 7 位元組的二進制值:
120= 世紀 100122= 世紀 1003= 月25= 天15= 小時 113= 分鐘 137= 秒 1
并且二進制值是相同的(唯一的區別在于Typ180 =TIMESTAMP和 12 =的元資料DATE)。
實際上,它們的存盤方式相同。
db<>在這里擺弄
However
The side-effects of a TIMESTAMP vs. a DATE data type in Oracle may lead to different effects.
When you subtract a
TIMESTAMPand either aTIMESTAMPor aDATEthen the return value is anINTERVAL DAY TO SECONDdata type.When you subtract a
DATEand aDATEthen the default return value is aNUMBERrepresenting the number of days difference.When you display a
TIMESTAMPthen the client application you are using may default to using theNLS_TIMESTAMP_FORMATsession parameter to format the timestamp as a string and the default for this parameter will typically show date, time and fractional seconds.When you display a
DATEthen the client application you are using may default to using theNLS_DATE_FORMATsession parameter to format the date as a string and the default for this parameter will show date but not time (and there will never be any fractional seconds to show). Just because the client application may chose not to show the time component does not mean that the time component does not exist.If you set the session parameters using:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'; ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS';Then, provided your client application is using those parameters to format them, they will display identically.
The problem you are seeing with the difference in Oracle is due to these side effects.
uj5u.com熱心網友回復:
如果問題是
那么,這是一個 H2 錯誤還是我遺漏了什么?
答案是:不,這不是錯誤,而您錯過的事實是,H2 中的兼容性模式就是這樣-嘗試以最小的努力達到與不同資料庫的最大兼容性。H2 不是這些資料庫的任何非標準特性(怪癖)的模擬器。在這種特殊情況下,要實作相同的行為,需要引入新的非標準資料型別,這超出了“最小努力”的水平。
uj5u.com熱心網友回復:
第一個查詢中的值輸出的不同在于會話的 NLS 設定。這些控制日期和時間戳的顯示格式:
sho parameter nls_date_format
NAME TYPE VALUE
--------------- ------ -----------
nls_date_format string DD-MON-YYYY
sho parameter nls_timestamp_format
NAME TYPE VALUE
-------------------- ------ -------------------------
nls_timestamp_format string DD-MON-YYYY HH24.MI.SSXFF
SELECT CAST(SYSDATE AS TIMESTAMP(0)), CAST(SYSDATE AS DATE) from dual;
CAST(SYSDATEASTIMESTAMP(0)) CAST(SYSDAT
------------------------------ -----------
25-MAR-2022 12.18.24.000000000 25-MAR-2022
如果將它們更改為相同的格式,則兩個運算式都會回傳相同的結果:
alter session set nls_date_format = 'DD-MON-YYYY HH24:MI:SS';
alter session set nls_timestamp_format = 'DD-MON-YYYY HH24:MI:SS';
SELECT CAST(SYSDATE AS TIMESTAMP(0)), CAST(SYSDATE AS DATE) from dual;
CAST(SYSDATEASTIMEST CAST(SYSDATEASDATE)
-------------------- --------------------
25-MAR-2022 12:17:43 25-MAR-2022 12:17:43
所以它們都包含完整的日期 時間,沒有小數秒。
請注意, whiledate和timestamp(0)具有相同的精度,因為您的進一步示例表明它們的作業方式不同:
- 從另一個中減去一個
date回傳值之間的天數作為number timestamp從 a 中減去 adate或timestamp回傳一個interval
所以結果:
SELECT CAST(TO_DATE('2022-01-05', 'YYYY-MM-DD') AS DATE) - CAST(TO_DATE('2022-01-01', 'YYYY-MM-DD') AS DATE) from dual
是4天。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/451456.html
