我在 Java 代碼中使用下面的 SQL 來更新 Oracle DB 中的日期。
UPDATE CUS_LOGS SET START_DATE=to_date(systimestamp 3,'DD-MON-RRRR'), END_DATE=to_date(systimestamp 21921,'DD-MON-RRRR')
WHERE CUS_ID IN ('9b90cb8175ba0ca60175ba12d8711006');
我的期望是:
START_DATE = 05-NOV-2022
END_DATE = 08-NOV-2082.
但是我看到的結果是
START_DATE = 05-NOV-2022
END_DATE = 08-NOV-1982 **********
顯然 iisue 發生在日期過去時31-12-2049。即 9922從今天開始添加(2022 年 2 月 11 日)
uj5u.com熱心網友回復:
問題是您依賴于隱式轉換,它使用您的 NLS 設定,將日期格式化為具有 2 位數年份的字串。
如果您的 NLS_DATE_FORMAT 正在DD-MON-RR或DD-MON-YY正在做
to_date(systimestamp 3,'DD-MON-RRRR')
真的在做類似的事情:
to_date(to_char(cast(systimestamp as date) 3,'DD-MON-RR','DD-MON-RRRR')
這意味著它嘗試使用掩碼“DD-MON-RRRR”將字串“08-NOV-82”轉換為日期。RRRR意味著像 82 這樣的2 位數年份被解釋為 1982 - 這就是您所看到的。使用DD-MON-YYYY會更糟,因為這會將 82 解釋為 0082。
alter session set nls_date_format = 'DD-MON-RR'
select
to_date(sysdate 3,'DD-MON-RRRR') as a,
to_char(to_date(sysdate 3,'DD-MON-RRRR'), 'YYYY-MM-DD') as b,
to_date(sysdate 21921,'DD-MON-RRRR') c,
to_char(to_date(sysdate 21921,'DD-MON-RRRR'), 'YYYY-MM-DD') as d,
to_date(sysdate 3,'DD-MON-YYYY') as e,
to_char(to_date(sysdate 3,'DD-MON-YYYY'), 'YYYY-MM-DD') as f,
to_date(sysdate 21921,'DD-MON-YYYY') as g,
to_char(to_date(sysdate 21921,'DD-MON-YYYY'), 'YYYY-MM-DD') as h
from dual
| 一個 | 乙 | C | D | 乙 | F | G | H |
|---|---|---|---|---|---|---|---|
| 05-11-22 | 2022-11-05 | 82 年 11 月 8 日 | 1982-11-08 | 05-11-22 | 0022-11-05 | 82 年 11 月 8 日 | 0082-1??1-08 |
因此,您需要將日期顯式轉換為具有 4 位數年份的字串,然后再次將其轉換回來......
但是您不需要進行任何轉換。只需將天數添加到時間戳 - 隱式地將其轉換為日期,但安全 - 得到你想要的結果:
alter session set nls_date_format = 'YYYY-MM-DD'
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS TZR'
select systimestamp,
systimestamp 3,
systimestamp 21921
from dual
| 系統時間戳 | 系統時間戳 3 | 系統時間戳 21921 |
|---|---|---|
| 2022-11-02 10:42:24 00:00 | 2022-11-05 | 2082-1??1-08 |
但是在這里使用沒有意義systimestamp,您甚至可以通過使用來避免隱式轉換sysdate:
select sysdate,
sysdate 3,
sysdate 21921
from dual
| 日期 | 日期 3 | 系統日期 21921 |
|---|---|---|
| 2022-11-02 | 2022-11-05 | 2082-1??1-08 |
小提琴
您似乎正在進行轉換以洗掉當前日期/時間的時間部分 - 或者更準確地說,將其設定為午夜,因為日期總是有時間。但是你可以用trunc().
因此,總而言之,您的更新宣告應該是:
UPDATE CUS_LOGS SET START_DATE=trunc(sysdate) 3, END_DATE=trunc(sysdate) 21921
WHERE CUS_ID IN ('9b90cb8175ba0ca60175ba12d8711006');
您的結束日期大約提前 60 年;您可能想要使用add_months(trunc(sysdate), 60*12)然后添加任何額外的天數 - 也許只是保留 3、 內部或外部add_months(),或兩者兼而有之;無論如何,今天add_months(trunc(sysdate) 3, 60*12) 3會給出與 , 相同的結果。 21921但目前還不清楚你在做什么......
您可以添加間隔而不是天數,這更明確一些;但這對于添加月/年效果不太好,因為它可能導致無效日期錯誤,例如,如果您嘗試將年份間隔添加到 2 月 29 日。
uj5u.com熱心網友回復:
您可以使用以下方法簡化查詢并防止隱式時間戳到日期到字串轉換(如@Alex Poole 所述)的問題:
UPDATE CUS_LOGS
SET START_DATE = TRUNC(SYSDATE) INTERVAL '3' DAY,
END_DATE = ADD_MONTHS(TRUNC(SYSDATE), 60*12) INTERVAL '6' DAY
WHERE CUS_ID = '9b90cb8175ba0ca60175ba12d8711006';
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/525616.html
標籤:爪哇sql甲骨文弹簧靴
上一篇:SQL狀態:90057,訊息:未找到約束“PRIMARYKEY|UNIQUE(USERNAME)”;SQL陳述句:
