Per motivi legacy, abbiamo una colonna VARCHAR2 nel nostro database Oracle 10, in cui la codifica dei caratteri è impostata su AL32UTF8
, che contiene alcuni valori non UTF-8. I valori sono sempre in uno di questi set di caratteri:Come posso convertire i valori Oracle VARCHAR2 in UTF-8 da un elenco di possibili codifiche?
- US-ASCII
- UTF-8
- CP1252
- Latin-1
Ho scritto una funzione di Perl per correggere i valori danneggiati al di fuori del database. Per un valore da questa colonna del database, scorre in questo elenco di codifiche e tenta di convertire il valore in UTF-8. Se la conversione fallisce, prova la prossima codifica. Il primo a convertire senza errori è il valore che manteniamo. Ora, vorrei replicare questa funzionalità all'interno del database in modo che chiunque possa usarlo.
Tuttavia, tutto ciò che posso trovare per questo è lo CONVERT
function, che non fallisce mai, ma inserisce un carattere di sostituzione per i caratteri che non riconosce. Quindi non c'è modo, per quanto posso dire, di sapere quando la conversione è fallita.
Perciò, ho due domande:
- c'è qualche interfaccia esistente che cerca di convertire una stringa in una di elenco delle codifiche, restituendo il primo che riesce?
- E se no, c'è qualche altra interfaccia che indica un errore se non è in grado di convertire una stringa in una codifica? Se è così, allora potrei scrivere la funzione precedente.
UPDATE:
Per avere un riferimento, ho scritto questa funzione PostgreSQL in PL/pgSQL che fa esattamente quello che mi serve:
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;
$$;
avrei caro piace sapere come fare l'equivalente in Oracle.
ciò che accade nel tuo codice è che tu * prima * cerchi di convertire i tuoi dati di input in al32utf8 con il comando 'convert', quindi verifica se l'operazione ha avuto successo. tuttavia, per i set di caratteri orientati ai byte, che cp1252 capita di essere, ogni codifica ha la lunghezza di esattamente 1 byte: la conversione in unicode non fallirà mai. quindi il tuo controllo avrà successo e la funzione 'reencode' uscirà. si noti che non è possibile distinguere tra i set di caratteri codificati in byte mediante una conversione corretta in unicode: per farlo è necessario disporre di informazioni contestuali. Saluti. – collapsar
(continua). 1.) tecnicamente, la mia affermazione si applica solo ai set di caratteri (codificati in byte) i cui glifi sono incorporati in unicode. non sono a conoscenza di alcun charset che non soddisfi questo criterio (suggerimenti apprezzati). 2.) per identificare il set di caratteri sorgente, si può 2a.) Nel caso particolare di latin-1 vs cp1252 controllare per byte che non sono mappati ai glifi in latin-1 (0x7f-0x9f) o 2b.) In generale per sequenze invece di singoli caratteri. esempio: A4 -> EURO (latin-15)/VALUTA (cp1252). quest'ultimo non si verifica dopo i numeri nei testi ordinari, quindi " A4" indica latino-15. –
collapsar
Purtroppo non ho informazioni contestuali e quindi sto solo ripulendo alcune vecchie cose. Alcune migliaia di convertiti in CP1252 su oltre un miliardo di dischi sono qualcosa con cui possiamo convivere. – theory