Estou procurando reparar uma tabela de dados no Oracle, de preferência via SQL sem privilégios, que teve dados UTF-8 inseridos em um banco de dados UTF-8, usando o conjunto de caracteres Latin-1 por engano.
O símbolo β GREEK SMALL LETTER BETA
deveria ter entrado no banco de dados, mas em vez disso os dois caracteres β
foram... como os dois caracteres UTF-8
Î LATIN CAPITAL LETTER I WITH CIRCUMFLEX
seguidos por ² SUPERSCRIPT TWO
.
Este código de exemplo demonstra o problema e a correção, mas só funciona com VARCHAR
colunas. Assim que a CLOB
é usado, a conversão falha:
-- This must return AL32UTF8 for this example to be valid
SELECT VALUE FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER='NLS_CHARACTERSET';
CREATE TABLE EXAMPLE (T VARCHAR2(20));
INSERT INTO EXAMPLE (T) VALUES ('Example β');
SELECT T FROM EXAMPLE; -- Should return 'Example β'
SELECT CONVERT(T, 'WE8ISO8859P1') FROM EXAMPLE;
UPDATE EXAMPLE SET T=CONVERT(T, 'WE8ISO8859P1');
SELECT T FROM EXAMPLE; -- Should return 'Example β', problem fixed
DROP TABLE EXAMPLE;
No entanto, se o VARCHAR2(20)
for alterado para CLOB
, isso não funcionará mais. CONVERT()
retorna caracteres de lixo. Eu posso usar TO_CHAR()
para contornar o problema, mas eventualmente recebo um erro que CLOB
tem mais de 4000 caracteres, então TO_CHAR()
falha.
Existe uma maneira de fazer o exemplo acima funcionar, ao usar uma CLOB
coluna com mais de 4000 caracteres?
DBMS_LOB
pacote também tem funções de conversão. Infelizmente, não há suporte para converter CLOB em CLOB e alterar o conjunto de caracteres em uma etapa, então os dados são convertidos primeiro em BLOB e depois de volta em CLOB.Agora a parte da conversão: