sql >> Base de Datos >  >> RDS >> Oracle

Oracle SQL-Loader maneja de manera eficiente las comillas dobles internas en los valores

Si nunca tuvo tuberías en los campos adjuntos, podría hacerlo desde el archivo de control. Si puede tener canalizaciones y comillas dobles dentro de un campo, creo que no tiene más remedio que preprocesar los archivos, lamentablemente.

Su solución [1], para reemplazar las comillas dobles con un operador SQL , está ocurriendo demasiado tarde para ser útil; SQL*Loader ya interpretó los delimitadores y los recintos antes de realizar el paso de SQL. Su solución [2], para ignorar el recinto, funcionaría en combinación con [1], hasta que uno de los campos contuviera un carácter de canalización. Y la solución [3] tiene los mismos problemas que usar [1] y/o [2] globalmente.

La documentación para especificación de delimitadores menciona que:

En otras palabras, si repite las comillas dobles dentro los campos entonces serían escapados y aparecerían en la tabla de datos. Como no puede controlar la generación de datos, puede preprocesar los archivos que obtiene para reemplazar todas las comillas dobles con comillas dobles con escape. Excepto que no desea reemplazar todos de ellos, no se debe escapar de los que en realidad son recintos reales.

Puede usar una expresión regular para apuntar a los caracteres relevantes y omitir otros. No es mi área fuerte, pero creo que puedes hacer esto con afirmaciones anticipadas y retrospectivas .

Si tuviera un archivo llamado orig.txt que contiene:

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

podrías hacer:

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

Eso busca una comilla doble que no esté precedida por el ancla de inicio de línea o un carácter de canalización; y no va seguido de un carácter de barra vertical ni de un ancla de final de línea; y reemplaza solo aquellos con comillas dobles escapadas (dobladas). Lo que haría new.txt contiene:

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

Las comillas dobles al principio y al final de los campos no se modifican, pero las del medio ahora se escapan. Si luego cargó eso con un archivo de control con comillas dobles:

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

Entonces terminarías 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"        

que con suerte coincide con sus datos originales. Puede haber casos extremos que no funcionen (como una comilla doble seguida de una tubería dentro un campo) pero hay un límite en lo que puede hacer para intentar interpretar los datos de otra persona... También puede haber (mucho) mejores patrones de expresiones regulares, por supuesto.

También podría considerar usar una tabla externa en lugar de SQL*Loader, si el archivo de datos está (o puede estar) en un directorio de Oracle y tiene los permisos adecuados. Todavía tiene que modificar el archivo, pero podría hacerlo automáticamente con preprocessor directiva, en lugar de tener que hacerlo explícitamente antes de llamar a SQL*Loader.