sql >> Database teknologi >  >> RDS >> Oracle

Oracle 10g accepterer 5-cifret årstal i en Dato

Oracle gemmer DATE s i tabeller med 7 bytes, hvor de første 2 bytes er:

  • Århundrede + 100
  • Århundrede + 100

Så den maksimale dato, der (teknisk) kan gemmes, er, når disse to bytes har værdierne 255 og 199 hvilket ville give et år på 15599 (Jeg ignorerer, at du teoretisk kunne gemme 255 i den anden byte, da det åbner op for en hel bunke af separate problemer).

Du kan konvertere en råværdi til en dato ved hjælp af DBMS_STATS.CONVERT_RAW_VALUE hvilket betyder, at vi kan omgå de normale metoder til oprettelse af datoer og direkte generere de byteværdier, som vil blive gemt.

Denne funktion er et eksempel 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;
/

Så hvis du har en datokolonne, kan du indsætte værdier, som du normalt ikke må indsætte:

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 fungerer ikke, når året overskrider de normale grænser for en dato. For at få værdierne gemt i tabellen kan du bruge DUMP for at få en streng, der indeholder byte-værdierne, eller du kan bruge EXTRACT for at få de enkelte komponenter.

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;

udgange:

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<>spil her




  1. Sådan optimeres PostgreSQL logisk replikering

  2. Upsert med en transaktion

  3. Sådan formateres dato og klokkeslæt i SQL Server

  4. Sådan nærmer du dig en Got minus en fra en læseopkaldsfejl, når du opretter forbindelse til en Amazon RDS Oracle-instans