- 浏览: 49523 次
- 性别:
- 来自: 北京
最新评论
环境:
DB-A 字符集:US7ASCII
DB-B 字符集:ZHS16GBK
需求: 从DB-A中将一个表的中文数据通过JAVA定时任务同步到DB-B.
DB-A库中表的信息如下:
CREATE TABLE USER_INFO (USER_ID number, USER_NAME varchar2(50));
如果用一般的方式来SELECT,和INSERT,不管客户端用什么样的字符集,数据到DB-B上肯定会显示乱码.
解决方法1 (在数据库实现)
解决思路:通过视图将数据转换成二进制数据,绕过字符集的转换,然后让目标库来读取.
1. 在DB-A库上创建视图:
create or replace view view_user_info
as
select user_id, utl_raw.cast_to_raw(user_name) user_name from user_info ;
2. 在DB-B库上创建视图:
create or replace view view_user_info_db_a
as
select user_id, utl_raw.cast_to_varchar2 (user_name) user_name from view_user_info@db_a;
3. 在DB-B库上进行数据读取:
select user_id,user_name from view_user_info_db_a ;
这时显示出来的数据才是正确的!
其实就是:select utl_raw.cast_to_raw('中华人民'),utl_raw.cast_to_varchar2('D6D0BBAAC8CBC3F1') from dual;
优点: 对JAVA程序来说是透明的,无所改动代码。
数据提取时,与客户端字符集无关
缺点: 增加数据库CPU开销
--经过钟MM的提示学习到了以下方法:
解决方法2 (在JAVA实现)
使用JAVA的两个函数来实现:getBytes() , new String()
先来看一下这两个函数:
. getBytes(charset)
这是java字符串处理的一个标准函数,其作用是将字符串所表示的字符按照charset编码,并以字节方式表示。
注意字符串在java内存中总是按unicode编码存储的。
比如"中文",正常情况下(即没有错误的时候)存储为"4e2d 6587",
如果charset为"gbk",则被编码为"d6d0 cec4",然后返回字节"d6 d0 ce c4"。
如果charset为"utf8"则最后是"e4 b8 ad e6 96 87"。
如果是"iso8859-1",则由于无法编码,最后返回 "3f 3f"(两个问号)。
. new String(charset)
这是java字符串处理的另一个标准函数,和上一个函数的作用相反,将字节数组按照charset编码进行组合识别,最后转换为unicode存储。
参考上述getBytes的例子,"gbk" 和"utf8"都可以得出正确的结果"4e2d 6587",但iso8859-1最后变成了"003f 003f"(两个问号)。
因为utf8可以用来表示/编码所有字符,所以new String( str.getBytes( "utf8" ), "utf8" ) === str,即完全可逆。
对于以上两个函数,我们可以有两种用法来解决这个问题:
方法 2.1
a) 无需关心客户端NLS_LANG的设置
b) 从数据库取出字符的二进制编码:
select user_id, utl_raw.cast_to_raw(user_name) user_name from user_info ;
c) 在java用其所 new String(username, 'GBK' ) 转成中文
d) 插入到目标库
方法 2.2 (推荐)
a) 将JAVA 客户端NLS_LANG设置为US7ASCII
b) 从数据库直接取出字段值
select user_id, user_name from user_info ;
(这时因为客户端和服务器的字符集一致,所以会得到正确的中文显示)
c) 将中文进行转码为GBK:
new String( user_name.getBytes( "gbk" ), "gbk" )
d) 得到正确的GBK中文编码插入到目标库
优点:代码完全由JAVA控制,无需作数据库变更,数据库的压力转移到了JAVA客户端.
注意:必须把客户端的字符集和服务器端的字符集设置成一样
DB-A 字符集:US7ASCII
DB-B 字符集:ZHS16GBK
需求: 从DB-A中将一个表的中文数据通过JAVA定时任务同步到DB-B.
DB-A库中表的信息如下:
CREATE TABLE USER_INFO (USER_ID number, USER_NAME varchar2(50));
如果用一般的方式来SELECT,和INSERT,不管客户端用什么样的字符集,数据到DB-B上肯定会显示乱码.
解决方法1 (在数据库实现)
解决思路:通过视图将数据转换成二进制数据,绕过字符集的转换,然后让目标库来读取.
1. 在DB-A库上创建视图:
create or replace view view_user_info
as
select user_id, utl_raw.cast_to_raw(user_name) user_name from user_info ;
2. 在DB-B库上创建视图:
create or replace view view_user_info_db_a
as
select user_id, utl_raw.cast_to_varchar2 (user_name) user_name from view_user_info@db_a;
3. 在DB-B库上进行数据读取:
select user_id,user_name from view_user_info_db_a ;
这时显示出来的数据才是正确的!
其实就是:select utl_raw.cast_to_raw('中华人民'),utl_raw.cast_to_varchar2('D6D0BBAAC8CBC3F1') from dual;
优点: 对JAVA程序来说是透明的,无所改动代码。
数据提取时,与客户端字符集无关
缺点: 增加数据库CPU开销
--经过钟MM的提示学习到了以下方法:
解决方法2 (在JAVA实现)
使用JAVA的两个函数来实现:getBytes() , new String()
先来看一下这两个函数:
. getBytes(charset)
这是java字符串处理的一个标准函数,其作用是将字符串所表示的字符按照charset编码,并以字节方式表示。
注意字符串在java内存中总是按unicode编码存储的。
比如"中文",正常情况下(即没有错误的时候)存储为"4e2d 6587",
如果charset为"gbk",则被编码为"d6d0 cec4",然后返回字节"d6 d0 ce c4"。
如果charset为"utf8"则最后是"e4 b8 ad e6 96 87"。
如果是"iso8859-1",则由于无法编码,最后返回 "3f 3f"(两个问号)。
. new String(charset)
这是java字符串处理的另一个标准函数,和上一个函数的作用相反,将字节数组按照charset编码进行组合识别,最后转换为unicode存储。
参考上述getBytes的例子,"gbk" 和"utf8"都可以得出正确的结果"4e2d 6587",但iso8859-1最后变成了"003f 003f"(两个问号)。
因为utf8可以用来表示/编码所有字符,所以new String( str.getBytes( "utf8" ), "utf8" ) === str,即完全可逆。
对于以上两个函数,我们可以有两种用法来解决这个问题:
方法 2.1
a) 无需关心客户端NLS_LANG的设置
b) 从数据库取出字符的二进制编码:
select user_id, utl_raw.cast_to_raw(user_name) user_name from user_info ;
c) 在java用其所 new String(username, 'GBK' ) 转成中文
d) 插入到目标库
方法 2.2 (推荐)
a) 将JAVA 客户端NLS_LANG设置为US7ASCII
b) 从数据库直接取出字段值
select user_id, user_name from user_info ;
(这时因为客户端和服务器的字符集一致,所以会得到正确的中文显示)
c) 将中文进行转码为GBK:
new String( user_name.getBytes( "gbk" ), "gbk" )
d) 得到正确的GBK中文编码插入到目标库
优点:代码完全由JAVA控制,无需作数据库变更,数据库的压力转移到了JAVA客户端.
注意:必须把客户端的字符集和服务器端的字符集设置成一样
发表评论
-
Oracle的left join中on和where的区别
2012-10-26 15:43 880Oracle的left join中on和where的区别 数 ... -
动态sql拼接单引号与 变量赋值
2012-06-21 10:09 3731if (lower(s_table)='gl_deta ... -
ora-00031:session marked for kill处理oracle中杀不掉的锁
2012-06-19 16:36 965转: 一些ORACLE中的进程被杀掉后,状态被置为" ... -
使用DBLINK为远程数据库的用户表创建同义词
2012-06-19 14:39 8461、创建db_link create database l ... -
以字符串数组为输入参数的存储过程
2012-06-19 14:27 2659今天项目中需要用到存 ... -
函数的使用
2012-06-04 17:09 901create or replace function Fun_ ... -
Oracle中decode的使简单例子
2012-06-04 17:06 1400decode(字段,表达式1,表达式2,表达式。。。) 当,字 ... -
oracle触发器
2012-04-20 09:11 655表: A 字段:a, b, c 当修改a字段的值时触发 c字段 ... -
oracle的全文索引
2012-04-16 14:29 744已有几个项目组开始使 ... -
单独的plsql链接数据库
2011-10-14 16:03 862转的: plsql 可不可以 ... -
Oracle经验集锦
2011-09-24 13:32 6451.删除表空间 DROP ... -
Oracle分区表详解 .
2011-08-06 10:42 598一、Oracle分区简介 ORACLE的分区是一种处理超大型 ... -
利用 rowid 提升update性能 .
2011-08-04 23:52 1772能不能想办法 提升一下如下update语句的性能 UPDA ... -
oracle全文索引的简单配置
2011-08-04 23:49 9551.创建数据存储定义(Datastore),使用多列数据存储在 ... -
用java调用oracle存储过程总结
2011-08-04 23:45 5991、什么是存储过程。存 ... -
Oracle SCN详解
2011-08-04 23:38 565pre. Oracle中的SCN(system change ... -
oracle 数据库里查看表空间使用状况
2011-08-04 23:34 603oracle表空间的事情状况要经常查看,一般空闲比例过低的时候 ... -
采用全文索引解决模糊查询速度慢的问题
2011-08-04 23:31 712众所周知,使用 like 进行模糊查询速度极差,包括 like ... -
oracle9i在windows上的dataguard配置
2011-08-04 23:23 659主库:win2003 server ora9i(9.2.0.1 ... -
Rman duplicate数据库复制(单系统)
2011-08-04 23:22 599一、实验环境: 1. 虚拟机:VMware Ser ...
相关推荐
解决不同字符集数据库间的数据同步问题 utl_raw_cast_to_raw utl_raw_cast_to_varchar2
修改数据库字符集修改数据库字符集
oracle数据库字符集 无法修改数据库字符集 乱码
Oracle数据库字符集问题解决方案大全.doc,搜罗的一些关于Oracle数据库的汉字无法正常显示的解决方案。希望对于需要的朋友有用。
修改oracle数据库字符集详细的操作命令
Oracle数据库字符集问题解析.pdf
为了确保Export、Import过程中,Oracle字符集不发生转换或正 确转换,建议最好在进行这个过程前,检查一下源数据库字符集与Export用户会话字符集是否一致,源数据库字符集与目标数据库字符集是否一致,目标数据库...
数据库字符集修改方法
修改Oracle数据库字符集的命令行方法。 在Oracle10g上也可以使用
字符集在创建数据库时指定,在创建后通常不能更改,所以在创建数据库时能否选择一个正确的字符集就显得尤为重要。
ORACLE修改数据库字符集
由于oracle字符集种类多,且在存储、检索、迁移oracle数据时多个环节与字符集的设置密切相关,因此在实际的应用中,数据库开发和管理人员经常会遇到有关oracle字符集方面的问题。本文通过以下几个方面阐述,对oracle...
在不同数据库做数据迁移、同其它系统交换数据等,常常因为字符集不同而导致迁移失败或数据库内数据变成乱码。现将oracle字符集相关的一些知识做了个简单总结
修改oracle数据库的字符集方法(RAC),适用RAC
Oracle数据库字符集问题及其解决方法.pdf
字符集不同的Oracle数据库间交换数据的解决方法.pdf
Oracle数据库升迁时字符集问题的解决.pdf
Oracle数据库字符集问题分析及解决方法.pdf
对Oracle数据库字符集若干问题的探讨.pdf
Oracle数据库字符集的查询[定义].pdf