初めてOracle SQLを使用します(MySQLに慣れています)。デフォルトの日付形式とは矛盾する情報を見つけています。 INSERT INTO my_tableステートメントでTO_DATEを使用しなければならないいくつかの試行の後、DD-MON-YY(つまり25-JAN-18)を想定している使用中のデータベースがようやく見つかりました。しかし、stackoverflowなどのさまざまなページに、デフォルトがYYYYMMDDまたはDD/MM/YYYYまたはYYYY-MM-DDと書かれているものがあります。なぜ相反する情報が非常に多いのですか?
Oracleおよび他のデータベースでは、デフォルトの形式を設定できます。初期設定では、形式は(通常)DD-MON-RRです。ここで、「RR」は2桁の年を表します。これは、あいまいさ(2桁の年?)と国際化(実際にはどの国がデフォルトですか?)の観点から、かなりお粗末な形式です。しかし、Oracleは長い間使用されてきました。
標準形式は、ISO(国際標準化機構)によっても定義されています。彼らはYYYY-MM-DDのようなものに落ち着きました。実際には、ハイフンはオプションですが、日付をより読みやすくすると思います。
DATE
を使用する場合、Oracleはこの形式の定数を受け入れます。
select DATE '2018-01-25'
これは非常に便利です。まず、合理的な標準をサポートすることは素晴らしいことです。第二に、国際化の設定に関係なく、コードは安全です。もちろん、Oracleのドキュメントでこれについて詳しく説明しています。 here は開始する1つの場所です。
DATE
にはフォーマットはありません。年(2バイト)および月、日、時間、分、秒(各1バイト)を表す 7-byte として内部的に保存されます。
_'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パラメータを設定できます(したがって、各ユーザーは独自のセッションに対して異なる設定を持つことができるため、never暗黙的な変換に依存する必要がありますセッション中に値を変更できます)。代わりに:
日付リテラルを使用します。
_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
_
日付は日付です-データを照会したときに日付がどのように表示されるかは、形式によって決まります。
フォーマットを指定せずに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形式を想定しないことがベストプラクティスです。そのため、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
さて、あなたの質問に答えるために-デフォルトは何ですか?まあ、それは依存します。
NLS_TERRITORYから派生しています( docs )
ただし、ベストプラクティスを覚えていて、デフォルトが何であるかを決して想定しておらず、DATEを扱う際に日付形式を明示している場合は、大丈夫です。
このトピックに最適なガイドは、グローバリゼーションサポートガイドです。 これはあなたの興味のあるセクションです。
_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
_