Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle SQL-Loader verarbeitet effizient interne doppelte Anführungszeichen in Werten

Wenn Sie noch nie Pipes in den umschlossenen Feldern hatten, können Sie dies über die Steuerdatei tun. Wenn Sie sowohl Pipes als auch doppelte Anführungszeichen in einem Feld haben können, haben Sie leider keine andere Wahl, als die Dateien vorzuverarbeiten.

Ihre Lösung [1], um doppelte Anführungszeichen zu ersetzen mit einem SQL-Operator , geschieht zu spät, um nützlich zu sein; die Trennzeichen und Umschließungen wurden bereits von SQL*Loader interpretiert, bevor es den SQL-Schritt ausführt. Ihre Lösung [2], das Gehäuse zu ignorieren, würde in Kombination mit [1] funktionieren - bis eines der Felder ein Pipe-Zeichen enthält. Und Lösung [3] hat die gleichen Probleme wie die globale Verwendung von [1] und/oder [2].

Die Dokumentation für Festlegen von Trennzeichen erwähnt, dass:

Mit anderen Worten, wenn Sie die doppelten Anführungszeichen innerhalb wiederholt haben die Felder werden dann maskiert und erscheinen in den Tabellendaten. Da Sie die Datengenerierung nicht kontrollieren können, könnten Sie die erhaltenen Dateien vorverarbeiten, um alle doppelten Anführungszeichen durch doppelte Anführungszeichen mit Escapezeichen zu ersetzen. Außer Sie möchten nicht alle ersetzen von ihnen - diejenigen, die eigentlich echte Gehege sind, sollten nicht entkommen werden.

Sie könnten einen regulären Ausdruck verwenden, um auf die relevanten Zeichen abzuzielen, die andere überspringen. Nicht meine Stärke, aber ich denke, Sie können dies mit Lookahead- und Lookbehind-Assertionen tun .

Wenn Sie eine Datei namens orig.txt hatten enthält:

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

Sie könnten Folgendes tun:

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

Das sucht nach einem doppelten Anführungszeichen, dem kein Zeilenanfangsanker oder ein Pipe-Zeichen vorangestellt ist; und wird nicht von einem Pipe-Zeichen oder Zeilenende-Anker gefolgt; und ersetzt nur diese durch doppelte Anführungszeichen (escaped). Das würde new.txt machen enthalten:

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

Die doppelten Anführungszeichen am Anfang und Ende der Felder werden nicht geändert, aber die in der Mitte werden jetzt maskiert. Wenn Sie das dann mit einer Steuerdatei mit Anführungszeichen geladen haben:

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

Dann würden Sie am Ende mit:

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 hoffentlich mit Ihren Originaldaten übereinstimmt. Es kann Grenzfälle geben, die nicht funktionieren (wie ein doppeltes Anführungszeichen gefolgt von einem senkrechten Strich innerhalb ein Feld), aber es gibt eine Grenze dafür, was Sie tun können, um zu versuchen, die Daten von jemand anderem zu interpretieren... Es kann natürlich auch (viel) bessere reguläre Ausdrucksmuster geben.

Sie könnten auch die Verwendung einer einer externen Tabelle anstelle von SQL*Loader, wenn sich die Datendatei in einem Oracle-Verzeichnis befindet (oder befinden kann) und Sie über die entsprechenden Berechtigungen verfügen. Sie müssen die Datei noch ändern, aber Sie könnten dies automatisch mit preprocessor Direktive, anstatt dies explizit vor dem Aufruf von SQL*Loader.

tun zu müssen