解决不同字符集数据库数据传输中文乱码问题
解决不同字符集数据库数据传输中文乱码问题
有两个数据库,使用US7ASCII字符集的数据库A和使用ZHS16GBK字符集的数据库B,如果想将数据库A中的中文字插入到B数据库,直接使用insert select会导致中文乱码。
一开始考虑的解决方法是应用程序在从A数据库select之前,更改session(连接到数据库A的session)的客户端字符集为US7ASCII,这样取出来的中文一定没有问题。同样在insert到数据库B之前,再修改session(连接到数据库B的session)的客户端字符集为ZHS16GBK。但是没有找到一种可以动态修改session字符集的方法,所以这个思路没走通。(注意:语句alter session set nls_lang =XXX是不合法的)
此时可以用Oracle提供的两个包函数来解决这个问题:
utl_raw.cast_to_raw(field name)
utl_raw.cast_to_varchar2(field name)
第一步:
我们首先通过toad直接连接到数据库A(US7ASCII),下图中表hxtemp的atdescription字段为中文,我们首先建立视图view_hxtemp,语句见下图,也可以看到view_hxtemp中atdescription字段的内容已经为RAW表示的16进制串了。
第二步:
在ZHS16GBK数据库中,插入该行的中文。
中文可以正常显示了。
注意:经过测试,如果不在US7ASCII字符集的数据库上做一个存放raw类型的中转表或视图的话,而是直接在ZHS16GBK数据库中直接写SQL语句通过dblink取utl_raw.cast_to_raw(atdescription),这样是得不到正确的RAW数据的,也就无法正确显示成原来的中文。
也就是说必须要在一个session中转换为raw,这样转换出来的raw才可以被另外一个数据库使用。
另外,在仅连接到一个数据库时,无论连接客户端使用什么字符集,都能取到正确的RAW数据。