Oracle
 sql >> Base de données >  >> RDS >> Oracle

Oracle 10g acceptant l'année à 5 chiffres dans une date

Oracle stocke DATE s dans des tableaux utilisant 7 octets où les 2 premiers octets sont :

  • Siècle + 100
  • Année du siècle + 100

Ainsi, la date maximale qui peut (techniquement) être stockée est lorsque ces deux octets ont les valeurs 255 et 199 ce qui donnerait une année de 15599 (J'ignore que vous pourriez théoriquement stocker 255 dans le deuxième octet car cela ouvre tout un tas de problèmes distincts).

Vous pouvez convertir une valeur brute en une date en utilisant le DBMS_STATS.CONVERT_RAW_VALUE ce qui signifie que nous pouvons contourner les méthodes normales de création de dates et générer directement les valeurs d'octets qui seront stockées.

Cette fonction en est un exemple :

CREATE FUNCTION createDate(
  year   int,
  month  int,
  day    int,
  hour   int,
  minute int,
  second int
) RETURN DATE DETERMINISTIC
IS
  hex CHAR(14);
  d DATE;
BEGIN
  hex := TO_CHAR( FLOOR( year / 100 ) + 100, 'fm0X' )
      || TO_CHAR( MOD( year, 100 ) + 100, 'fm0X' )
      || TO_CHAR( month, 'fm0X' )
      || TO_CHAR( day, 'fm0X' )
      || TO_CHAR( hour + 1, 'fm0X' )
      || TO_CHAR( minute + 1, 'fm0X' )
      || TO_CHAR( second + 1, 'fm0X' );
  DBMS_OUTPUT.PUT_LINE( hex );
  DBMS_STATS.CONVERT_RAW_VALUE( HEXTORAW( hex ), d );
  RETURN d;
END;
/

Ensuite, si vous avez une colonne de date, vous pouvez insérer des valeurs que vous n'êtes normalement pas autorisé à insérer :

CREATE TABLE table_name ( date_column DATE );

INSERT INTO table_name ( date_column )
VALUES ( DATE '2019-12-31' + INTERVAL '1:02:03' HOUR TO SECOND );

INSERT INTO table_name ( date_column ) VALUES ( createDate( 15599, 12, 31, 1, 2, 3 ) );

INSERT INTO table_name ( date_column ) VALUES ( createDate( 12017, 2, 21, 0, 0, 0 ) );

TO_CHAR ne fonctionne pas lorsque l'année dépasse les limites normales d'une date. Pour obtenir les valeurs stockées dans la table, vous pouvez utiliser DUMP pour obtenir une chaîne contenant les valeurs d'octets ou vous pouvez utiliser EXTRACT pour obtenir les composants individuels.

SELECT DUMP( date_column ),
       TO_CHAR( date_column, 'YYYY-MM-DD' ) AS value,
       TO_CHAR( EXTRACT( YEAR FROM date_column ), 'fm00000' )
         || '-' || TO_CHAR( EXTRACT( MONTH  FROM date_column ), 'fm00' )
         || '-' || TO_CHAR( EXTRACT( DAY    FROM date_column ), 'fm00' )
         || ' ' || TO_CHAR( EXTRACT( HOUR   FROM CAST( date_column AS TIMESTAMP ) ), 'fm00' )
         || ':' || TO_CHAR( EXTRACT( MINUTE FROM CAST( date_column AS TIMESTAMP ) ), 'fm00' )
         || ':' || TO_CHAR( EXTRACT( SECOND FROM CAST( date_column AS TIMESTAMP ) ), 'fm00' )
         AS full_value
FROM table_name;

sorties :

DUMP(DATE_COLUMN)                 | VALUE      | FULL_VALUE          
:-------------------------------- | :--------- | :-------------------
Typ=12 Len=7: 120,119,12,31,2,3,4 | 2019-12-31 | 02019-12-31 01:02:03
Typ=12 Len=7: 255,199,12,31,2,3,4 | 0000-00-00 | 15599-12-31 01:02:03
Typ=12 Len=7: 220,117,2,21,1,1,1  | 0000-00-00 | 12017-02-21 00:00:00

db<>jouez ici