Eu tenho um ambiente Postgres 8.4 onde a codificação em todos os nossos bancos de dados está definida como - FinalmenteSQL_ASCII
estamos migrando para o Postgres 9.2 e gostaria de migrar tudo para a codificação. UTF8
Infelizmente, os dados de texto neste banco de dados não estão limpos - Tentar restaurar o pg_dump para um banco de dados codificado em utf8 gera erros sobre seqüências de bytes inválidas, mesmo se eu especificar --encoding=UTF8
quando executo o pg_dump (presumivelmente porque o Postgres não sabe o que fazer com eles e apenas os despeja inalterados?).
Temos MUITOS dados (mais de um milhão de linhas com elementos de texto/string), e auditar tudo manualmente seria muito demorado (e sujeito a erros), então gostaria de automatizar isso, se possível.
Existe uma maneira fácil de encontrar as strings/campos de texto não conformes com utf8 no banco de dados para que possamos corrigi-los? Ou estou preso a uma auditoria manual para corrigir essa bagunça?
Suspeito que o conteúdo do seu banco de dados esteja em iso8859 ou cp1252. Se fosse ASCII, você não teria problemas para importá-lo. Você pode determinar a codificação abrindo seu dump com python. O seguinte python3 tenta codificações até obter sucesso. Ele pode ser usado para determinar a codificação do arquivo.
O Python também pode ser usado para acessar o banco de dados e auditar os dados. Também pode ser usado para transcodificar os dados para UTF-8 enquanto os copia, se necessário.
Despejos de codificação de texto mutilados são difíceis de trabalhar.
A solução usual - e reconhecidamente grosseira - é executar
iconv
no despejo de formato SQL, com o-c
sinalizador para dizer a ele para omitir caracteres inválidos na codificação de destino.Isso só é viável se o banco de dados de origem estiver supostamente em uma codificação primária e tiver apenas alguns dados incorretos aqui e ali devido à falha em realmente aplicar e verificar essa codificação.
Se o banco de dados de origem estiver em codificações mistas/múltiplas, essa abordagem realmente não funcionará. Você teria que fazer a detecção de conjunto de caracteres por campo, usando algo como o procedimento armazenado PL/Python ou PL/Perl para fazer a melhor detecção de codificação em cada campo, convertê-lo para a codificação de destino (digamos, utf-8) e, em seguida,
UPDATE
o campo com o texto recodificado. Desnecessário dizer que isso será lento e desajeitado, mas se cada campo puder ter uma codificação diferente, não há muito mais a ser feito.Tal abordagem é inexata e propensa a erros. Ele ainda vai deixar você com texto mutilado onde as codificações são mal adivinhadas. No entanto, esse texto provavelmente também foi exibido mutilado no aplicativo antes, porque seria armazenado em uma codificação e depois reinterpretado em outra para exibição.
Você pode usar uchardet para determinar a codificação:
https://code.google.com/p/uchardet/
Em seguida, use iconv, possivelmente com -c, para converter entre codificações:
http://www.documentroot.com/2013/12/utf8-encoding-and-postgres-dump.html