Mal*_*ous 3 oracle character-set utf-8
我希望修复 Oracle 中的数据表,理想情况下是通过非特权 SQL,该 SQL 已将 UTF-8 数据插入到 UTF-8 数据库中,错误地使用了 Latin-1 字符集。
该符号? GREEK SMALL LETTER BETA应该已进入数据库,但两个字符β已进入......因为两个 UTF-8 字符
Î LATIN CAPITAL LETTER I WITH CIRCUMFLEX后跟² SUPERSCRIPT TWO.
此示例代码演示了问题和修复方法,但它仅适用于VARCHAR列。一旦CLOB使用了a ,转换就会失败:
-- 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;
Run Code Online (Sandbox Code Playgroud)
但是,如果VARCHAR2(20)更改为,CLOB则不再有效。 CONVERT()返回垃圾字符。我可以TO_CHAR()用来解决这个问题,但最终我得到一个错误,该错误CLOB超过 4000 个字符,因此TO_CHAR()失败。
当使用CLOB超过 4000 个字符的列时,有没有办法让上面的例子工作?
DBMS_LOB包也有转换功能。不幸的是,不支持将 CLOB 转换为 CLOB 并一步更改字符集,因此首先将数据转换为 BLOB,然后再转换回 CLOB。
CREATE TABLE EXAMPLE (T CLOB);
INSERT INTO EXAMPLE (T) VALUES ('Example β ');
begin
for i in 1..12
loop
update example set t = t || t;
end loop;
commit;
end;
/
select dbms_lob.getlength(t) from example;
DBMS_LOB.GETLENGTH(T)
---------------------
45056
Run Code Online (Sandbox Code Playgroud)
现在转换部分:
create or replace function repair_data (p_clob clob) return clob as
l_blob blob;
l_dest_offset number := 1;
l_src_offset number := 1;
l_lang_context number := 0;
l_warning number;
l_result clob;
begin
dbms_lob.createtemporary(l_blob, true, dbms_lob.call);
dbms_lob.createtemporary(l_result, true, dbms_lob.call);
dbms_lob.converttoblob(l_blob, p_clob, dbms_lob.lobmaxsize, l_dest_offset, l_src_offset,
nls_charset_id('WE8ISO8859P1'), l_lang_context, l_warning);
l_dest_offset := 1;
l_src_offset := 1;
l_lang_context := 0;
dbms_lob.converttoclob(l_result, l_blob, dbms_lob.lobmaxsize, l_dest_offset, l_src_offset,
nls_charset_id('AL32UTF8'), l_lang_context, l_warning);
return l_result;
end;
/
select repair_data(T) from example;
REPAIR_DATA(T)
-----------------------------
Example ? Example ? Example ? ...
update example set t = repair_data(t);
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8855 次 |
| 最近记录: |