External Tables, possibili errori

mercoledì 29 agosto 2012 alle 29:01 | Pubblicato su 11g | 1 commento
Tag: , ,

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 for comments on this post. TrackBack URI

  1. 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.


Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

Blog su WordPress.com.
Entries e commenti feeds.

%d blogger cliccano Mi Piace per questo: