Oracle memorizza DATE
s nelle tabelle che utilizzano 7 byte in cui i primi 2 byte sono:
- Secolo + 100
- Anno del secolo + 100
Quindi la data massima che può (tecnicamente) essere memorizzata è quando quei due byte hanno i valori 255
e 199
che darebbe l'anno di 15599
(Sto ignorando che potresti teoricamente memorizzare 255
nel secondo byte in quanto ciò apre un intero mucchio di problemi separati).
Puoi convertire un valore grezzo in una data utilizzando il DBMS_STATS.CONVERT_RAW_VALUE
il che significa che possiamo ignorare i normali metodi di creazione delle date e generare direttamente i valori dei byte che verranno archiviati.
Questa funzione ne è un esempio:
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;
/
Quindi se hai una colonna di data puoi inserire valori che normalmente non sei autorizzato a inserire:
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
non funziona quando l'anno supera i limiti normali di una data. Per ottenere i valori memorizzati nella tabella puoi usare DUMP
per ottenere una stringa contenente i valori dei byte oppure puoi usare EXTRACT
per ottenere i singoli componenti.
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;
uscite:
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<>gioca qui