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.