• 0
  • 0
分享
  • 解锁Oracle数据库测试:三招攻克汉字乱码——软件测试圈
  • quinn 2024-07-04 11:43:14 字数 5868 阅读 537 收藏 0

  一、背景

  在我们日常的测试工作中,无论在数据迁移还是系统测试过程中,测试数据准确性和可用性是测试工作的重中之重,测试人员经常需要查询数据库中的数据或手工造测试数据,而登到oracle数据库后有时会发现显示中文乱码的情况,如下图所示:

1-1.png

  或者是:

1-2.png

  好好的怎么就乱码了呢?明明“之前”访问其他数据库是没问题。在学习和查询相关资料后我解决了这个问题,但由此引发了我对出现汉字乱码问题的学习兴趣,都是什么原因导致的汉字显示乱码呢?

  首先,字符集设置不当是影响Oracle数据库汉字显示的关键问题。下文则详细介绍了oracle关于字符集的分类、构成及设定方法,分析了ORACLE数据库汉字显示乱码的常见现象及原因,并针对各种现象及原因提出了行之有效的解决办法。

  二、关于字符集

  字符集是ORACLE为适应不同语言文字显示而设定的。用于汉字显示的字符集主要有ZHS16CGB231280、ZHS16GBK、US7ASCII和UTF-8等。字符集同时存在于服务器端和客户端。服务器端字符集是在安装ORACLE时指定的,字符集登记信息存储在ORACLE数据库字典的V$NLS_PARAMETERS表中;而客户端字符集是在系统注册表(WINDOWS系统)或在用户的环境变量(UNIX系统)中设定的。

  三、字符集的构成与设定

  字符集的构成与设定方式分为客户端与服务器端两种:

  (1)客户端字符集的构成与设定

  客户端的字符集是由当前用户的环境变量NLS_LANG设定的。环境变量NLS_LANG的构成:NLS_LANG=language_territory.charset

  其中:

        language 指定服务器消息的语言
        territory   指定服务器的日期和数字格式
        charset    指定字符集

  三个成分可以任意组合,例如:

        AMERICAN_AMERICA.US7SCII
        SIMPLIFIED CHINESE_CHINA.ZHS16GBK
        AMERICAN_AMERICA.ZHS16GBK

  WINDOWS系统是在注册表项:HKEY_LOCAL_MACHINE/SOFTWARE/ORACLE/HOME0/NLS_LANG中设定;

  (2)服务端字符集的构成与设定

  服务端字符集的构成体现在数据字典表V$NLS_PARAMETERS的NLS_LANGUAGE、NLS_TERRITORY、NLS_CHARACTERSET三项取值上,其中NLS_CHARACTERSET的取值就是具体的数据库字符集。如利用查询语句SQL>SELECT * FROM V$NLS_PARAMETERS;可得到如下结果:

  PARAMETER                   VALUE
  NLS_LANGUAGE           SIMPLIFIED CHINESE
  NLS_TERRITORY               CHINA
  NLS_CHARACTERSET           ZHS16GBK

  即当前数据库使用的字符集是ZHS16GBK。

  数据库服务端的字符集是在创建数据时设定的。但可通过如下方法对已设定的字符集进行修改:

  方法一:重建数据库。建立数据库时将数据库的字符集设定为所需字符集。

  方法二:修改SYS.PROPS$表。即用SYS用户登陆ORACLE后,利用下面语句修改相应的字符集并提交:SQL>UPDATE PROPS$ SET VALUE$=‘ZHS16GBK’WHERE NAME=‘NLS_CHARACTERSET’;SQL>COMMIT;

  通过此种方法来更改数据库字符集,只对更改后的数据有效,即数据库中原来的数据仍以原字符集被存储。

  方法三:在linux系统下,则需要手动替换整个字符集,具体操作如下:

  1.查看当前数据库字符集

  select * from nls_database_parameters
  where parameter='NLS_CHARACTERSET';
  -----------------------------------
  PARAMETER         VALUE
  NLS_CHARACTERSET WE8ISO8859P1

  2.将字符集修改为中文字符集ZHS16GBK(具体linux版本不同可能存在差异)

  SQL> shutdown immediate
  Database closed.
  Database dismounted.
  ORACLE instance shut down.
  SQL> STARTUP MOUNT;
  ORACLE instance started.
  Total System Global Area  734003200 bytes
  Fixed Size                  1221564 bytes
  Variable Size             264244292 bytes
  Database Buffers          465567744 bytes
  Redo Buffers                2969600 bytes
  Database mounted.
  SQL> ALTER SYSTEM ENABLE RESTRICTED SESSION;
  System altered.
  SQL> ALTER DATABASE OPEN;
  Database altered.
  SQL> ALTER DATABASE CHARACTER SET ZHS16GBK;
  ALTER DATABASE CHARACTER SET ZHS16GBK
  *
  ERROR at line 1:
  ORA-12712: new character set must be a superset of old character set
  SQL> ALTER DATABASE character set INTERNAL_USE ZHS16GBK;
  Database altered.
  SQL> SHUTDOWN IMMEDIATE;
  Database closed.
  Database dismounted.
  ORACLE instance shut down.
  SQL> startup
  ORACLE instance started.
  Total System Global Area  734003200 bytes
  Fixed Size                  1221564 bytes
  Variable Size             264244292 bytes
  Database Buffers          465567744 bytes
  Redo Buffers                2969600 bytes
  Database mounted.
  Database opened.

  此种方法依旧只对更改后的数据有效,即数据库中原来的数据仍以原字符集被存储。

  另外,有的还利用CREATE DATABASE CHARACTER SET ZHS16GBK命令暂时的修改字符集,当重启数据库后,数据库字符集将恢复原来的字符集。

  四、 查看数据库字符集

  这涉及三方面的字符集:

  一是:oracle server端的字符集;

  二是:oracle client端的字符集;

  三是:dmp文件的字符集;

  在做数据导入的时候,需要这三个字符集都一致才能正确导入。

  2.1查询oracle server端的字符集

  有很多种方法可以查出oracle server端的字符集

  ①比较直观的查询方法

  SQL> select userenv('language') from dual;

  查询结果如下: SIMPLIFIED CHINESE_CHINA.ZHS32GB18030

  ②查看有关字符集的所有参数

  SELECT  * FROM  v$nls_parameters;

  结果中的NLS_CHARACTERSET ZHS32GB18030

  2.2查看dmp文件的字符集

  用oracle的exp工具导出的dmp文件也包含了字符集信息,dmp文件的第2和第3个字节记录了dmp文件的字符集。如果dmp文件不大,比 如只有几M或几十M,可以用UltraEdit打开(16进制方式),看第2第3个字节的内容,如0354,然后用以下SQL查出它对应的字符集:

  SQL> select nls_charset_name(to_number('0354','xxxx')) from dual;ZHS16GBK

  2.3查询oracle client端的字符集

  在windows平台下,就是注册表里面相应OracleHome的NLS_LANG。具体路径:

  Win+R中输入regedit 路径\HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\ nls_lang 显示本地的字符集,这样就只影响这个窗口里面的环境变量。

  在unix平台下,就是环境变量NLS_LANG。

  $echo $NLS_LANG

  AMERICAN_AMERICA.ZHS16GBK

  以我行常用的PLSQL Developer为例,在不同oracle版本下的客户端环境变量配置地址不同:

  1.oracle10g注册表说在位置如下:

  ①在windows+R键中输入regedit

  ②\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\ORACLE\KEY_OraDb10g_home1

  ③修改NLS_LANG=“SIMPLIFIED Chinese_CHINA.ZHS16GBK”或

  NLS_LANG=“SIMPLIFIED CHINESE_CHINA.AL32UTF8”等(如图一)

  2.oracle12g注册表位置:HKEY_LOCAL_MACHINE/SOFTWARE/ORACLE/KEY_OraDB12Home1/NLS_LANG

  3.oracle11g注册表位置:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\

  4.也有注册表位置:

  在HKEY_LOCAL_MACHINE/SOFTWARE/ORACLE/Home0/NLS_LANG的其他oracle版本。

1-3.png

  如果检查的结果发现server端与client端字符集不一致,建议统一修改为同server端相同的字符集。

  五、常见的汉字乱码问题及解决方案(解决方案操作详见三)

  要在客户端正确显示ORACLE数据库中的汉字信息,首先必须使客户端的字符集与服务器端的字符集一致;其次是加载到ORACLE数据库的数据字符集必须与服务器字符集一致。据此,汉字显示乱码的问题大致可以分为以下几种情况:

  (1)客户端字符集与服务器端字符集不同,服务器端字符集与加载数据字符集一致。这种情况是最常见的,只要把客户端的字符集设置正确即可。具体解决方案:

  第一步:查询V$NLS_PARAMETERS得到服务端的字符集:SQL>SELECT * FROM V$NLS_PARAMETERS;

  PARAMETER                       VALUE
  NLS_LANGUAGE            SIMPLIFIED CHINESE
  NLS_TERRITORY                   CHINA             
  NLS_CHARACTERSET              ZHS16GBK

  第二步:根据服务端的字符集设定客户端的字符集,设定方法参见客户端的字符集的设定方式。以UNIX系统为例,可在当前用户的profile文件中增加如下两行:

  NLS_LANG=SIMPLIFIED Chinese_CHINA.ZHS16GBK    export NLS_LANG

  (2)客户端字符集与服务器端字符集相同,服务器端字符集与加载数据字符集不一致。这种情况一般发生在ORACLE版本升级或重新安装数据库时选择了与原来数据库不同的字符集,而恢复加载的备份数据仍是按原字符集卸出的场合。另一种情况是加载从其它使用不同字符集的ORACLE数据库卸出的数据。在这两种情况中,不管客户端字符集与服务器端字符集是否一致都无法正确显示汉字。具体解决方案:

  方案一:按服务端字符集的修改方法修改服务端字符集与加载数据字符集一致,然后导入数据。(见三中方法三)

  方案二:利用数据格式转储,避开字符集带来的问题。即先将加载数据倒入到与其字符集一致的数据库中,然后再将数据要么按文本格式导出(数据量较小的情况下),要么通过第三方工具(如POWER BUILDER,ACCESS,FOXPRO等)导出数据,最后将导出的数据导入到目标数据库中。

  (3)客户端字符集与服务器端字符集不同,服务端字符集与输入数据字符集不同。这种情况是在客户端字符集与服务器端字符集不一致时,从客户端输入了汉字信息。输入的这些信息即便是把客户端字符集更改正确,也无法显示汉字。解决方案:修改客户端字符集与服务端字符集一致后,重新输入数据。(此处较为复杂详情见百度文档)

  六、 总结

  由于ORACLE数据库创建后,数据库的字符集不能改变,因此需要提前考虑数据库将选用哪一种字符集,在我行中可以在ITA资源申请时关注相关情况。数据库字符集选择的一般规则是将数据库字符集设定为操作系统本地字符集的一个超集,同时数据库字符集也应该是所有客户字符集的超集。在中文环境中我们更多使用ZHS16GBK字符集,因为它包含了ZHS16CGB231280字符集,小伙伴们你们学会了么?


作者:林宫利    

来源:http://www.51testing.com/html/90/n-7801490.html

  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          • 使用 Git 进行版本管理时,肯定不只做提交,有时候也会需要回退修改,并且在回退的基础上进行重新提交,这时候有几个常用的命令就需要用到了,下面分别做介绍。 1、查看提交日志 首先,我们查看当前提交记录的命令:$ git log commit bfee9d6618bc1deae52ac4a7942b96990bbfe661 (HEAD -> master, origin/master, origin/HEAD) Author: sylan215 <sylan215@sylan215.com> Date: Thu Oct 19 15:19:30 2017 +0800 ...
            1 2 1803
            分享
          •   与来自中国的竞争对手相比,三星的可折叠手机要厚得多,这显然会对用户体验造成负面影响。荣耀 Magic V2合上时的厚度为 10.1 毫米,而Galaxy Z Fold5的厚度则高达 13.4 毫米。  不过,三星在这方面似乎终于有了突破,根据一项新的传言,即将推出的 Galaxy Z Fold6 将是三星有史以来最薄的可折叠手机,而且薄度大大改善,预计它合拢时的厚度正好为 11 毫米,虽然没有创下什么纪录,但对于这家韩国公司一贯迈小步的风格来说,绝对比以前好得多。  请注意,上图并没有展示 Fold6 的实物,它只是按比例将 Fold5 缩小到 11 毫米的近似值,何况目前这只是一个未经证...
            0 0 767
            分享
          • 手机App是当下互联网的主流模式之一,因此对于App相关测试需求也在逐年递增中,很多小伙伴没有从事过App相关的测试,有些注意点可能都不是很清楚,下面就我的App测试从业经验,分享给大家啦!目前工作中,测试App会涉及到一下几个方面:客户端、小程序、h5页面等,看似不同却又大相径庭。1、功能模块测试:功能模块测试其实最重要的是考察测试者的逻辑思维能力和对需求的理解能力以及一些页面交互性,输入输出的考虑等,所以以上三者是共通的,没有太大的区别。2、权限管理:1)相同点:需考虑权限允许的情况和权限不允许的情况;需要多测试无系统权限的页面2)不同点:App测试时需要考虑用户是否可以访问手机通讯、相册...
            3 0 2299
            分享
          •   二维码概述  二维码本身就是一个URL,只是通过QR码的形式把URL和用户身份信息转换成二进制的0和1,二维码中黑色的色素块代表1,白色的色素块代表0,我们通过相机扫码,就获取了二维码中的URL。  测试用例罗列(含扫码支付的相关内容)  1.界面测试:  · 界面的按钮和文字说明是否清晰、正确  · 界面的设计风格是否符合大众审美,对用户操作是否友好  2.功能测试:  · 扫描成功是否有提示  · 扫描失败是否有提示  · 只扫描一半时,是否扫描成功  · 打开扫描功能一段时间后没有扫描任何二维码,是否有提示用户或自动退出扫描功能  · 是否支持相册获取二维码,当扫描不是二维码时提示是...
            9 9 6413
            分享
          • 问题场景:执行完一个测试计划后,在察看结果树或者聚合报告里可以看到执行结果,但是如果关闭JMeter后再打开该测试计划后,却发现上次的执行结果就被清空了,那怎么办呢?解决办法:JMeter提供了生成HTML报告的功能,这样保存后我们就能看到之前的执行结果生成的报告了。当然,这个报告不仅仅能看到执行结果,还有很多的统计图表,清晰明了,非常有用。操作步骤:            1   创建一个csv格式或jtl格式的文件    ...
            0 0 4737
            分享
      • 51testing软件测试圈微信