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

Oracle SQL-Loader gestisce in modo efficiente le doppie virgolette interne nei valori

Se non hai mai avuto pipe nei campi racchiusi, puoi farlo dal file di controllo. Se puoi avere sia pipe che virgolette all'interno di un campo, penso che tu non abbia altra scelta che preelaborare i file, sfortunatamente.

La tua soluzione [1], per sostituire le virgolette doppie con un operatore SQL , sta accadendo troppo tardi per essere utile; i delimitatori e gli allegati sono già stati interpretati da SQL*Loader prima di eseguire il passaggio SQL. La tua soluzione [2], per ignorare l'enclosure, funzionerebbe in combinazione con [1] - fino a quando uno dei campi non contiene un carattere pipe. E la soluzione [3] presenta gli stessi problemi dell'utilizzo di [1] e/o [2] a livello globale.

La documentazione per specificando i delimitatori menziona che:

In altre parole, se hai ripetuto le virgolette dentro i campi quindi verrebbero sottoposti a escape e apparirebbero nei dati della tabella. Poiché non puoi controllare la generazione dei dati, puoi preelaborare i file che ottieni per sostituire tutte le virgolette doppie con virgolette doppie con escape. Tranne che non vuoi sostituire tutti di loro - quelli che in realtà sono dei veri e propri recinti non dovrebbero essere evasi.

Potresti usare un'espressione regolare per indirizzare i personaggi rilevanti saltandone altri. Non è la mia area di forza, ma penso che tu possa farlo con lookahead e lookbehind assertions .

Se avessi un file chiamato orig.txt contenente:

"1"|A|"B"|"C|D"
"2"|A|"B"|"C"D"
3|A|""B""|"C|D"
4|A|"B"|"C"D|E"F"G|H""

potresti fare:

perl -pe 's/(?<!^)(?<!\|)"(?!\|)(?!$)/""/g' orig.txt > new.txt

Ciò cerca una doppia virgoletta che non è preceduta dall'ancora di inizio riga o da un carattere pipe; e non è seguito da un carattere pipe o da un'ancora di fine riga; e sostituisce solo quelli con virgolette doppie (raddoppiate). Il che renderebbe new.txt contengono:

"1"|A|"B"|"C|D"
"2"|A|"B"|"C""D"
3|A|"""B"""|"C|D"
4|A|"B"|"C""D|E""F""G|H"""

Le doppie virgolette all'inizio e alla fine dei campi non vengono modificate, ma quelle al centro ora sono sfuggite. Se poi lo hai caricato con un file di controllo con virgolette doppie:

load data
truncate
into table t42
fields terminated by '|' optionally enclosed by '"'
(
  col1,
  col2,
  col3,
  col4
)

Quindi finiresti con:

select * from t42 order by col1;

      COL1 COL2       COL3       COL4                
---------- ---------- ---------- --------------------
         1 A          B          C|D                 
         2 A          B          C"D                 
         3 A          "B"        C|D                 
         3 A          B          C"D|E"F"G|H"        

che si spera corrisponda ai tuoi dati originali. Potrebbero esserci casi limite che non funzionano (come una doppia virgoletta seguita da una barra verticale all'interno un campo) ma c'è un limite a ciò che puoi fare per tentare di interpretare i dati di qualcun altro... Potrebbero esserci anche modelli di espressioni regolari (molto) migliori, ovviamente.

Potresti anche considerare l'utilizzo di una tabella esterna invece di SQL*Loader, se il file di dati è (o può essere) in una directory Oracle e si dispone delle autorizzazioni corrette. Devi ancora modificare il file, ma potresti farlo automaticamente con preprocessor direttiva, piuttosto che doverlo fare in modo esplicito prima di chiamare SQL*Loader.