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