web-dev-qa-db-fra.com

Format DATE par défaut d'Oracle

Première utilisation d'Oracle SQL (je suis habitué à MySQL). Je trouve des informations contradictoires sur le format de date par défaut. Après plusieurs tentatives d'utilisation de TO_DATE avec mes instructions INSERT INTO my_table, j'ai finalement trouvé la base de données que j'utilise attend DD-MON-YY (c'est-à-dire le 25 janvier 18). Pourtant, sur diverses pages de stackoverflow et d’autres, j’en vois qui disent que la valeur par défaut est AAAAMMJJ ou JJ/MM/AAAA ou AAAA-MM-JJ. Pourquoi autant d'informations contradictoires?

1
BigRedEO

Oracle, ainsi que d'autres bases de données, vous permet de définir le format par défaut. Hors de la boîte, le format est (généralement) DD-MON-RR, où "RR" fait référence à une année à deux chiffres. C'est un format plutôt moche, du point de vue de l'ambiguïté (année à deux chiffres?) Et de l'internationalisation (pour quels pays s'agit-il réellement par défaut?) Mais Oracle existe depuis très longtemps.

Les formats standard sont également définis par l'ISO, l'Organisation internationale de normalisation. Ils ont opté pour quelque chose de plus semblable à AAAA-MM-JJ. En réalité, les traits d'union sont facultatifs, mais je pense qu'ils rendent la date beaucoup plus lisible.

Oracle accepte les constantes dans ce format, si vous utilisez DATE:

select DATE '2018-01-25'

C'est très pratique. Premièrement, il est agréable d’appuyer des normes raisonnables. Deuxièmement, le code est sécurisé, quels que soient les paramètres d'internationalisation. Bien entendu, la documentation Oracle couvre cela en détail; ici est un endroit pour commencer.

2
Gordon Linoff

Une DATE n'a pas de format - elle est stockée en interne sous la forme 7 octets représentant l'année (2 octets) et le mois, le jour, l'heure, la minute et la seconde (1 octet chacun).

'25-JAN-18' n'est pas une date - c'est un littéral de texte.

Quand tu fais:

INSERT INTO table_name ( date_column ) VALUES ( '25-JAN-18' );

Oracle tentera d'être utile et effectuera une conversion implicite d'une chaîne en une date en utilisant le paramètre NLS_DATE_FORMAT pour la session de l'utilisateur en tant que modèle de format. Ainsi, votre déclaration sera implicitement convertie en:

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

Tout utilisateur peut définir ses paramètres NLS dans sa propre session (never doit donc se fier à la conversion implicite, chaque utilisateur pouvant définir un paramètre différent pour sa propre session et modifier les valeurs en cours de session). Au lieu de cela, vous devriez:

  • Utilisez un littéral Date:

    DATE '2018-01-25'
    
  • Utiliser un littéral d'horodatage

    TIMESTAMP '2018-01-25 01:23:45'
    
  • Utilisez TO_DATE( date_string, format_string [, nls_values] ) et utilisez explicitement un modèle de format:

    TO_DATE( '25-JUN-18', 'DD-MON-RR' )
    

Si vous voulez changer le NLS_DATE_FORMAT dans votre session, vous pouvez utiliser:

ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

Quel est le format de date par défaut?

Etant donné qu'une DATE n'a pas de format, cette question n'a pas de sens. Au lieu de cela si nous demandons:

Quel est le paramètre de session par défaut NLS_DATE_FORMAT qu'Oracle utilise pour convertir les chaînes et les dates?

Cela dépend du paramètre de session NLS_TERRITORY (cela dépend donc de l'endroit où vous vous trouvez dans le monde):

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;

Sort le format de date et la liste des territoires correspondant à ce format:

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
4
MT0

Les DATE sont des DATE - le format détermine le mode d'affichage de la DATE lorsque vous interrogez vos données.

Si vous ne fournissez pas de format et n'utilisez pas la fonction TO_CHAR, nous fournirons la DATE dans la valeur par défaut NLS_DATE_FORMAT - définie dans la base de données, mais pouvant également être spécifiée pour votre session.

Pour votre session - 

select * from NLS_SESSION_PARAMETERS
where PARAMETER = 'NLS_DATE_FORMAT';

Le mien est 'DD-MON-YYYY', donc quand je demande SYSDATE:

SQL> select sysdate from dual;

SYSDATE    
-----------
03-MAY-2018

Lorsque vous travaillez avec DATE, il est généralement préférable de ne PAS adopter un format DATE spécifique. Ainsi, lorsque les données INSERT ou SELECT avec les DATE sont à la fois, être EXPLICIT. Par exemple.

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

Maintenant, pour répondre à votre question - quel est le défaut? En fait ça dépend.

Il est dérivé de votre NLS_TERRITORY ( docs )

Toutefois, si vous vous souvenez des meilleures pratiques, et que vous n'assumez jamais la valeur par défaut, et que vous utilisez explicitement vos formats de date lorsque vous travaillez avec des DATE, vous devriez être d'accord. 

Le meilleur guide que nous avons pour ce sujet est notre Guide d’assistance à la mondialisation. Ceci est la section qui vous intéresse.

3
thatjeffsmith