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