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

Oracle SQL-Loader håndterer effektivt interne dobbelte anførselstegn i værdier

Hvis du aldrig har haft rør i de lukkede felter, kunne du gøre det fra kontrolfilen. Hvis du kan have både piper og dobbelte anførselstegn inden for et felt, så tror jeg, du ikke har andet valg end at forbehandle filerne, desværre.

Din løsning [1], for at erstatte dobbelte anførselstegn med en SQL-operator , sker for sent til at være nyttigt; afgrænsningerne og indeslutningerne er allerede blevet fortolket af SQL*Loader, før den udfører SQL-trinnet. Din løsning [2], for at ignorere indeslutningen, ville fungere i kombination med [1] - indtil et af felterne indeholdt et rørtegn. Og løsning [3] har de samme problemer som at bruge [1] og/eller [2] globalt.

Dokumentationen til angivelse af skilletegn nævner, at:

Med andre ord, hvis du gentog de dobbelte anførselstegn indeni felterne, så ville de blive escaped og ville blive vist i tabeldataene. Da du ikke kan kontrollere datagenereringen, kan du forbehandle de filer, du får, for at erstatte alle dobbelte anførselstegn med undslupne dobbelte anførselstegn. Bortset fra at du ikke ønsker at erstatte alle af dem - dem, der faktisk er rigtige indhegninger, bør ikke undslippes.

Du kan bruge et regulært udtryk til at målrette mod, at de relevante tegn vil springe andre over. Ikke mit stærke område, men jeg tror, ​​du kan gøre dette med lookahead og lookbehind-påstande .

Hvis du havde en fil kaldet orig.txt indeholdende:

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

du kunne gøre:

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

Det leder efter et dobbelt anførselstegn, som ikke er forudgået af line-start-ankeret eller et rørtegn; og er ikke efterfulgt af et rørkarakter eller linjeendeanker; og erstatter kun dem med undslupne (doblede) dobbelte anførselstegn. Hvilket ville gøre new.txt indeholder:

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

De dobbelte anførselstegn ved begyndelsen og slutningen af ​​felter er ikke ændret, men dem i midten er nu escaped. Hvis du derefter indlæste det med en kontrolfil med dobbelte anførselstegn:

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

Så ville du ende med:

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"        
 

som forhåbentlig matcher dine originale data. Der kan være kantstilfælde, der ikke virker (som et dobbelt anførselstegn efterfulgt af et rør indenfor et felt), men der er en grænse for, hvad du kan gøre for at forsøge at fortolke en andens data... Der kan selvfølgelig også være (meget) bedre regulære udtryksmønstre.

Du kan også overveje at bruge en ekstern tabel i stedet for SQL*Loader, hvis datafilen er (eller kan være) i et Oracle-bibliotek, og du har de rigtige tilladelser. Du skal stadig ændre filen, men du kan gøre det automatisk med preprocessor direktiv, snarere end at skulle gøre det eksplicit, før du kalder SQL*Loader.




  1. Hvordan konverteres et tidsstempelfelt til int8? Eller bare slip kolonnen og lave en ny?

  2. Forskellen mellem disse to sammenføjningstabeller?

  3. Hvordan får du tabelformateret output fra MySQL i ikke-interaktiv tilstand?

  4. Sådan laver du en LEFT SEMI JOIN i SQL Server