热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

Oracle数据库字符集问题解析(2)

欢迎进入Oracle社区论坛,与200万技术人员互动交流进入实验结果分析二quote:--------------------------------------------------------------------------------[更改客户端字符集为ZHS16GBKD:SETNLS_

欢迎进入Oracle社区论坛,与200万技术人员互动交流 >>进入 实验结果分析二 quote: -------------------------------------------------------------------------------- [ 更改客户端字符集为ZHS16GBK D:SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK D:SQLPLUS "

欢迎进入Oracle社区论坛,与200万技术人员互动交流 >>进入

实验结果分析二


quote:
--------------------------------------------------------------------------------
[ 更改客户端字符集为ZHS16GBK
D:>SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK

D:>SQLPLUS "/ AS SYSDBA"

无法正常显示数据

SQL> SELECT * FROM TEST;

R1
--------------------
6+11

疑问1:ZHS16GBK为US7ASCII的超集,为什么在ZHS16GBK环境下无法正常显示


--------------------------------------------------------------------------------

这主要是因为Oracle检查发现数据库设置的字符集与客户端配置字符集不同,它将对数据进行字符集的转换。数据库中实际存放的数据为182(10110110)、171(10101011)、177(10110001)、177(10110001),由于数据库字符集设置为US7ASCII,它是一个7bit的字符集,存储在8bit的字节中,则Oracle忽略各字节的最高bit,则182(10110110)就变成了54(0110110),在ZHS16GBK中代表数字符号“6”(当然在其它字符集中也是“6”),同样过程也发生在其它3个字节,这样“东北”就变成了“6+11”。

实验结果分析三


quote:
--------------------------------------------------------------------------------
最初由 tellin 发布
用ZHS16GBK插入数据
SQL> INSERT INTO TEST VALUES('东北');

1 row created.

SQL> SELECT * FROM TEST;

R1
--------------------
6+11
??

SQL> EXIT

--------------------------------------------------------------------------------


当客户端字符集设置为ZHS16GBK后向数据库插入“东北”,Oracle检查发现数据库设置的字符集为US7ASCII与客户端不一致,需要进行转换,但字符集ZHS16GBK中的“东北”两字在US7ASCII中没有对应的字符,所以Oracle用统一的“替换字符”插入数据库,在这里为“?”,编码为63(00111111),这时,输入的信息实际上已经丢失,不管字符集设置如何改变(如下面引用的实验结果),第二行SELECT出来的结果也都是两个“?”号(注意是2个,而不是4个)。


quote:
--------------------------------------------------------------------------------

更改客户端字符集为US7ASCII
D:>SET NLS_LANG=AMERICAN_AMERICA.US7ASCII

D:>SQLPLUS "/ AS SYSDBA"

无法显示用ZHS16GBK插入的字符集,但可以显示用US7ASCII插入的字符集
SQL> SELECT * FROM TEST;

R1
----------
东北
??


更改服务器字符集为ZHS16GBK
SQL> update props$ set value$='ZHS16GBK' WHERE NAME='NLS_CHARACTERSET';

1 row updated.

SQL> COMMIT;

更改客户端字符集为ZHS16GBK
D:>SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK

D:>SQLPLUS "/ AS SYSDBA"

可以显示以前US7ASCII的字符集,但无法显示用ZHS16GBK插入的数据,说明用ZHS16GBK插入的数据为乱码。

SQL> SELECT * FROM TEST;

R1
--------------------
东北
??

--------------------------------------------------------------------------------


需要指出的是,通过“update props$ set value$='ZHS16GBK' WHERE NAME='NLS_CHARACTERSET';”来修改数据库字符集是非常规作法,很可能引起问题,在这里只是原文引用网友的实验结果。

实验结果分析四


quote:
--------------------------------------------------------------------------------

SQL> INSERT INTO TEST VALUES('东北');

1 row created.

SQL> SELECT * FROM TEST;

R1
--------------------
东北
??
东北

SQL> EXIT

--------------------------------------------------------------------------------


由于此时数据库与客户端的字符集设置均为ZHS16GBK,所以不会发生字符集的转换,第一行与第三行数据显示正确,而第二行由于存储的数据就是63(00111111),所以显示的是“?”号。


quote:
--------------------------------------------------------------------------------

更改客户端字符集为US7ASCII

D:>SET NLS_LANG=AMERICAN_AMERICA.US7ASCII

D:>SQLPLUS "/ AS SYSDBA"

无法显示数据

SQL> SELECT * FROM TEST;

R1
----------
??
??
??

疑问2:第一行数据是用US7ASCII环境插入的,为何无法正常显示?

--------------------------------------------------------------------------------


将客户端字符集设置改为US7ASCII后进行SELECT,Oracle检查发现数据库设置的字符集为ZHS16GBK,数据需要进行字符集转换,而第一行与第三行的汉字“东”与“北”在客户端字符集US7ASCII中没有对应字符,所以转换为“替换字符”(“?”),而第二行数据在数据库中存的本来就是两个“?”号,所以虽然在客户端显示的三行都是两个“?”号,但在数据库中存储的内容却是不同的。

实验结果分析五


quote:
--------------------------------------------------------------------------------


SQL> INSERT INTO TEST VALUES('东北');

1 row created.

SQL> EXIT
更改客户端字符集为ZHS16GBK
D:>SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK

D:>SQLPLUS "/ AS SYSDBA"

无法显示用US7ASCII插入的字符集,但可以显示用ZHS16GBK插入的字符集
SQL> SELECT * FROM TEST;

R1
--------------------
东北
??
东北
6+11

SQL>
疑问3:US7ASCII为ZHS16GBK的子集,为何在US7ASCII环境下插入的数据无法显示? [/B]
--------------------------------------------------------------------------------


在客户端字符集设置为US7ASCII时,向字符集为ZHS16GBK的数据库中插入“东北”,需要进行字符转换,“东北”的ZHS16GBK编码为182(10110110)、171(10101011)与177(10110001)、177(10110001),由于US7ASCII为7bit编码,Oracle将这两个汉字当作四个字符,并忽略各字节的最高位,从而存入数据库的编码就变成了54(00110110)、43(00101011)与49(00110001)、49(00110001),也就是“6+11”,原始信息被改变了。这时,将客户端字符集设置为ZHS16GBK再进行SELECT,数据库中的信息不需要改变传到客户端,第一、三行由于存入的信息没有改变能显示“东北”,而第二、四行由于插入数据时信息改变,所以不能显示原有信息了。

分析了这么多的内容,但实际上总结起来也很简单,要想在字符集方面少些错误与麻烦,需要坚持两条基本原则:
在数据库端:选择需要的字符集(通过create database中的CHARACTER SET与NATIONAL CHARACTER SET子句指定);
在客户端:设置操作系统实际使用的字符集(通过环境变量NLS_LANG设置)。


例如:
CHARACTER SET ZHS16GBK
NATIONAL CHARACTER SET AL16UTF16


推荐阅读
  • MySQL缓存机制深度解析
    本文详细探讨了MySQL的缓存机制,包括主从复制、读写分离以及缓存同步策略等内容。通过理解这些概念和技术,读者可以更好地优化数据库性能。 ... [详细]
  • MySQL 数据库迁移指南:从本地到远程及磁盘间迁移
    本文详细介绍了如何在不同场景下进行 MySQL 数据库的迁移,包括从一个硬盘迁移到另一个硬盘、从一台计算机迁移到另一台计算机,以及解决迁移过程中可能遇到的问题。 ... [详细]
  • 本文介绍了如何使用PHP代码实现微信平台的媒体素材上传功能,详细解释了API接口的使用方法和注意事项,确保文件路径正确以避免常见的错误。 ... [详细]
  • 本文详细介绍了 MySQL 的查询处理流程,包括从客户端连接到服务器、查询缓存检查、语句解析、查询优化及执行等步骤。同时,深入探讨了 MySQL 中的乐观锁机制及其在并发控制中的应用。 ... [详细]
  • 在现代网络环境中,两台计算机之间的文件传输需求日益增长。传统的FTP和SSH方式虽然有效,但其配置复杂、步骤繁琐,难以满足快速且安全的传输需求。本文将介绍一种基于Go语言开发的新一代文件传输工具——Croc,它不仅简化了操作流程,还提供了强大的加密和跨平台支持。 ... [详细]
  • SQLite 动态创建多个表的需求在网络上有不少讨论,但很少有详细的解决方案。本文将介绍如何在 Qt 环境中使用 QString 类轻松实现 SQLite 表的动态创建,并提供详细的步骤和示例代码。 ... [详细]
  • 近期遇到电脑网络不稳定和游戏时频繁重启的问题,寻求专业建议。网络环境为ADSL调制解调器通过路由器共享给两台电脑使用,怀疑存在ARP攻击或硬件配置问题。希望获得详细的故障排查和解决方案。 ... [详细]
  • 网络运维工程师负责确保企业IT基础设施的稳定运行,保障业务连续性和数据安全。他们需要具备多种技能,包括搭建和维护网络环境、监控系统性能、处理突发事件等。本文将探讨网络运维工程师的职业前景及其平均薪酬水平。 ... [详细]
  • 使用Python在SAE上开发新浪微博应用的初步探索
    最近重新审视了新浪云平台(SAE)提供的服务,发现其已支持Python开发。本文将详细介绍如何利用Django框架构建一个简单的新浪微博应用,并分享开发过程中的关键步骤。 ... [详细]
  • 从零开始构建完整手机站:Vue CLI 3 实战指南(第一部分)
    本系列教程将引导您使用 Vue CLI 3 构建一个功能齐全的移动应用。我们将深入探讨项目中涉及的每一个知识点,并确保这些内容与实际工作中的需求紧密结合。 ... [详细]
  • PHP 5.5.0rc1 发布:深入解析 Zend OPcache
    2013年5月9日,PHP官方发布了PHP 5.5.0rc1和PHP 5.4.15正式版,这两个版本均支持64位环境。本文将详细介绍Zend OPcache的功能及其在Windows环境下的配置与测试。 ... [详细]
  • 百度服务再次遭遇技术问题,疑似DNS解析故障
    近日晚间,百度多项在线服务出现加载异常,包括移动端搜索在内的多个功能受到影响。初步迹象表明,问题可能与DNS服务器解析有关。 ... [详细]
  • 本文详细介绍了《问道》手游在2020年12月31日进行的服务器维护情况,以及此次更新中新增的跨年狂欢活动和寒假活动等内容。同时,文章还涵盖了其他重要的系统优化与修复信息。 ... [详细]
  • 本文介绍如何在Linux服务器之间使用SCP命令进行文件传输。SCP(Secure Copy Protocol)是一种基于SSH的安全文件传输协议,支持从远程机器复制文件到本地服务器或反之。示例包括从192.168.45.147复制tomcat目录到本地/home路径。 ... [详细]
  • 通过与阿里云的合作,牛客网成功解决了跨国视频面试中的网络卡顿问题,为求职者和面试官提供了更加流畅的沟通体验。 ... [详细]
author-avatar
不想不知痛_378
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有