Oracle的默认DATE格式

Big*_*dEO 7 sql oracle date

第一次使用Oracle SQL(我已经习惯了MySQL)。我发现有关默认日期格式的信息冲突。经过多次尝试将TO_DATE与INSERT INTO my_table语句一起使用后,我终于找到了我正在使用的数据库,该数据库预期使用DD-MON-YY(即25-JAN-18)。但是在stackoverflow和其他地方的各个页面上,我看到一些说默认值为YYYYMMDD或DD / MM / YYYY或YYYY-MM-DD的页面。为什么会有这么多相互矛盾的信息?

MT0*_*MT0 9

A DATE没有格式-内部存储为7个字节,代表年(2个字节)以及月,日,时,分和秒(各1个字节)。

'25-JAN-18' 不是日期-它是文本文字。

当您这样做时:

INSERT INTO table_name ( date_column ) VALUES ( '25-JAN-18' );
Run Code Online (Sandbox Code Playgroud)

Oracle将尝试提供帮助,并使用NLS_DATE_FORMAT用户会话的参数作为格式模型来执行从字符串到日期的隐式转换。因此,您的语句将隐式转换为:

INSERT INTO table_name ( date_column ) VALUES (
  TO_DATE(
    '25-JAN-18',
    ( SELECT VALUE FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT' )
  )
);
Run Code Online (Sandbox Code Playgroud)

任何用户都可以在自己的会话中设置其NLS参数(因此,您永远不要依赖隐式转换,因为每个用户可以为自己的会话设置不同的设置,并且可以在会话中更改值)。相反,您应该:

如果您确实要更改NLS_DATE_FORMAT会话中的,则可以使用:

ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
Run Code Online (Sandbox Code Playgroud)

默认日期格式是什么?

由于a DATE没有格式,因此这个问题没有意义。相反,如果我们问:

NLS_DATE_FORMATOracle用于在字符串和日期之间转换的默认会话参数是什么?

它取决于NLS_TERRITORY会话参数(因此取决于您在世界上的位置):

SET SERVEROUTPUT ON;

VARIABLE cur REFCURSOR;

DECLARE
  territories SYS.ODCIVARCHAR2LIST;
  formats     SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST();
BEGIN
  select value
  BULK COLLECT INTO territories
  from v$nls_valid_values
  where parameter = 'TERRITORY'
  order by value;

  formats.EXTEND( territories.COUNT );
  FOR i IN 1 .. territories.COUNT LOOP
    EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_TERRITORY='''||territories(i)||'''';

    SELECT value
    INTO   formats(i)
    FROM   NLS_SESSION_PARAMETERS
    WHERE  PARAMETER = 'NLS_DATE_FORMAT';
  END LOOP;

  OPEN :cur FOR
  SELECT CAST( f.format AS VARCHAR2(12) ) AS format,
         LISTAGG( t.territory, ', ' ) WITHIN GROUP ( ORDER BY t.territory ) AS territories
  FROM   ( SELECT ROWNUM AS rn, COLUMN_VALUE AS territory FROM TABLE( territories ) ) t
         INNER JOIN
         ( SELECT ROWNUM AS rn, COLUMN_VALUE AS format FROM TABLE( formats ) ) f
         ON ( f.rn = t.rn )
  GROUP BY f.format;
END;
/

PRINT :cur;
Run Code Online (Sandbox Code Playgroud)

输出日期格式和与该格式对应的地区列表:

FORMAT       TERRITORIES
------------ ------------------------------------------------------------------
DD MON RRRR  THAILAND
DD-MM-RR     ALGERIA, BAHRAIN, INDIA, MOROCCO, THE NETHERLANDS, TUNISIA
DD-MM-RRRR   BANGLADESH, INDONESIA, ROMANIA, VIETNAM
DD-MON-RR    AMERICA, CHINA, HONG KONG, IRELAND, ITALY, PAKISTAN, TAIWAN,
             UNITED KINGDOM
DD-MON-RRRR  ISRAEL
DD.MM.RR     AUSTRIA, BELARUS, CIS, CROATIA, CZECH REPUBLIC, CZECHOSLOVAKIA,
             GERMANY, RUSSIA, SLOVAKIA, SLOVENIA, SWITZERLAND
DD.MM.RRRR   ALBANIA, AZERBAIJAN, ESTONIA, FINLAND, FYR MACEDONIA, ICELAND,
             KAZAKHSTAN, MACEDONIA, NORWAY, SERBIA AND MONTENEGRO, UKRAINE,
             YUGOSLAVIA
DD.MM.RRRR.  MONTENEGRO, SERBIA
DD.fmMM.RRRR ARMENIA
DD/MM/RR     AFGHANISTAN, BELGIUM, BRAZIL, CAMEROON, CATALONIA, CHILE, COLOMBIA,
             CONGO BRAZZAVILLE, CONGO KINSHASA, COSTA RICA, CYPRUS, DJIBOUTI,
             EGYPT, EL SALVADOR, FRANCE, GABON, GREECE, GUATEMALA, HONDURAS,
             IRAQ, IVORY COAST, JORDAN, KUWAIT, LEBANON, LIBYA, LUXEMBOURG,
             MAURITANIA, MEXICO, NEW ZEALAND, NICARAGUA, OMAN, PANAMA, PERU,
             PUERTO RICO, QATAR, SAUDI ARABIA, SINGAPORE, SOMALIA, SPAIN, SUDAN,
             SYRIA, UNITED ARAB EMIRATES, URUGUAY, VENEZUELA, YEMEN
DD/MM/RRRR   ARGENTINA, BAHAMAS, BERMUDA, ECUADOR, MALAYSIA, SENEGAL, TURKEY,
             UGANDA, ZAMBIA
DD/MON/RR    AUSTRALIA, SOUTH AFRICA, UZBEKISTAN
DD/fmMM/RRRR LAOS, NIGERIA
MM/DD/RRRR   PHILIPPINES
RR-MM-DD     CANADA, DENMARK, JAPAN
RR-MON-DD    HUNGARY
RR.MM.DD     PORTUGAL
RR/MM/DD     KOREA, POLAND
RRRR-MM-DD   BULGARIA, SWEDEN
RRRR-fmMM-DD CAMBODIA
RRRR.MM.DD   LATVIA, LITHUANIA
RRRR/fmMM/fm IRAN, SRI LANKA
fmDD-MM-RR   BOLIVIA
fmDD/MM/RR   PARAGUAY
fmDD/MM/RRRR BELIZE, ETHIOPIA, MALTA, NEPAL
fmDD/fmMM/RR MALDIVES
fmMM.DD.RRRR BOSNIA AND HERZEGOVINA
fmMM/DD/RRRR KENYA, TANZANIA
Run Code Online (Sandbox Code Playgroud)


Gor*_*off 8

Oracle和其他数据库允许您设置默认格式。开箱即用的格式(通常是DD-MON-RR),其中“ RR”表示两位数的年份。从歧义(两位数年份?)和国际化(实际上是默认的国家/地区)的角度来看,这是一种非常糟糕的格式。但是Oracle已经存在了很长时间。

标准格式也由国际标准组织ISO定义。他们选择了类似YYYY-MM-DD的产品。实际上,连字符是可选的,但我认为它们使日期更具可读性。

如果您使用以下格式,则Oracle接受这种格式的常量DATE

select DATE '2018-01-25'
Run Code Online (Sandbox Code Playgroud)

这非常方便。首先,支持合理的标准非常好。其次,无论国际化设置如何,代码都是安全的。Oracle文档当然会对此进行详细介绍。是一个起点。

  • 谢谢 - 我找到的第一个可以理解的解释! (3认同)

tha*_*ith 5

DATE是DATE-格式决定了查询数据时DATE的显示方式。

如果您不提供格式并使用TO_CHAR函数,我们将以默认NLS_DATE_FORMAT的形式提供DATE-该默认值在数据库中定义,但也可以为您的会话指定。

对于您的会话-

select * from NLS_SESSION_PARAMETERS
where PARAMETER = 'NLS_DATE_FORMAT';
Run Code Online (Sandbox Code Playgroud)

我的是“ DD-MON-YYYY”,所以当我查询SYSDATE时:

SQL> select sysdate from dual;

SYSDATE    
-----------
03-MAY-2018
Run Code Online (Sandbox Code Playgroud)

使用DATE时,通常最好的做法是不采用特定的DATE格式。因此,当同时使用INSERT或SELECT数据和DATE时,请使用EXPLICIT。例如。

SQL> drop table JUST_DATES;

Table JUST_DATES dropped.

SQL> 
SQL> create table JUST_DATES (
  2      DATE1 date
  3  );

Table JUST_DATES created.

SQL> 
SQL> insert   into JUST_DATES values ( to_date('01-01-2018','MM-DD-YYYY') );

1 row inserted.

SQL> 
SQL> select to_char(
  2      DATE1,
  3      'MON/DD/RR'
  4  )
  5    from JUST_DATES;

TO_CHAR(DATE1,'MON
------------------
JAN/01/18
Run Code Online (Sandbox Code Playgroud)

现在,回答您的问题-默认值是什么?这得看情况。

它来自您的NLS_TERRITORY(docs

但是,如果您记住最佳实践,并且从未假设默认值是什么,并且在使用DATE时明确使用了日期格式,则应该没事。

关于该主题的最佳指南是《全球化支持指南》。这是您感兴趣的部分。