数据库是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的值正常显示中文? 请教各为高手!!! 分不够可再加,先谢过!

解决方案 »

  1.   

    试一下以下的方法:(基于WINDOWS操作系统)
    在A数据库上:
      (1)打开CMD
      (2)设置参数NLS_LANG='simplified chinese'_china.zhs16gbk;
      (3)执行EXP命令.
    在B数据库上:
      (1)执行IMP命令.
    可以解决你的问题
      

  2.   


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

  3.   

     修改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%'; 从网上找来的,不难呀?哪里看不明白,就再发出来
      

  4.   

    下面的楼主参考一下:一、字符集参数  
    一旦数据库创建后,数据库的字符集是不能改变的。因此,考虑使用哪一种字符集是十分重要的。数据库字符集应该是操作系统本地字符集的一个超集。存取数据库的客户使用的字符集将决定选择哪一个超集,即数据库字符集应该是所有客户字符集的超集。  
    下面介绍一些与字符集有关的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等)转换。  
      

  5.   

    访问不同字符集的数据库,是这个意思吧
    用与A一样的字符集联A库,读出数据,断开连接,将环境变量(或改注册表)改为B库字符集,保存数据。
      

  6.   

    先谢过楼上各位,无论答案最终正确与否,只要是相关的思路、意见本人都会散分,感谢各位的热心,也请继续参与…… ^_^
    A库字符集安装的时候已经选择了AMERICAN_AMERICA.US7SCII,目前有几十万的数据量。若是改Oracle服务端字符集担心数据库会有崩溃掉的可能,客户也不会同意;改客户端字符集(通过改注册表的方式)的话用PL/SQL Developer查询数据正常显示中文。但这应该属于一种“欺骗”的行为。
    因为:中文在A库中虽然是以us7ascii存放的,但客户端和服务端字符集若相同则系统默认是不进行中间字符集转换的,也就是说中文数据不会造成“丢失”。
    这样在客户端会正常显示中文。但其本质上A库相应表中存放的还是中文数据对应的us7ascii码,这样的话A库不通过备份/恢复的方式直接以dblink连接B库并将数据插入到B库(字符集:SIMPLIFIED CHINESE_CHINA.ZHS16GBK)中,B库显示的一定是乱码呀。所以改客户端的字符集是没用的,而服务端的字符集又不允许改,各位大侠还有其他的方法吗?  不吝赐教,多谢!!!
      

  7.   

    楼主的情况应该是属于典型的用错误的字符集存储了“正确”的信息。对于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导入,应该也不复杂。
    仅供参考.
      

  8.   


    不一定要建视图,举个例子。比如:
    可以在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中可以利用触发器实现自动化,看你的实际情况吧。)
      

  9.   

    楼上的兄弟,多谢了,tab_temp是临时表吧,可是给我的用户只有可以连接数据库、查询表的权限,其他什么权限都没有哇
    临时表建不了……  5555555555555555
      

  10.   

    那么不通过建表或视图的方式,直接查询可以么?
    比如:select utl_raw.cast_to_varchar2(utl_raw.cast_to_raw(x)) from tab@Blink
      

  11.   


    这个转换已经无意义了,字段x从DBLINK进来的时候已经被重新编码。
    ps:可以把需求描述的更详细点吗?是一次性的数据迁移还是日常操作?
      

  12.   

    数据库建好之后不大好搞,在数据库创建的时候直接把字符集设置成utf-8就不会出现这种问题了。
      

  13.   

    kan kan 13 lou de jie guo shi sm 
      

  14.   

    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 [email protected];
    4、第四步:在B库中插入操作:如下
     
      insert into b select utl_raw.cast_to_varchar2(name) name from a_tab;