Por razones heredadas, tenemos una columna VARCHAR2 en nuestra base de datos Oracle 10, donde la codificación de caracteres se establece en AL32UTF8
, que contiene algunos valores que no son UTF-8. Los valores son siempre en uno de estos conjuntos de caracteres:¿Cómo puedo convertir los valores de Oracle VARCHAR2 a UTF-8 de una lista de posibles codificaciones?
- US-ASCII
- UTF-8
- CP1252
- América-1
He escrito una función de Perl para arregla valores rotos fuera de la base de datos. Para un valor de esta columna de base de datos, recorre esta lista de codificaciones e intenta convertir el valor a UTF-8. Si la conversión falla, intenta la siguiente codificación. El primero en convertir sin error es el valor que guardamos. Ahora, me gustaría replicar esta funcionalidad dentro de la base de datos para que cualquiera pueda usarla.
Sin embargo, todo lo que puedo encontrar para esto es CONVERT
function, que nunca falla, pero inserta un carácter de reemplazo para los caracteres que no reconoce. Entonces, de acuerdo con lo que puedo decir, no hay forma de saber cuándo falló la conversión.
para ello, tengo dos preguntas:
- ¿Hay alguna interfaz existente que trata de convertir una cadena en uno de la lista de codificaciones, volviendo la primera que tiene éxito?
- Y si no, ¿hay alguna otra interfaz que indique fallas si no puede convertir una cadena a una codificación? Si es así, entonces podría escribir la función anterior.
ACTUALIZACIÓN:
Como referencia, he escrito esta función PostgreSQL en PL/pgSQL que hace exactamente lo que necesito:
CREATE OR REPLACE FUNCTION encoding_utf8(
bytea
) RETURNS TEXT LANGUAGE PLPGSQL STRICT IMMUTABLE AS $$
DECLARE
encoding TEXT;
BEGIN
FOREACH encoding IN ARRAY ARRAY[
'UTF8',
'WIN1252',
'LATIN1'
] LOOP
BEGIN
RETURN convert_from($1, encoding);
EXCEPTION WHEN character_not_in_repertoire OR untranslatable_character THEN
CONTINUE;
END;
END LOOP;
END;
$$;
Me encantaría saber cómo hacer el equivalente en Oracle.
lo que sucede en su código es que * primero * intente convertir sus datos de entrada a al32utf8 llamando a 'convertir', y luego verifique si la operación fue exitosa. sin embargo, para conjuntos de caracteres orientados a bytes, lo que sucede es que cp1252 es, cada codificación tiene la longitud de exactamente 1 byte, la conversión a unicode nunca fallará. por lo tanto, su verificación tendrá éxito y la función 'reencode' saldrá. tenga en cuenta que es imposible distinguir entre conjuntos de caracteres de origen codificados por bytes mediante una conversión exitosa a unicode, necesita información contextual para hacerlo. Saludos. – collapsar
(cont.). 1.) técnicamente, mi enunciado solo se aplica a los conjuntos de caracteres (codificados en bytes) cuyos glifos se incorporan a unicode. No conozco ningún juego de caracteres que no cumpla con este criterio (sugerencias apreciadas). 2.) para identificar el juego de caracteres de origen, puede 2a) en el caso particular de latin-1 vs cp1252 comprobar los bytes que no están mapeados en glifos en latin-1 (0x7f-0x9f) o 2b) en verificación general para secuencias en lugar de caracteres individuales. ejemplo: A4 -> EURO (latin-15)/CURRENCY (cp1252). esto último no ocurrirá después de los números en los textos ordinarios, por lo que ' A4 'indicaría latin-15. –
collapsar
Lamentablemente, no tengo información contextual, así que estoy limpiando algunas cosas viejas. Unos pocos miles convertidos a CP1252 de más de mil millones de registros es algo con lo que podemos vivir. – theory