External Tables, possibili errori
mercoledì 29 agosto 2012 alle 29:01 | Pubblicato in 11g | 1 commentoEtichette: csv, external tables, oracle
Ieri ho incontranto uno dei tanti casi in cui una “external table” oracle può non funzionare, nel mio caso dando errore durante le interrogazioni. Voglio quindi descrivere il caso . Questa è la DDL della mia external table utilizzata per accedera a un file CSV:
create table letturearduino_csv ( id number, tman number, trit number, text number, tboll number, pump_status number, dataora date, acspump number, znpump number, zntman number, zntrit number, acscaldaia number, tsalatermica number ) organization external ( type oracle_loader default directory LOAD_DATA access parameters ( records delimited by newline TERRITORY AMERICA BADFILE 'letturearduino.bad' LOGFILE 'letturearduino.log' skip 1 fields terminated by ";" optionally enclosed by "'" MISSING FIELD VALUES ARE NULL ( id , tman , trit , text , tboll , pump_status , dataora char(20) date_format DATE mask 'yyyy-mm-dd hh24:mi:ss', acspump , znpump , zntman , zntrit , acscaldaia , tsalatermica ) ) location ( 'letturearduino2.csv' ) );
Il file CVS è stato generato tramite phpMyAdmin da un database MySQL su cui registro i dati del mio impianto solare termico tramite il microprocessore Arduino (ne parlo dettagliatamente qui), per essere più dettagliato riporto anche la struttura della tabella di partenza:
CREATE TABLE `letturearduino2` ( `lecture_id` bigint(20) NOT NULL AUTO_INCREMENT, `s_temp_rit` decimal(7,4) DEFAULT NULL, `s_temp_man` decimal(7,4) DEFAULT NULL, `s_temp_ext` decimal(7,4) DEFAULT NULL, `s_temp_amb` decimal(7,4) DEFAULT NULL, `pump_status` decimal(2,0) DEFAULT NULL, `dataora` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `acspump` decimal(2,0) DEFAULT NULL, `znpump` decimal(2,0) DEFAULT NULL, `zntman` decimal(7,4) DEFAULT NULL, `zntrit` decimal(7,4) DEFAULT NULL, `acscaldaia` decimal(2,0) DEFAULT NULL, `tca` decimal(7,4) DEFAULT NULL)
Caricando il file sul mio database server, un Oracle 11.2.0.2 32 bit su linux e facendo un count sulla tabella riscontravo il seguente errore:
error processing column TSALATERMICA in row 44551 for datafile /usr/backup/UNLOAD/letturearduino2.csv
ORA-01722: invalid number
E questo è l’estratto incriminato del file csv (la prima colonna riporta il numero di riga)
44548 ... 44549 65098;16.3000;15.6000;6.6000;28.5000;0;2012-04-10 09:31:38;0;0;16.3000;16.5000;0; 44550 65099;16.3000;15.6000;6.6000;28.5000;0;2012-04-10 09:32:39;0;0;16.3000;16.5000;0; 44551 65100;16.3000;15.6000;6.6000;28.5000;0;2012-04-10 09:33:40;0;0;16.3000;16.5000;0;15.7000 44552 65101;16.3000;15.6000;6.6000;28.5000;0;2012-04-10 09:34:42;0;0;16.3000;16.5000;0;15.8000 44553 ...
Quindi nella mia tabella fino a un certo punto l’ultima colonna non è valorizzata (è stata aggiunata a posteriori), il problema è che la mia external table cominciava a dare errore nel momento in cui la colonna era valorizzata. Non era un problema di numero perché altrimenti avrebbero dato errore anche tutti gli altri. Ho provato ad aggiungere all’ultimo campo anche la clausola
NULL if (TSALATERMICA = BLANKS)
ma in realtà il problema sembrava contrario e la parte “MISSING FIELD VALUES ARE NULL” dovrebbe gia risolvere questo caso. Poi ho avuto un’illuminazione ed ho fatto un controllo sul file csv:
[oracle@methone ~]$ file letturearduino2.csv letturearduino2.csv: ASCII text, with CRLF line terminators
Dunque, inspiegabilmente il file generato da phpMyAdmin è in formato DOS, quindi eseguendo un semplice dos2unix:
[oracle@methone ~]$ dos2unix letturearduino2.csv dos2unix: converting file letturearduino2.csv to UNIX format ...
il problema è magicamente scomparso.
1 commento »
RSS feed dei commenti a questo articolo. TrackBack URI
Lascia un Commento
Blog su WordPress.com. | Tema: Pool di Borja Fernandez.
Voci e commenti feeds.


Read Translated version of this blog
A livello client si suppone che ci sia Windows e perciò spesso in ambito web formati e utility hanno standard con “a capo” uguale alla coppia CR+LF.
Il parametro NEWLINE della clausola DELIMITED BY è intelligente, per cui (http://docs.oracle.com/cd/B28359_01/server.111/b28319/et_params.htm):
If DELIMITED BY NEWLINE is specified, then the actual value used is platform-specific. On UNIX platforms, NEWLINE is assumed to be “\n”. On Windows NT, NEWLINE is assumed to be “\r\n”.
Nel tuo caso bisogna utilizzare la clausola DELIMITED BY specificando la stringa ‘\r\n’… non ho provato in effetti se funziona o se per specificare la stringa di delimitazione bisogna passare alla notazione esadecimale.
Comment by Roberto— venerdì 31 agosto 2012 #