oracle字符集问题(us7ascii 转 zhs16gbk)

千骑卷平冈 2009-01-11 12:57:31
数据库是Oracle9i的,但字符集设置的是:us7ascii,而正常保存中文数据的数据库字符集是:zhs16gbk。
请问各位Oracle有没有什么内置的函数,可以将us7ascii字符集下的数据转换成zhs16gbk下的数据,并且能正常显示中文。

我试过用convert函数不管用,utl_raw.cast_to_varchar2()和UTL_RAW.CAST_TO_RAW()联合使用也不管用。

我的意思是:现有两个Oracle数据库:A(字符集为us7ascii的库)和B(字符集为zhs16gbk的库)
假如我在A数据库中查询:select a.name from A a
如果不做任何处理就把name的值插入到B数据库中,数据肯定是乱码。
要怎样处理才能使B数据库中name的值正常显示中文?

请教各为高手!!! 分不够可再加,先谢过!
...全文
4254 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
简易人 2011-09-15
  • 打赏
  • 举报
回复
1、第一步:在A库中建立视图如下
create or replace view a_tab as
select ID,UTL_RAW.CAST_TO_RAW(NAME)NAME from a;

2、第二步:在B数据库中建立DBLink链接连接到A数据库中
-- Create database link
create database link ORCL.US.ORACLE.COM
connect to SOFT
using '(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.2.180)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl)
)
)';

3、第三步:在B库中建立同义词将在A库中建立的视图映射过来(此处的同义词将是A库中转过码的视图)

create or replace synonym a_tab for user.T@ORCL.US.ORACLE.COM;


4、第四步:在B库中插入操作:如下

insert into b select utl_raw.cast_to_varchar2(name) name from a_tab;


vainkeen 2011-04-21
  • 打赏
  • 举报
回复
kan kan 13 lou de jie guo shi sm
richard_first 2009-02-18
  • 打赏
  • 举报
回复
数据库建好之后不大好搞,在数据库创建的时候直接把字符集设置成utf-8就不会出现这种问题了。
butchroller 2009-01-13
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 wqmain 的回复:]
那么不通过建表或视图的方式,直接查询可以么?
比如:select utl_raw.cast_to_varchar2(utl_raw.cast_to_raw(x)) from tab@Blink
[/Quote]

这个转换已经无意义了,字段x从DBLINK进来的时候已经被重新编码。
ps:可以把需求描述的更详细点吗?是一次性的数据迁移还是日常操作?
千骑卷平冈 2009-01-13
  • 打赏
  • 举报
回复
那么不通过建表或视图的方式,直接查询可以么?
比如:select utl_raw.cast_to_varchar2(utl_raw.cast_to_raw(x)) from tab@Blink
千骑卷平冈 2009-01-13
  • 打赏
  • 举报
回复
楼上的兄弟,多谢了,tab_temp是临时表吧,可是给我的用户只有可以连接数据库、查询表的权限,其他什么权限都没有哇
临时表建不了…… 5555555555555555
butchroller 2009-01-13
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 wqmain 的回复:]
那么,一定要在A库中建视图吗? 假如用户没有建视图的权限又该怎么办?
[/Quote]

不一定要建视图,举个例子。比如:
可以在A中执行插入:insert into tab_temp@Blink select utl_raw.cast_to_raw(x) from tab;
然后在B中执行转换:insert into tab select utl_raw.cast_to_varchar2(x) from tab_temp;
(或者B中可以利用触发器实现自动化,看你的实际情况吧。)
xingkongmori 2009-01-12
  • 打赏
  • 举报
回复
看过,不会,值得学习
butchroller 2009-01-12
  • 打赏
  • 举报
回复
楼主的情况应该是属于典型的用错误的字符集存储了“正确”的信息。

对于us7ascii转zhs16gbk用utl_raw.cast_to_varchar2()和UTL_RAW.CAST_TO_RAW()应该是可行的。
要注意的是,cast_to_raw()要在源库,如:
 create view v_tab as select utl_raw.cast_to_raw(x) x from tab; 

而cast_to_varchar2()要在目标库,如:
 insert into tab select utl_raw.cast_to_varchar2(x) from v_tab@Blink; 

其原则就是:通过两个database的边界必须以raw形式,这样就避免了Oracle自动的字符集转换。

还有种办法就是将原表数据以文本形式导出至操作系统文件,然后到目标库sqlldr导入,应该也不复杂。
仅供参考.
千骑卷平冈 2009-01-12
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 butchroller 的回复:]
楼主的情况应该是属于典型的用错误的字符集存储了“正确”的信息。

对于us7ascii转zhs16gbk用utl_raw.cast_to_varchar2()和UTL_RAW.CAST_TO_RAW()应该是可行的。
要注意的是,cast_to_raw()要在源库,如:

SQL code create view v_tab as select utl_raw.cast_to_raw(x) x from tab;


而cast_to_varchar2()要在目标库,如:

SQL code insert into tab select utl_raw.cast_to_varchar2(x) from v_tab@Blink; …
[/Quote]

多谢!你说的很清楚,我也明白了。那么,一定要在A库中建视图吗? 假如用户没有建视图的权限又该怎么办?
谢谢大家 我会尽快结贴……
千骑卷平冈 2009-01-11
  • 打赏
  • 举报
回复
先谢过楼上各位,无论答案最终正确与否,只要是相关的思路、意见本人都会散分,感谢各位的热心,也请继续参与…… ^_^
A库字符集安装的时候已经选择了AMERICAN_AMERICA.US7SCII,目前有几十万的数据量。若是改Oracle服务端字符集担心数据库会有崩溃掉的可能,客户也不会同意;改客户端字符集(通过改注册表的方式)的话用PL/SQL Developer查询数据正常显示中文。但这应该属于一种“欺骗”的行为。
因为:中文在A库中虽然是以us7ascii存放的,但客户端和服务端字符集若相同则系统默认是不进行中间字符集转换的,也就是说中文数据不会造成“丢失”。
这样在客户端会正常显示中文。但其本质上A库相应表中存放的还是中文数据对应的us7ascii码,这样的话A库不通过备份/恢复的方式直接以dblink连接B库并将数据插入到B库(字符集:SIMPLIFIED CHINESE_CHINA.ZHS16GBK)中,B库显示的一定是乱码呀。

所以改客户端的字符集是没用的,而服务端的字符集又不允许改,各位大侠还有其他的方法吗? 不吝赐教,多谢!!!
smartcobra 2009-01-11
  • 打赏
  • 举报
回复
访问不同字符集的数据库,是这个意思吧
用与A一样的字符集联A库,读出数据,断开连接,将环境变量(或改注册表)改为B库字符集,保存数据。
wangxuhero 2009-01-11
  • 打赏
  • 举报
回复
下面的楼主参考一下:

一、字符集参数
一旦数据库创建后,数据库的字符集是不能改变的。因此,考虑使用哪一种字符集是十分重要的。数据库字符集应该是操作系统本地字符集的一个超集。存取数据库的客户使用的字符集将决定选择哪一个超集,即数据库字符集应该是所有客户字符集的超集。
下面介绍一些与字符集有关的NLS_LANG参数:
NLS_LANG格式:NLS_LANG=language_territory.charset
有三个组成部分(语言、地域和字符集),每个组成成分控制了NLS子集的特性。三个成分可以任意组合,例如:
AMERICAN_AMERICA.US7SCII
JPANESE_JAPAN.JA16EUC
其中:language 指定服务器消息的语言。
territory 指定服务器的日期和数字格式。
Charset 指定字符集
还有一些子集可以更明确定义NLS_LANG参数:
NLS_DATE_FORMAT 缺省的日期格式
NLS_DATE_LANGUAGE 缺省的日期语言
NLS_NUMBERIC_CHARACTERS 小数字符和组分隔开
NLS_CURRENCY 本地货币字符
NLS_ISO_CURRENCY ISO货币字符
NLS_SORT 字符排序序列
二、字符集转换
1、NLS_LANG参数的修改方法:
1)用SYS用户名登陆ORACLE。
2)查看字符集内容
SQL>SELECT * FROM PROPS$;
3)修改相应的字符子集
SQL>UPDATE PROPS$ SET VALUE$=’SIMPLIFIED CHINESE ‘
WHERE NAME=’NLS_LANGUAGE’;
4) 递交COMMIT;
2、NLS_LANG参数的具体应用:
1)采用服务器端/客户端方式,两端字符集不同
修改客户端字符集:
WIN:修改注册表
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\NLS_LANG
UNIX:按照1方法,直接进入ORACLE 修改。
2)不同字符集使用EXP/IMP命令
按照1方法,修改IMP端的字符集设置,如果是WIN系统,还必须修改注册表。注意:NLS_LANG三个子集的参数必须一致。另外,如果字符集单双字节设置不同,则不能通过修改字符集进行转换。可以使用其他方式,不修改字符集,进行ORACLE数据库搬移,如数据量比较小,可以使用SQLLOAD命令,通过文本文件转换;使用其他数据库软件(ACCESS,FOXPRO等)转换。
yf520gn 2009-01-11
  • 打赏
  • 举报
回复
修改Oracle字符集(character set)
本方法适用于Oracle9i, 10g以及XE. 在10.2.0.1.0下测试无错. 需要注意的是, 使用此方法会破坏数据库中的原有双字节字符. 一种办法是先将数据库导出, 修改完字符集后再导入; 另一种办法就是不管他, 就那样使用. 一般如果是一个测试环境, 像方法二那样就可以了, 但是可能某些表无法读取, 需要注意.

sql> shutdown immediate
sql> startup mount
sql> alter system enable restricted session;
sql> alter system set job_queue_processes=0;
sql> alter system set aq_tm_processes=0;
sql> alter database open;
sql> alter database character set <internal_use> AL32UTF8;
sql> shutdown immediate
sql> startup

这里的INTERNAL_USE可选,譬如用于不能从父集转到子集的场合,但是这样做会产生乱码,或者表中的数据不能读取。

如果数据库中存在CLOB字段,那么就不允许对字符集进行转换,此时可以查看alert<sid>.log文件,把含有CLOB的表trancate.

sql> trancate table [table_name];

转换后的数据库字符集可以通过以下命令察看.

sql> select name, value$ from props$ where name like '%NLS%';

从网上找来的,不难呀?哪里看不明白,就再发出来
千骑卷平冈 2009-01-11
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 bai_jiong 的回复:]
试一下以下的方法:(基于WINDOWS操作系统)
在A数据库上:
(1)打开CMD
(2)设置参数NLS_LANG='simplified chinese'_china.zhs16gbk;
(3)执行EXP命令.
在B数据库上:
(1)执行IMP命令.
可以解决你的问题
[/Quote]

谢谢您的回复,我不是备份和恢复数据库,只是想把A数据库某个表的若干条数据插入到B数据库的某个表中。
如果用A库以dblink的方式访问B库并插入数据,应该怎么办?
只是先修改一下A库客户端的字符集就可以吗?这样B库中显示A库插入过来的数据仍是乱码啊?
有没有其他方法,比如通过内置函数来处理?

期待回复,多谢!
bai_jiong 2009-01-11
  • 打赏
  • 举报
回复
试一下以下的方法:(基于WINDOWS操作系统)
在A数据库上:
(1)打开CMD
(2)设置参数NLS_LANG='simplified chinese'_china.zhs16gbk;
(3)执行EXP命令.
在B数据库上:
(1)执行IMP命令.
可以解决你的问题

10 数据库服务器字符集更改步骤 问题描述: 在客户端插入字符“咪咪”,从数据库中查询显示时出现乱码 处理步骤: 10.1 对数据库做全库导出,备份全库数据,以防故障发生 首先设定客户端的字符集,必须以ZHS16GBK字符集导出,然后才能在更改失败后顺利倒入新建的库。 #setenv NLS_LANG "SIMPLIFIED CHINESE_CHINA.ZHS16GBK"; #stty -istrip -parity cs8; #setenv LANG zh 拟在/sybdata(磁盘阵列)下建立一个目录orabak,用于存放dmp文件。 #mkdir /sybdata/orabak #chown oracle:oinstall /sybdata/orabak #su – oracle #cd /sybdata/orabak %exp system/manager@hnsdh file=hnsdh_2005-8-17 log=hnsdh_exp_2005-8-17 full=y (此处命名为示例,以实施当日日期为准) 察看日志结尾,以判定导出是否成功。 #cat hnsdh_2005-8-17.dmp | od -x | head 看第二和第三个字节组成的十六进制数是多少可判断导出文件的字符集。 示例如下 #cat example.dmp | od -x | head 0000000 0303 5445 5850 4f52 543a 5630 392e 3032 。。。 0000220 646d 7000 0000 0000 0000 0000 0000 0000 十六进制的0354化为十进制为852,参造下表 NLS_CHARSET_ID NLS_CHARSET_NAME HEX_ID -------------- ------------------------------ ------------- 1 US7ASCII 1 2 WE8DEC 2 3 WE8HP 3 4 US8PC437 4 5 WE8EBCDIC37 5 6 WE8EBCDIC500 6 7 WE8EBCDIC1140 7 8 WE8EBCDIC285 8 ................... 850 ZHS16CGB231280 352 851 ZHS16MACCGB231280 353 852 ZHS16GBK 354 853 ZHS16DBCS 355 860 ZHT32EUC 35c 861 ZHT32SOPS 35d 862 ZHT16DBT 35e 863 ZHT32TRIS 35f 864 ZHT16DBCS 360 865 ZHT16BIG5 361 866 ZHT16CCDC 362 867 ZHT16MSWIN950 363 868 ZHT16HKSCS 364 870 AL24UTFFSS 366 871 UTF8 367 872 UTFE 368 即可得出这个dmp文件的字符集ZHS16GBK。 10.2 在数据库中直接更改字符集参数 操作步骤如下: SQL> shutdown immediate SQL> startup mount SQL> ALTER SYSTEM ENABLE RESTRICTED SESSION; SQL> ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0; SQL> ALTER SYSTEM SET AQ_TM_PROCESSES=0; SQL> ALTER DATABASE OPEN; SQL> alter session set events '10046 trace name context forever,level 12'; SQL> alter database character set INTERNAL_USE ZHS16GBK; SQL> shutdown immediate SQL> startup 察看系统字符集 SQL> SELECT * FROM NLS_DATABASE_PARAMETERS; 看NLS_CHARACTERSET的值为多少,如果为ZHS16GBK则说明改动成功。 如果执行正常,则按照下一节进行测试操作。 10.3 更改成功后的测试 测试1,在数据库服务器端下测试 %setenv NLS_LANG "SIMPLIFIED CHINESE_CHINA.ZHS16GBK"; %stty -istrip -parity cs8; %setenv LANG zh %sqlplus /nolog SQL〉conn / as sysdba SQL〉create table test_tq (a char(20)); SQL〉insert into test_tq 1>(a) 2>values ('洣洣'); SQL〉select * from test_tq; 如显示为 A -------------------- 洣洣 则成功。 测试2,Windows客户端环境下测试 运 行REGEDIT,第一步选HKEY_LOCAL_MACHINE,第二步选择SOFTWARE, 第三步选择 ORACLE, 第四步选择 NLS_LANG, 键 入 与服 务 器 端 相 同 的 字 符 集(本例为:AMERICAN_AMERICAN.US7ASCII)。 右击我的电脑,然后点击属性,“高级”页面下,点击“环境变量”,在系统变量中添加: 变量名:NLS_LANG 变量值:SIMPLIFIED CHINESE_CHINA.ZHS16GBK 运行cmd,输入echo %NLS_LANG%,查看系统变量设置时否成功 然后运行: $sqlplus system/manager@hnsdh SQL〉conn / as sysdba SQL〉create table test_tq (a char(20)); SQL〉insert into test_tq 1>(a) 2>values ('洣洣'); SQL〉select * from test_tq; 如显示为 A -------------------- 洣洣 则成功。 10.4 更改不成功时的措施 新建数据库,设定字符集ZHS16GBK,其他参数先照搬原来的,并倒入数据。建库时所需的具体参数在重建之前要搜集。注意在配置控制文件时设定最大数据文件数。 建好数据库以后,执行以下命令即可恢复数据库 %cd /sybdata/orabak %imp system/manager@hnsdh full=y ignore=y file=hnsdh_2005-8-17 log=hnsdh_imp_2005 -8-17

3,490

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 高级技术相关讨论专区
社区管理员
  • 高级技术社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧