Oracle里令人头疼的生僻字处理案例

2024-05-09 12:12

本文主要是介绍Oracle里令人头疼的生僻字处理案例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

事情起因

有小伙伴找到我问一下生僻字的问题,数据库是oracle 11g,字符集是zhs16gbk
 

image.png


下图里显示的??应该是“𧿹”这个字,算是个生僻字。
 

image.png


问应用厂家就说数据库字符集建错了,要改库的字符集。what???,这库都用了好几年了,现在改库字符集也不现实啊。
检查下字典点,看表里也是??显示

image.png

模拟测试

为了测试, 先创建个测试表,第1列是varchar2,第2列是nvarchar2
这里为了方便测试,使用scott用户

CREATE TABLE "SCOTT"."TEST_NAME" ( "BIANMA" NUMBER NOT NULL ENABLE, "VARCHAR2_NAME" VARCHAR2(200 BYTE), "NVARCHAR2_NAME" NVARCHAR2(200), CONSTRAINT "TEST_NAME_PK" PRIMARY KEY ("BIANMA") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE( INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "USERS" ENABLE ) SEGMENT CREATION DEFERRED PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE( INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "USERS" ;

创建如下图
 

image.png


这里提供几个把生僻字转换为Unicode的网址

http://unicode.wiicha.com/
https://www.bejson.com/convert/unicode_chinese/

查询一下这个字
 

image.png


\u是转换字符,用的时候去掉
查询一下

select utl_raw.cast_to_nvarchar2('d85fdff9') from dual;

image.png

在库里组合查询一下,看出来也可以显示

select utl_raw.cast_to_nvarchar2('d85fdff96307') from dual;

image.png


更新一下两个列里的内容

insert into  test_name  values (1,(select utl_raw.cast_to_nvarchar2('d85fdff96307') from dual),(select utl_raw.cast_to_nvarchar2('d85fdff96307') from dual));
commit;
select * from test_name

image.png

可以看出来,使用这种unicode转换的方式,只对nvchar2生效,varchar2还是显示乱码

关于varchar2和nvchar2

引用ASKTOM里的解答
NVARCHAR Vs. VARCHAR - Ask TOM (oracle.com)

Thanks for the question, Andrew.
Asked: September 04, 2015 - 3:00 pm UTC
Last updated: February 25, 2020 - 8:20 am UTC
Version: 12.0.2
Viewed 50K+ times! This question is 

img

You Asked
In a database with character sets defined as:
NLS_CHARACTERSET = AL32UTF8
NLS_NCHAR_CHARACTERSET = UTF8
Would there be any difference in the (language) character sets that could be stored by VARCHAR2 Vs. NVARCHAR2? As in
NAME VARCHAR2(60 CHAR)
Vs.
NAME NVARCHAR2(60 CHAR)
and Chris said…
NVARCHAR2 is a unicode-only data type. It’s useful if you want to have unicode for some columns (those that are NVARCHAR2) but have the rest of the database use a different characterset. In all other cases stick with using VARCHAR2.
In your case the only difference between UTF8 and AL32UTF8 is the AL version includes “supplementary characters”.
See also:
http://www.oracle.com/technetwork/database/database-technologies/globalization/twp-appdev-unicode-10gr2-129234.pdf
and
http://docs.oracle.com/database/121/NLSPG/ch6unicode.htm#NLSPG006

解决办法

根据以上测试的情况来看,有几个方案:
方案1、列由原来的varchar2改为nvarchar2,再插入unicode编码。
方案2、新建个utf8字符集的库,导出现有全库,再导入回去。
方案3、𧿹改写成别的可识别字符,如(足母)代替。
下面一个一个说一下几个方案:
方案1
需要停业务改表,结构,测试了一下,varchar2可以直接改成nvarchar2,但是nvarchar2改成varchar2要求必须没有数据。实际生产我也没测试过直接改列的字段类型,不知道会不会有问题。。
目前从网上收录2个操作方法
操作A
1、将表字段修改类型为:NVARCHAR2(),无论该字段是否存值都可以直接修改 alter table 表名 modify (字段名 nvarchar2(20));
注:如果想从NVARCHAR2()改回VARCHAR2,会报错:“ORA-01439:要更改数据类型,则要修改的列必须为空”,
解决方案为:①、将该字段A改名B;②、新建表字段,命名为A,将B值更新到A;③、删除B字段
2、使用该sql将生僻字插入到表中: update 表名 set 字段名 = N’生僻字’ where …
注意set字段名字前一定要有N,且在’'外。
操作B
也有人提供一个中转的解决办法:
修改字段类型,需要先将该字段清空,如果需要保存数据,可以先建一个临时的字段存储这些数据,然后删除要修改的列,再重新创建

--临时字段
alter table test_name add TEMP nvarchar2(200);
--赋转换后的值
update test_name set TEMP=cast(VARCHAR2_NAME as nvarchar2(200));
commit;
--删除字段
alter table test_name drop column VARCHAR2_NAME;
--重建
ALTER TABLE TEST_NAME ADD (VARCHAR2_NAME NVARCHAR2(200) );
--赋值
update test_name set VARCHAR2_NAME=TEMP;
--临时字段的使命完成了
alter table test_name drop column TEMP;
select * from test_name
insert into  test_name  values (2,(select utl_raw.cast_to_nvarchar2('d85fdff96307') from dual),(select utl_raw.cast_to_nvarchar2('d85fdff96307') from dual));

image.png


方法2:
基本不可行,一是停机时间太长,再就是改了字符集再重新导入的时候也可能会遇到字段长度不够的问题。
方法3:
就是真实案例,问了一下别家医院(几个不同厂家的HIS系统)是怎么解决这个问题的,结果。。。。就是写成(足母),别笑,真的好多家都这么搞的!!
 

image.png


另1家医院也是这样

image.png

总结后记

虽然这个能有办法解决。
但是还有一点我没想明白,人名生僻字他们咋解决的??难道人名的字段类型本来就是nvarchar2???
有知道的小伙伴可以告诉我一下,谢谢!

20240509

后来大佬们给的结果就是,在把varchar2改成nvarchar2,再重新录入。看来要整库都改生僻字是个大工程,1个1个改肯定是不好办。

image.png

 也欢迎关注我的公众号【徐sir的IT之路】,一起学习————————————————————————————
公众号:徐sir的IT之路
CSDN :https://blog.csdn.net/xxddxhyz?type=blog
墨天轮:https://www.modb.pro/u/3605
PGFANS:https://www.pgfans.cn/user/home?userId=5568————————————————————————————

这篇关于Oracle里令人头疼的生僻字处理案例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/973381

相关文章

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

PHP轻松处理千万行数据的方法详解

《PHP轻松处理千万行数据的方法详解》说到处理大数据集,PHP通常不是第一个想到的语言,但如果你曾经需要处理数百万行数据而不让服务器崩溃或内存耗尽,你就会知道PHP用对了工具有多强大,下面小编就... 目录问题的本质php 中的数据流处理:为什么必不可少生成器:内存高效的迭代方式流量控制:避免系统过载一次性

MyBatis分页查询实战案例完整流程

《MyBatis分页查询实战案例完整流程》MyBatis是一个强大的Java持久层框架,支持自定义SQL和高级映射,本案例以员工工资信息管理为例,详细讲解如何在IDEA中使用MyBatis结合Page... 目录1. MyBATis框架简介2. 分页查询原理与应用场景2.1 分页查询的基本原理2.1.1 分

oracle 11g导入\导出(expdp impdp)之导入过程

《oracle11g导入导出(expdpimpdp)之导入过程》导出需使用SEC.DMP格式,无分号;建立expdir目录(E:/exp)并确保存在;导入在cmd下执行,需sys用户权限;若需修... 目录准备文件导入(impdp)1、建立directory2、导入语句 3、更改密码总结上一个环节,我们讲了

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

Python中 try / except / else / finally 异常处理方法详解

《Python中try/except/else/finally异常处理方法详解》:本文主要介绍Python中try/except/else/finally异常处理方法的相关资料,涵... 目录1. 基本结构2. 各部分的作用tryexceptelsefinally3. 执行流程总结4. 常见用法(1)多个e

PHP应用中处理限流和API节流的最佳实践

《PHP应用中处理限流和API节流的最佳实践》限流和API节流对于确保Web应用程序的可靠性、安全性和可扩展性至关重要,本文将详细介绍PHP应用中处理限流和API节流的最佳实践,下面就来和小编一起学习... 目录限流的重要性在 php 中实施限流的最佳实践使用集中式存储进行状态管理(如 Redis)采用滑动

MyBatis-plus处理存储json数据过程

《MyBatis-plus处理存储json数据过程》文章介绍MyBatis-Plus3.4.21处理对象与集合的差异:对象可用内置Handler配合autoResultMap,集合需自定义处理器继承F... 目录1、如果是对象2、如果需要转换的是List集合总结对象和集合分两种情况处理,目前我用的MP的版本

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

Python自动化处理PDF文档的操作完整指南

《Python自动化处理PDF文档的操作完整指南》在办公自动化中,PDF文档处理是一项常见需求,本文将介绍如何使用Python实现PDF文档的自动化处理,感兴趣的小伙伴可以跟随小编一起学习一下... 目录使用pymupdf读写PDF文件基本概念安装pymupdf提取文本内容提取图像添加水印使用pdfplum