Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Oracle SQL-Loader tratando de forma eficiente as aspas duplas internas em valores


Se você nunca teve pipes nos campos fechados, pode fazê-lo a partir do arquivo de controle. Se você pode ter pipes e aspas duplas em um campo, acho que não tem escolha a não ser pré-processar os arquivos, infelizmente.

Sua solução [1], para substituir aspas duplas com um operador SQL , está acontecendo tarde demais para ser útil; os delimitadores e anexos já foram interpretados pelo SQL*Loader antes de executar a etapa SQL. Sua solução [2], para ignorar o anexo, funcionaria em combinação com [1] - até que um dos campos contivesse um caractere de barra vertical. E a solução [3] tem os mesmos problemas que usar [1] e/ou [2] globalmente.

A documentação para especificar delimitadores menciona que:

Em outras palavras, se você repetiu as aspas duplas dentro os campos, então eles seriam escapados e apareceriam nos dados da tabela. Como você não pode controlar a geração de dados, você pode pré-processar os arquivos que você obtém para substituir todas as aspas duplas por aspas duplas com escape. Exceto que você não deseja substituir todos deles - os que são realmente recintos reais não devem ser escapados.

Você pode usar uma expressão regular para direcionar os caracteres relevantes pulando outros. Não é minha área forte, mas acho que você pode fazer isso com lokahead e lookbehind assertions .

Se você tivesse um arquivo chamado orig.txt contendo:
"1"|A|"B"|"C|D"
"2"|A|"B"|"C"D"
3|A|""B""|"C|D"
4|A|"B"|"C"D|E"F"G|H""

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

Isso procura por aspas duplas que não são precedidas pela âncora de início de linha ou por um caractere de barra vertical; e não é seguido por um caractere de barra vertical ou âncora de final de linha; e substitui apenas aqueles com aspas duplas com escape (duplicadas). O que tornaria new.txt conter:
"1"|A|"B"|"C|D"
"2"|A|"B"|"C""D"
3|A|"""B"""|"C|D"
4|A|"B"|"C""D|E""F""G|H"""

As aspas duplas no início e no final dos campos não são modificadas, mas as do meio agora são escapadas. Se você carregou isso com um arquivo de controle com aspas duplas:
load data
truncate
into table t42
fields terminated by '|' optionally enclosed by '"'
(
  col1,
  col2,
  col3,
  col4
)

Então você terminaria com:
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 esperamos corresponder aos seus dados originais. Pode haver casos extremos que não funcionam (como aspas duplas seguidas por uma barra vertical dentro um campo), mas há um limite para o que você pode fazer para tentar interpretar os dados de outra pessoa... Também pode haver padrões de expressão regular (muito) melhores, é claro.

Você também pode considerar usar uma tabela externa em vez de SQL*Loader, se o arquivo de dados estiver (ou puder estar) em um diretório Oracle e você tiver as permissões corretas. Você ainda precisa modificar o arquivo, mas pode fazer isso automaticamente com o preprocessor diretiva, em vez de precisar fazer isso explicitamente antes de chamar SQL*Loader.