第一次使用Oracle SQL(我习惯使用MySQL)。我发现有关默认日期格式的信息存在冲突。在几次尝试使用我的INSERT INTO my_table语句的TO_DATE之后,我终于找到了我正在使用的数据库预期DD-MON-YY(即25-JAN-18)。然而,在stackoverflow和其他地方的各个页面上,我看到一些说默认为YYYYMMDD或DD / MM / YYYY或YYYY-MM-DD。为什么这么多相互矛盾的信息?
答案 0 :(得分:6)
DATE
没有格式 - 它在内部存储为7-bytes,代表年份(2个字节)和月,日,小时,分钟和秒(每个1个字节)。
'25-JAN-18'
不是日期 - 它是文字文字。
当你这样做时:
INSERT INTO table_name ( date_column ) VALUES ( '25-JAN-18' );
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' )
)
);
任何用户都可以在他们自己的会话中设置他们的NLS参数(因此你应该从不>依赖于隐式转换,因为每个用户可以为自己的会话设置不同的设置,并且可以在会话期间更改值)。相反,你应该:
使用日期文字:
DATE '2018-01-25'
使用时间戳文字
TIMESTAMP '2018-01-25 01:23:45'
使用TO_DATE( date_string, format_string [, nls_values] )
并明确使用格式模型:
TO_DATE( '25-JUN-18', 'DD-MON-RR' )
如果您确实要更改会话中的NLS_DATE_FORMAT
,则可以使用:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
默认日期格式是什么?
由于DATE
没有格式,因此这个问题没有意义。相反,如果我们问:
Oracle用于在字符串和日期之间进行转换的默认
NLS_DATE_FORMAT
会话参数是什么?
这取决于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;
输出与该格式对应的日期格式和地区列表:
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
答案 1 :(得分:5)
Oracle以及其他数据库允许您设置默认格式。开箱即用,格式为(通常)DD-MON-RR,其中“RR”表示两位数的年份。从模糊性(两位数年份?)和国际化(对于哪些国家实际上是默认的?)来看,这是一种非常糟糕的格式。但甲骨文已经存在了很长时间。
标准格式也由国际标准组织ISO定义。他们选择了更像YYYY-MM-DD的东西。实际上,连字符是可选的,但我认为它们使日期更具可读性。
如果您使用DATE
:
select DATE '2018-01-25'
这非常方便。首先,支持合理的标准是件好事。其次,无论国际化设置如何,代码都是安全的。 Oracle文档当然详细介绍了这一点; here是一个值得一去的地方。
答案 2 :(得分:5)
DATE是DATE - 格式决定了查询数据时DATE的显示方式。
如果您没有提供格式并使用TO_CHAR函数,我们将在默认的NLS_DATE_FORMAT中提供DATE - 这是在数据库中定义的,但也可以为您的会话指定。
为您的会议 -
select * from NLS_SESSION_PARAMETERS
where PARAMETER = 'NLS_DATE_FORMAT';
我的是DD-MON-YYYY',所以当我查询SYSDATE:
SQL> select sysdate from dual;
SYSDATE
-----------
03-MAY-2018
使用DATE时,通常最佳做法是不假设特定的DATE格式。因此当使用DATE进行INSERT或SELECT数据时,应该是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
现在,回答你的问题 - 默认是什么?嗯,这取决于。
它来自您的NLS_TERRITORY(docs)
但是,如果你还记得最佳做法,并且你从不假设默认值是什么,并且在使用DATE时你明确了日期格式,那么你应该没问题。
我们为此主题提供的最佳指南是“全球化支持指南”。 This is the section of interest to you.
答案 3 :(得分:0)
只有在使用TO_DATE
插入日期时才需要注意的事项是你如何解析它。
实施例
什么行不通
to_date('31-03-2016','dd-mon-yyyy')
什么会起作用
to_date('31-03-2016','dd-mm-yyyy')
to_date('31-Mar-2016','dd-Mon-yyyy')
您传递给to_date
的日期和格式应该匹配
31 - dd
Mar - Mon
2016 - yyyy