pl/sql developer oracle生僻字显示问题

news2024/11/19 10:53:03

一、问题由来
       随着国标GB18030的推行,各行各业都在如火如荼的落实改造。自己在工作中也发现很多问题,查阅了很多资料都未解决自己的问题。经过慢慢摸索,对生僻字经常出现的问题进行总结,现分享如下。

二、问题描述

1. oracle存储不了生僻字。

2. 在PL/SQL Developer 中输入生僻字时,该生僻字无法正常显示。

3. pl/sql能录入能显示,通过jdbc不能显示。

4. jdbc能录入能显示,通过pl/sql不能显示。

三、原因

1.对于数据库而言,不区分什么生僻字,它仅仅是存储一堆的字节而已。能否存储生僻字主要是看以下几个方面:

a.数据库自身设置的字符集(该字符集会影响jdbc或odbc驱动与服务器的传输编码,不像mysql那样可以指定传输编码。这个没有找到相关资料辅佐,有兴趣可以抓包验证),这里面有两个关键的参数,一个是针对varchar2,一个是针对nvarchar2,这两个的区别可自行百度,资料比较多。

如图所示,我自己的数据库varchar2类型我设置的是AL32UTF8(all language 32位即4个字节 utf-8编码)。nvarchar2我也是用的utf-8。utf8和gbk的区别这儿也不做描述,百度资料很多。这儿可以看到我的数据库是大字符集的,能存储生僻字。

b.客户端的字符集,这个可通过环境变量或注册表等修改(环境变量名为NLS_LANG,不会修改可自行百度)。

如图,我的客户端也是使用utf-8编码。网上的很多oracle显示中文乱码的问题差不多就到这儿了,确定了这两步差不多就可以解决中文乱码问题了。但是现在要说的是生僻字,为啥一会儿能显示一会儿又不能显示让人很迷惑,下面一一讲解。

2.数据库能存储生僻字后,想着插入一个生僻字来做测试,但是pl/sql却不能显示该生僻字,这个原因首先取决于你有没有安装能显示相关生僻字的字库(目前市面的大多字库都不能显示生僻字),其次是pl/sql工具要选择生僻字的字库,这样在pl/sql的编辑界面和结果界面才能显示生僻字。

3.设计了一张varchar2字段的表,pl/sql能插入和显示生僻字,但是程序(jdbc或odbc)读取不到该字。该字“𫍣”为生僻字,没相关字库是显示不出来的。

 如图上,该字通过pl/sql能插入,也能显示,以为没有没有问题了,但是发现用程序读取时,却是无法解析,若是应用程序的话那就乱码了,例如我通过jdbc读取如下:

当看到-17,-65,-67这几个字符时, 条件反射想到这是转码有问题。在unicode编码里面,有几个特殊的码点可以记一下,对查问题时很有用。

其中字符�,码点为FFFD,utf-8编码为 EF,BF,BD,即-17,-65,-67。该特殊码点表示替换字符,当你给定一段字节信息,用UTF-8解码时,如果解码失败,就会把该字转换为�。那为啥会存在解码失败,原因就是你的字节信息不是UTF-8的编码,但你却用UTF-8解码,那当然就会失败。最常见的就是你的字节流是GBK的,但解码时用UTF-8,这样就会存在字符替换。如下图:

 顺便一提,还有一个常见的字符显示错误还有一个:锟斤拷。这个又是怎么来的?同上面的道理,GBK转到UTF-8失败后,得到的是字符�,当有用该字符的字节信息通过GBK解码时,因为一个汉字只用两个字节,该字解出来就是我们看到的锟斤拷,如下图:

自此大家看到 �或者锟斤拷的时候,就知道是编码不一致问题,不用再好奇星号怎么来的。

回到主题,为啥jdbc读到的是-17,-65,-67,是存储了错误的字节?还是传输时转码了字节流信息?所幸oracle提供了一个函数可以查看数据库存储的究竟是什么字节——dump函数,函数具体怎么使用还是自行百度,下面看一下数据库里面存储的究竟是啥。

 存储了6个字节,而我们数据库设置的字符集为utf8,这个生僻字utf8编码却是F0,AB,8D,A3这4个字节,显然差异不是一点半点。那数据库中存储的这个字节到底怎么来的?我们知道不管jdbc还是pl/sql等其他工具,最终和服务器通信就是网络包,而包里的内容若没加密就是一个个字节流(即使加密也是一个个字节,只是读不出来)而已,既然这样,直接抓包看看就知道了。抓包结果如下图:

        还好oracle的网络通讯没有加密,很容易就找到发送的包信息,从上图可以很清晰的看出oracle存储的字符集是由客户端获取的,而至于pl/sql客户端获取该字的utf8码为什么是一个6字节,这个就不清楚了,有知道原因的同学可以告知一下。猜测这个是系统开发环境有关(可以这么理解,如果你的工具支持unicode,那编码解码就是我们理解utf的规则,例如自己写的工具JOV,用的VS2013开发的,平台支持unicode,生僻字字符是用是4个字节表示,其实就是utf-16。而pl/sql,xshell等工具应该是不支持unicode,遇到生僻字这种会进行转码表示,不知道具体是什么规则,但肯定有东西在里面的,不然也不会获取到6个字节,正常的汉字获取的utf8编码大家都是一样的),从码值上看正常的utf8是F0,AB,8D,A3,pl/sql获取到的是ed,a1,ac,ed,bd,a3,可以看到最后一个字节始终是相同的,他们之间的转换规则有知道的可以告知一下。

       到此可以理解为什么pl/sql能插入和显示生僻字,而其他jdbc获取到的却是乱码的问题了,根本原因是你用的工具能否支持unicode,虽然你的数据库字符集已经设置是utf8了,但真正存储的是你工具传给oracle的utf8的字节信息,你传入的是非主流的utf8(如上存入的ed,a1,ac,ed,bd,a3),别人肯定就读不出来(别人只认识F0,AB,8D,A3)。

       同理,回答第四个问题,原因也是一样的,用你的程序(以java为例,java肯定支持unicode的,你获取utf8很容易getBytes("utf-8")就可以获得,该值获得的就是正常的字节信息)插入该生僻字后,数据库中存储的就是F0,AB,8D,A3,而pl/sql读取生僻字它有他的规则,它认识的是6个字节的那个,4个字节的它就不认识了,如下图:

       可以看到自己的程序插入和显示都正常,但是pl/sql工具却把它当两个汉字来处理了,很好理解嘛,因为oracle存储了4个字节(一般情况下gbk一个普通汉字占2个字节,一个普通汉字utf8占3个字节),两个汉字它就当gbk码处理了, 下图也可以验证。

      至此oracle生僻字不能显示或不能存储的问题差不多描述清楚了,也解释了为什么,还有不明白的就多读几遍吧。文章中使用的工具:pl/sql developer, wireshark, eclipse, jov。jov工具已开源,有兴趣的可以去之前的文章找,最新版也可以去下载。https://download.csdn.net/download/jerome_jun/87815045

      还有一个问题,有人想我既想在pl/sql工具里面插入查看,又想应用程序能正确读取,那有办法吗?答案当然是肯定的,既然都知道了不能读取的原因,oracle如何存储信息,那当然可以解决。思路有两种:一是不改变现在的数据库字符集信息,自己写一个小工具提供插入和显示,需要支持更改字库,支持unicode编码,项目也不难,有兴趣的可以去写一个,没编程能力的当我白说。第二种方式是还记得上面提到的NVARCHAR2吗,这个设计本身就是针对这种字符集的情况,申请到的字符长度是多少就是多少,它也是可以设置字符集的,那究竟设置成啥呢?AL16UTF16了解一下,老规矩自行百度这个编码规则是啥。其实很多应用他们支持unicode码时,具体的表现形式用的就是UTF-16,像之前提到的VS2013和java,它的中文unicode码都是用utf-16存储的,优点缺点大家也可以自行去百度。回到主题,当你的NVARCHAR2设置为AL16UTF16后,你会发现ps/sql工具获取的utf-16编码和其他工具都一样了,大家存储的字节信息都一致了,这样大家就能正常访问了。那你可能会问varchar2直接设置成AL16UTF16好了嘛,不同工具不是都可以插入、修改、查询了嘛,很会举一反三,要是地主家儿子你是可以这么干的,这个问题嘛可以看看chatGPT怎么回答的:

     

整个排查问题分享得差不多了,有不恰当之处欢迎指导。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/653556.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

超声功率放大器的工作原理和特点是什么

超声功率放大器是一种利用超声波振动产生机械振动的装置,通过将输入信号放大后输出到负载中,以实现对超声能量的有效利用。其工作原理和特点如下: 超声功率放大器的工作原理 超声功率放大器的工作原理是基于压电效应和磁致伸缩效应。当输入电…

2023亚马逊科技中国峰会之Amazon DeepRacer赛车比赛

目录 一、前言 二、什么是 Amazon DeepRacer 三、如何构建自己的第一个强化学习模型 1、创建 Amazon DeepRacer 资源 2、自定义你的赛道 3、开始你的模型 4、关于优化模型 5、在仿真器中测试 6、在真实赛道上测试你的模型 四、中国峰会总决赛 五、自动驾驶赛车名校邀…

使用PlotNeuralNet绘制深度学习网络图的基本操作(二)

使用PlotNeuralNet绘制深度学习网络图的基本操作(二) 接下来我们利用pycharm来绘制当中我们的神经网络模型架构,目标是直接将.tex文件生成为pdf和png。我在学习的过程中参考了一些学习视频,觉得这个up主讲的还不错: 1…

CH583,CH582,CH581 国产蓝牙芯片RISC-V内核BLE 5.3无线MCU

概述 CH583是集成BLE无线通讯的32位RISC微控制器。片上集成2Mbps低功耗蓝牙BLE 通讯模块、2个全速USB主机和设备控制器及收发器、2个SPI、4个串口、ADC、触摸按键检测模块、RTC等丰富的外设资源。 CH583相比CH582多了SP11主机,支持最低1. 7V电源电压。CH581 基于CH…

Java实现动态生成word报告

Java实现动态生成word报告 1.准备好docx文件模板 举例&#xff1a;动态生成表格数据&#xff0c;以下是list数组类型的freemarker语法 将写好的word模板加入到templates目录下 2.在pom.xml中导入相关依赖 <dependency><groupId>fr.opensagres.xdocreport</g…

react antd checkbox实现全选,多选

背景 目前好像只有table组件有实现表格数据的全选功能&#xff0c;如果说对于list&#xff0c;card&#xff0c;collapse等其他组件来说&#xff0c;需要自己结合checkbox来手动实现全选功能。 Checkbox.Group有实现全选功能&#xff0c;但是对于需要遍历出来的数据&#xff…

人民大学与加拿大女王大学金融硕士——原来“鱼和熊掌”可以兼得

“鱼和熊掌”不可兼得&#xff0c;我们从小就听到过这句话。随着长大&#xff0c;随着能力增强&#xff0c;两者我们都想要。就像在中国人民大学与加拿大女王大学金融硕士项目读研&#xff0c;我们不只要获得毕业证书&#xff0c;我们还要学到真本领。你的愿望在人大女王金融硕…

Ubuntu18.04离线安装Nginx

因需要安装nginx的服务器无法连接互联网&#xff0c;所以需要离线安装。首先需要下载nginx的安装包&#xff0c;之后进行安装&#xff0c;在安装之前需要保证gcc&#xff0c;g&#xff0c;make等依赖包已经安装。 因为是需要离线安装&#xff0c;所以在之前是用的一台互联网下载…

Java选择题刷题记录1

LinkedList类继承自AbstractSequentialList ArrayList listnew ArrayList(); 这种是默认创建大小为10的数组&#xff0c;每次扩容大小为1.5倍&#xff1b;ArrayList listnew ArrayList(20);这种是指定数组大小的创建&#xff0c;创建时直接分配其大小&#xff0c;扩充0次 Ite…

naive-ui NPopconfirm怎么用vue3的h()渲染

先看效果 然后我先贴代码&#xff0c; 你们看懂的先运行下&#xff0c; 文章后面我教你怎么 添加这种有template&#xff0c;有slot插槽的组件 h(NPopconfirm,{positiveButtonProps: {size: tiny,color: #007293,bordered: true,},negativeButtonProps: {size: tiny,color: #…

解决添加上@RequiresPermissions权限注解后无法访问接口,swagger读取不到的问题

目录 一、先搭建 Swagger 1、添加依赖库 2、创建Swagger配置类 3、配置yml 4、编写测试Web接口 5、测试Web接口 二、解决问题 1、出现的问题 2、解决问题 一、先搭建 Swagger 开发前后端分离架构的项目&#xff0c;往往调试后端Web接口需要用到POSTMAN工具。虽然POSTM…

智安网络|人工智能蔓延,网络安全所面临的威胁和应对之道

随着人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;技术的快速发展和广泛应用&#xff0c;我们进入了一个智能时代&#xff0c;人工智能已经蔓延到我们生活的方方面面。然而&#xff0c;与其带来的方便和创新相伴随的是网络安全所面临的新威胁。 【威…

记录一下RocketMQ中遇见的 连环大坑!!!差点没把我摔死

目录 环境&#xff1a;Win10 &#xff0c; 不是 linux 首先我遇见的第一个问题是&#xff1a; No route info of this topic 问题原因&#xff1a; PS&#xff1a; 64位系统环境下&#xff0c;如果软件在安装时安装路径默认c:\progarmfiles即为64位&#xff0c;默认c:\pr…

Sharding-JDBC之PreciseShardingAlgorithm(精确分片算法)

目录 一、简介二、maven依赖三、数据库3.1、创建数据库3.2、创建表 四、配置&#xff08;二选一&#xff09;4.1、properties配置4.2、yml配置 五、精确分片算法5.1、精确分库算法5.2、精确分表算法 六、实现6.1、实体层6.2、持久层6.3、服务层6.4、测试类6.4.1、保存订单数据6…

ai画图怎么弄?简单几步教会你如何用ai绘画

艺术创作一直是人类文明发展的重要组成部分&#xff0c;在当今数字化时代&#xff0c;ai技术的不断进步也为我们带来了全新的创作方式。在这其中&#xff0c;ai绘画软件因其独特的创作方式和优秀的绘画效果受到了广泛关注和喜爱。使用ai绘画软件可以让我们轻松地创作出各种风格…

关于数据仓库那点事,一文捋清

借助海量的数据&#xff0c;企业进行了深层次的数字化改革&#xff0c;把数据当成了企业发展的核心&#xff0c;但无效的数据即使规模再大&#xff0c;也对企业没有意义&#xff0c;所以数据质量也就愈发重要。 数据仓库 事实上&#xff0c;很多人在看到数据仓库的第一眼&…

【夜深人静学数据结构与算法 | 第四篇】手撕二叉树遍历

目录 前言&#xff1a; 二叉树遍历方式&#xff1a; 手撕前中后序遍历&#xff08;递归&#xff09;的三大准备 深度优先搜索&#xff1a; 手撕前中后遍历&#xff08;递归&#xff09;&#xff1a; 手撕前中后序遍历&#xff08;迭代&#xff09;&#xff1a; 深度优先…

经典Java面试题收集

1、面向对象的特征有哪些方面&#xff1f; 答&#xff1a;面向对象的特征主要有以下几个方面&#xff1a; 抽象&#xff1a;抽象是将一类对象的共同特征总结出来构造类的过程&#xff0c;包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为&#xff0c;并不关注这…

EHCI接口概述(三)

EHCI主机接口寄存器在BAR0所示的PCI MEM地址空间中&#xff0c;主要包括两部分&#xff1a; 1&#xff09;能力寄存器组 2&#xff09;操作寄存器组 下面先介绍能力寄存器组 CAPLENGTH寄存器&#xff0c;8位只读寄存器&#xff0c;给出了控制寄存器组的偏移量。 HCIVERSION…