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

Il tentativo di esportare un Oracle tramite PL/SQL fornisce una data di 0000-00-00

Il valore memorizzato in quella colonna non è una data valida. Il primo byte del dump dovrebbe essere il secolo, che secondo la nota di supporto Oracle 69028.1 è memorizzato nella notazione 'excess-100', il che significa che dovrebbe avere un valore di 100 + il secolo effettivo; quindi 1900 sarebbe 119, 2000 sarebbe 120 e 5500 sarebbe 155. Quindi 44 rappresenterebbe -5600; la data che hai memorizzato sembra rappresentare effettivamente 5544-09-14 BC . Poiché Oracle supporta solo date con anni compresi tra -4713 e +9999, questo non viene riconosciuto.

Puoi ricrearlo abbastanza facilmente; la parte più complicata è in primo luogo ottenere la data non valida nel database:

create table t42(dt date);

Table created.

declare
    d date;
begin
    dbms_stats.convert_raw_value('2c9c090e010101', d);
    insert into t42 (dt) values (d);
end;
/

PL/SQL procedure successfully completed.

select dump(dt), dump(dt, 1016) from t42;

DUMP(DT)
--------------------------------------------------------------------------------
DUMP(DT,1016)
--------------------------------------------------------------------------------
Typ=12 Len=7: 45,56,9,14,1,1,1
Typ=12 Len=7: 2d,38,9,e,1,1,1

Quindi questa ha una singola riga con gli stessi dati che hai. Usando alter session Posso vedere quella che sembra una data valida:

alter session set nls_date_format = 'DD-Mon-YYYY';
select dt from t42;

DT
-----------
14-Sep-5544

alter session set nls_date_format = 'YYYYMMDDHH24MISS';
select dt from t42;

DT
--------------
55440914000000

Ma se uso una maschera di data esplicita, ottiene solo zeri:

select to_char(dt, 'DD-Mon-YYYY'), to_char(dt, 'YYYYMMDDHH24MISS') from t42;

TO_CHAR(DT,'DD-MON-Y TO_CHAR(DT,'YY
-------------------- --------------
00-000-0000          00000000000000

E se eseguo la tua procedura:

exec dump_table_to_csv('T42');

Il CSV risultante ha:

"DT"
"0000-00-00T00:00:00"

Penso che la differenza sia che quelli che tentano di mostrare la data si attengono al tipo di dati della data interna 12, mentre quelli che mostrano zeri utilizzano il tipo di dati esterno 13, come menzionato nella nota 69028.1.

Quindi, in breve, la tua procedura non sta facendo nulla di sbagliato, la data che sta tentando di esportare non è internamente valida. A meno che tu non sappia quale data doveva essere, il che sembra improbabile dato il tuo punto di partenza, non credo che ci sia molto che tu possa fare al riguardo se non indovinarlo o ignorarlo. A meno che, forse, tu non sappia come sono stati inseriti i dati e non riesca a capire come sono stati danneggiati.

Penso che sia più probabile che provenga da un programma OCI rispetto a quello che ho fatto qui; questo trucco "grezzo" era originario di qui. Potresti anche voler guardare la nota 331831.1. E questa domanda precedente è in qualche modo correlata.