sql >> Databasteknik >  >> RDS >> Oracle

Oracle 10g accepterar 5-siffrigt år i ett datum

Oracle lagrar DATE s i tabeller med 7 byte där de första 2 byte är:

  • Century + 100
  • Sekelår + 100

Så det maximala datumet som (tekniskt sett) kan lagras är när dessa två byte har värdena 255 och 199 vilket skulle ge ett år på 15599 (Jag ignorerar att du teoretiskt skulle kunna lagra 255 i den andra byten eftersom det öppnar upp en hel hög av separata problem).

Du kan konvertera ett råvärde till ett datum med DBMS_STATS.CONVERT_RAW_VALUE vilket innebär att vi kan kringgå de normala metoderna för att skapa datum och direkt generera bytevärdena som kommer att lagras.

Den här funktionen är ett exempel på det:

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

Om du sedan har en datumkolumn kan du infoga värden som du normalt inte får infoga:

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 fungerar inte när året överskrider de normala gränserna för ett datum. För att få värdena lagrade i tabellen kan du använda DUMP för att få en sträng som innehåller bytevärdena eller så kan du använda EXTRACT för att få de enskilda komponenterna.

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;

utgångar:

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<>spela här




  1. MySQL Storage Engine Optimization:Konfigurera InnoDB-optimering för hög prestanda

  2. T-SQL delad sträng baserad på avgränsare

  3. ScaleGrid DBaaS nominerad till Cloud Excellence Awards 2018

  4. Hur Tan() fungerar i PostgreSQL