日期格式符RR和YY的區別

來源:互聯網
上載者:User

標籤:

近來有一個應用,串連11g的庫,自身邏輯大致是根據日期和其他條件刪除表中對應的記錄,此處日期條件判斷未使用to_date(),其中日期和另外一些條件是個複合主鍵,然後再插入一條新記錄(此處日期欄位使用to_date(XX, ‘DDMONYY’))。在測試的時候,測試人員發現一個問題,先手工插入了一條2050年的記錄,然後執行應用,發現報主鍵衝突,再追查是因為原先的記錄並未刪除,導致新插入的記錄主鍵衝突,看起來很詭異的問題,為何沒有刪除舊的記錄?

原因就在於刪除的檢索條件中日期使用的是DDMONYY日期格式符,但插入的時候沒有用任何日期格式符,此時就會使用資料庫的預設日期格式符,即:

SELECT * FROM nls_database_parameters
WHERE parameter=‘NLS_DATE_FORMAT‘;

9i之後NLS_DATE_FORMAT的預設值就是DD-MON-RR。DDMON月和天的格式化字元都是相同的,對年的格式化字元都是使用的兩位,RR和YY,那麼現在的問題就是DDMONYY和DDMONRR中對年的判斷有何區別?

首先,看DD-MON-RR,以下是官方文檔的描述:

The RR Datetime Format Element

The RR datetime format element is similar to the YY datetime format element, but it provides additional flexibility for storing date values in other centuries. The RR datetime format element lets you store 20th century dates in the 21st century by specifying only the last two digits of the year.

RR日期格式符和YY日期格式符很相似,但是對於不同世紀,他提供了儲存日期值額外的擴充性。RR日期格式符可以讓你在21世紀通過僅僅指定年份的後兩位來儲存20世紀的日期。

If you use the TO_DATE function with the YY datetime format element, then the year returned always has the same first 2 digits as the current year. If you use the RR datetime format element instead, then the century of the return value varies according to the specified two-digit year and the last two digits of the current year.

如果在TO_DATE函數中使用YY格式符,那麼只會返回和當前年相同的前兩位年費數字。如果使用RR格式符,那就可以根據指定的兩位年份數字,還有當前年的後兩位元字,返回不同的值。

That is:

  • If the specified two-digit year is 00 to 49, then

    • If the last two digits of the current year are 00 to 49, then the returned year has the same first two digits as the current year.

    • If the last two digits of the current year are 50 to 99, then the first 2 digits of the returned year are 1 greater than the first 2 digits of the current year.

  • If the specified two-digit year is 50 to 99, then

    • If the last two digits of the current year are 00 to 49, then the first 2 digits of the returned year are 1 less than the first 2 digits of the current year.
    • If the last two digits of the current year are 50 to 99, then the returned year has the same first two digits as the current year.

如果指定的兩位年份數字是00-49,那麼

  1. 如果當前年的後兩位元字是00-49,則返回的年份和當前年的前兩位元字相同。
  2. 如果當前年的後兩位元字是50-99,則返回的年份前兩位元字會比當前年的前兩位元字大1。

如果指定的兩位年份數字是50-99,那麼

  1. 如果當前年份的後兩位元字是00-49,則返回的年份前兩位元字會比當前年的前兩位元字小1。
  2. 如果當前年的後兩位元字是50-99,則返回的年份和當前年的前兩位元字相同。

如下樣本:

  1. 假設以下查詢發生在1950-1999之間:

    SELECT TO_CHAR(TO_DATE(‘27-OCT-98’, ‘DD-MON-RR’), ‘YYYY’) “Year” FROM DUAL;

    1998

    SELECT TO_CHAR(TO_DATE(‘27-OCT-17’, ‘DD-MON-RR’), ‘YYYY’) “Year” FROM DUAL;

    2017

  2. 假設以下查詢發生在2000-2049之間:

    SELECT TO_CHAR(TO_DATE(‘27-OCT-98’, ‘DD-MON-RR’), ‘YYYY’) “Year” FROM DUAL;

    1998

    SELECT TO_CHAR(TO_DATE(‘27-OCT-17’, ‘DD-MON-RR’), ‘YYYY’) “Year” FROM DUAL;

    2017

不管是2000年之前還是之後執行SQL,查詢都會返回相同的值。使用RR日期格式符寫的SQL,可以根據不同的年份前兩位來返回相同的值。

接下來看看DDMONYY,提供的兩位年份數字,此時對於世紀的判斷就會和當前資料庫伺服器設定的世紀相同,例如現在是2015年,使用to_date(‘01JAN50’,’DDMONYY’),那麼存入的就是2050-01-01。

再回顧下開始提到的問題,
1. 測試人員手工插入一條2050年的記錄。
2. 應用首先執行刪除操作,此時日期條件沒用to_date(),直接用了’01JAN50’,預設使用的則是DDMONRR格式符,當前是2015年,因此實際刪除的條件是1950年的記錄。當前表中沒有1950年的記錄,因此刪除記錄條數是0。
3. 應用執行插入操作,此時使用的日期查詢條件是’01JAN50’,當前是2015年,因此實際要插入的是2015年的記錄。但由於表中已經存在一條2050年的記錄,因此會報主鍵衝突的錯誤。

總結起來,最直接的方式就是使用YYYY或RRRR全年份的表示方式,這樣不會有誤會,如果使用YY或RR兩位表示年份,那就要清楚這兩者的區別,以及自己的需求,畢竟Oracle也要根據規則來判斷兩位年份是哪個世紀的,因此需要選擇適合的方式,而且當一次交易中有多次增刪改日期條件的邏輯,那麼前後使用YY或RR要一致,否則就會因前後條件不一致,導致不同的結果,一個小小的日期格式,包含了不同的理解,顯現出了Oracle系統設計的精妙,也對使用者提出來一定的要求,原理比用法更重要。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

日期格式符RR和YY的區別

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.