sql >> Database >  >> RDS >> Oracle

Oracle SQL-Loader efficiënt omgaan met interne dubbele aanhalingstekens in waarden

Als u nooit leidingen in de bijgevoegde velden had, zou u dit kunnen doen vanuit het controlebestand. Als je zowel pijpen als dubbele aanhalingstekens in een veld kunt hebben, dan denk ik dat je helaas geen andere keuze hebt dan de bestanden voor te verwerken.

Uw oplossing [1], ter vervanging van dubbele aanhalingstekens met een SQL-operator , gebeurt te laat om nog bruikbaar te zijn; de scheidingstekens en bijlagen zijn al geïnterpreteerd door SQL*Loader voordat de SQL-stap wordt uitgevoerd. Uw oplossing [2], om de bijlage te negeren, zou werken in combinatie met [1] - totdat een van de velden een pipe-teken bevatte. En oplossing [3] heeft dezelfde problemen als het globaal gebruiken van [1] en/of [2].

De documentatie voor het specificeren van scheidingstekens vermeldt dat:

Met andere woorden, als u de dubbele aanhalingstekens binnen . herhaalt de velden dan zouden ze worden ontsnapt en in de tabelgegevens verschijnen. Omdat u de gegevensgeneratie niet kunt controleren, kunt u de bestanden die u krijgt voorbewerken om alle dubbele aanhalingstekens te vervangen door dubbele aanhalingstekens met escapetekens. Behalve dat je niet alles wilt vervangen van hen - degenen die eigenlijk echte omhuizingen zijn, mogen niet worden ontsnapt.

U kunt een reguliere expressie gebruiken om de relevante tekens te targeten en anderen overslaan. Niet mijn sterkste kant, maar ik denk dat je dit kunt doen met vooruitblik- en lookbehind-beweringen .

Als u een bestand had met de naam orig.txt met daarin:

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

je zou kunnen doen:

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

Dat zoekt naar een dubbel aanhalingsteken dat niet wordt voorafgegaan door het lijnstartanker of een pijpteken; en wordt niet gevolgd door een pijpteken of lijneindanker; en vervangt alleen die met escaped (verdubbelde) dubbele aanhalingstekens. Wat new.txt . zou maken bevatten:

"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 dubbele aanhalingstekens aan het begin en einde van velden zijn niet gewijzigd, maar die in het midden zijn nu escaped. Als je dat vervolgens hebt geladen met een controlebestand met dubbele aanhalingstekens:

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

Dan zou je eindigen met:

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"        

die hopelijk overeenkomt met uw oorspronkelijke gegevens. Er kunnen randgevallen zijn die niet werken (zoals een dubbel aanhalingsteken gevolgd door een pijp binnen een veld) maar er is een limiet aan wat u kunt doen om de gegevens van iemand anders te interpreteren... Er kunnen natuurlijk ook (veel) betere reguliere expressiepatronen zijn.

U kunt ook overwegen om een externe tabel in plaats van SQL*Loader, als het gegevensbestand in een Oracle-directory staat (of kan zijn) en u over de juiste rechten beschikt. Je moet het bestand nog steeds aanpassen, maar je zou het automatisch kunnen doen met de preprocessor richtlijn, in plaats van dat expliciet te moeten doen voordat SQL*Loader wordt aangeroepen.




  1. Hoe QUERY in expdp te gebruiken om alleen de gegevens van de laatste 3 maanden te extraheren

  2. Aantal rijen in Leer 2

  3. mysqlception is niet afgehandeld - Er is al een open DataReader gekoppeld aan deze verbinding die eerst moet worden gesloten

  4. MySQL Trigger - Een SELECT opslaan in een variabele