the*_*ory 9 oracle unicode utf-8 character-encoding
由于遗留原因,我们在Oracle 10数据库中有一个VARCHAR2列 - 其中字符编码设置为AL32UTF8
-that包含一些非UTF-8值.值始终位于以下字符集之一:
我编写了一个Perl函数来修复数据库外的破坏值.对于此数据库列中的值,它会遍历此编码列表并尝试将值转换为UTF-8.如果转换失败,则尝试下一次编码.第一个无错误转换的是我们保留的价值.现在,我想在数据库中复制此功能,以便任何人都可以使用它.
但是,我能找到的就是CONVERT
函数,它永远不会失败,但是为它无法识别的字符插入替换字符.因此,据我所知,无法知道转换何时失败.
因此,我有两个问题:
更新:
作为参考,我在PL/pgSQL中编写了这个PostgreSQL函数,它完全符合我的需要:
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;
$$;
Run Code Online (Sandbox Code Playgroud)
我非常想知道如何在Oracle中做同等的事情.
感谢关于@collapsar的UTF-8非法字符的关键信息,以及同事的一些挖掘,我想出了这个:
CREATE OR REPLACE FUNCTION reencode(string IN VARCHAR2) RETURN VARCHAR2
AS
encoded VARCHAR2(32767);
type array_t IS varray(3) OF VARCHAR2(15);
array array_t := array_t('AL32UTF8', 'WE8MSWIN1252', 'WE8ISO8859P1');
BEGIN
FOR I IN 1..array.count LOOP
encoded := CASE array(i)
WHEN 'AL32UTF8' THEN string
ELSE CONVERT(string, 'AL32UTF8', array(i))
END;
IF instr(
rawtohex(
utl_raw.cast_to_raw(
utl_i18n.raw_to_char(utl_raw.cast_to_raw(encoded), 'utf8')
)
),
'EFBFBD'
) = 0 THEN
RETURN encoded;
END IF;
END LOOP;
RAISE VALUE_ERROR;
END;
Run Code Online (Sandbox Code Playgroud)
奇怪的是,它永远不会到达WE8ISO8859P1:WE8MSWIN1252转换我所拥有的800个左右的错误值列表中的每一个都没有抱怨.我的Perl或PostgreSQL实现也是如此,其中CP1252因某些值失败但ISO-8859-1成功.尽管如此,Oracle的值似乎已经足够了,并且似乎是有效的Unicode(通过将它们加载到PostgreSQL中进行测试),所以我不能抱怨.我认为,这足以清理我的数据.
归档时间: |
|
查看次数: |
78428 次 |
最近记录: |