sql >> Database >  >> RDS >> Oracle

Oracle 10g accepteert een 5-cijferig jaar in een datum

Oracle slaat DATE op s in tabellen met 7 bytes waarbij de eerste 2 bytes zijn:

  • Eeuw + 100
  • Jaar van de eeuw + 100

Dus de maximale datum die (technisch) kan worden opgeslagen, is wanneer die twee bytes de waarden 255 hebben en 199 wat een jaar zou opleveren van 15599 (Ik negeer dat je in theorie 255 zou kunnen opslaan in de tweede byte, want dat opent een hele hoop afzonderlijke problemen).

U kunt een onbewerkte waarde converteren naar een datum met behulp van de DBMS_STATS.CONVERT_RAW_VALUE wat betekent dat we de normale methoden voor het maken van datums kunnen omzeilen en direct de bytewaarden kunnen genereren die worden opgeslagen.

Deze functie is daar een voorbeeld van:

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;
/

Als je dan een datumkolom hebt, kun je waarden invoegen die je normaal niet mag invoegen:

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 werkt niet wanneer het jaar de normale grenzen van een datum overschrijdt. Om de waarden die in de tabel zijn opgeslagen te krijgen, kunt u DUMP . gebruiken om een ​​tekenreeks te krijgen die de bytewaarden bevat of u kunt EXTRACT . gebruiken om de afzonderlijke componenten te krijgen.

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;

uitgangen:

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<>viool hier




  1. COALESCE-functie in TSQL

  2. INSERT a SELECT GROUP BY :meer doelkolommen dan expressies fout

  3. MySQL LOG() Functie – Retourneer de natuurlijke logaritme van een waarde

  4. Zijn query's van het SELECT-type het enige type dat kan worden genest?