本人将一个US7ASCII字符集导出的DMP,导入到ZHS16GBK的10G数据库中。
导入完成后,发现其中原汉字部分都变成了“???????”。
查了一些材料,说只要将DMP中的第二、三字节改为ZHS16GBK字符集的标识再导入,就可以正常显示了,可是尝试了一下还是不行。这里我可以确保客户端和服务器的字符集环境变量一致。
于是又考将目的地数据库的字符集由ZHS16GBK改为US7ASCII,通过update props$ set value$的方法进行修改。但是,网上又有前辈说,不可以这样修改字符集,特别是不能从超级向子集修改(ZHS16GBK是US7ASCII的超级)。由于无路可走,最后还是硬着头皮把字符集改成了US7ASCII。然后将数据导了进去,汉字部分可以正常显示了。然后又将字符集改回ZHS16GBK,汉字还是可以正常显示。就此,此问题已经解决。
本人在此想求教各位高手,虽然问题解决了,但是,对这过程中的原理,及为何常规做法不能达成的结果却用非常规的方法可以实现?请哪位前辈给讲解一下其中的原理?

解决方案 »

  1.   

    常规导法错误在于你exp,imp操作所在的客户端nls_lang设置问题。由于这个设置的问题,导致你的exp-imp存在不正确的字符集转换。
      

  2.   


    我EXP,IMP时客户端的NLS_LANG和服务器的字符集都是对应同步的?怎么会出现设置问题?
      

  3.   

    简单说下我对字符集的理解:
    字符集在oracle中最大的体现就是取字节位的不同,ZHS16GBK与US7ASCII每次取字节位不一样,所以导致不同字符集数据转换的时候会出现乱码,打个比方,假如说US7ASCII是3位一取,而ZHS16GBK是4位一取,那么一个汉字的4位在US7ASCII中只能取3位,所以就出乱码.
    当你修改props$表的NLS_CHARACTERSET后,oracle每次取数据的位数就变了,所以你可以正确读取到DMP文件的内容,但是对于原库的数据就会产生影响.
    估计你的库中还是会有一些其他的问题你暂时没发现我的理解可能会有错误!希望高手指正,互相交流
      

  4.   

    导出数据库:
    select value from nls_database_parameters
    where parameter='NLS_CHARACTERSET';
    是什么值?exp操作所在客户端nls_lang是什么值?
    imp操作所在客户端nls_lang是什么值?
      

  5.   

    1.US7ASCII
    2.AMERICAN_AMERICA.US7ASCII
    3.SIMPLIFIED CHINESE_CHINA.ZHS16GBK
      

  6.   

    第三步imp时还是用US7ASCII,与导出一致。还有你导入后select时的所在客户机字符集没问题吧。US7ASCII到ZHS16GBK是个子超集关系,由US7ASCII导到ZHS16GBK不应有乱码。
      

  7.   

    又查了一下,在oracle 9i版本中由US7ASCII导到ZHS16GBK会乱码,这可能是因为Oracle9i的编码方案发生了较大改变。lz是用的9i吗?
      

  8.   

    不管怎么样,先作一次csscan再说.否则你后悔莫及啊.
      

  9.   


    数据库先还是和dmp一致US7ASCII,由于ZHS16GBK是超集,导入完成后,升级数据库的字符集到ZHS16GBK就可以了。修改字符集可以参考
    (有关字符集的子集和超级关系(来自Metalinke Doc: 119164.1))
    http://www.inthirties.com/?p=792(如何查询和修改Oracle的字符集)
    http://www.inthirties.com/?p=516