首先,我们先来安利一下何谓生僻字?想必大家都听过陈柯宇的《生僻字》这首歌,摘取其部分生僻字歌词如下:
qióng qióng jié lì hàng xiè yī qì
茕 茕 孑 立沆 瀣 一 气
jǔ jǔ dú xíng tí hú guàn dǐng
踽 踽 独 行 醍 醐 灌 顶
mián mián guā dié fèng wéi guī niè
绵 绵 瓜 瓞 奉 为 圭 臬
lóng xíng dá dá jī jiǎo gā lá
龙 行 龘 龘 犄 角 旮 旯
生僻字又称冷僻字,指不常见的或人们不熟悉的汉字。
接下来,我们再来安利下字符和字符集。字符(Character)是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字,就需要进行字符编码,以便计算机能够识别和存储各种文字。中文文字数目大,而且还分为简体中文和繁体中文两种不同书写规则的文字,而计算机最初是按英语单字节字符设计的,因此,对中文字符进行编码,是中文信息交流的技术基础。看到这,就该回到文章的正题了,为什么Oracle 数据库存储生僻字会出现乱码?Oracle 数据库用的是什么字符编码?
查看当前使用的字符集
select userenv('language') from dual;

图1 Oracle使用的字符集
或者查询以下SQL命令:
select * from v$nls_parameters where parameter='NLS_CHARACTERSET';
ZHS16GBK字符集是不包含生僻字编码的,因而在ZHS16GBK字符集下存储生僻字自然就会出现乱码。
解决方案
暂时提出以下两种解决方案:
修改数据库字符集为“AL32UTF8”。
不修改数据库字符集的前提下,从开发的角度实现间接读写存储数据库的生僻字。
方案分析
如果采取将数据库的字符集修改为“AL32UTF8”,那么必须要解决的一个问题是数据库字段长度如何进行自动扩容。为什么要解决这个问题,是因为汉字在这两种字符集下的长度是不一致的,一个汉字在ZHS16GBK字符集下是占用两个字节,但是在AL32UTF8字符集下占用三个字节,因而在修改字符集之前,必须要考虑这个问题。
如果采取间接读写存储数据库的生僻字,那么必须整理代码改动涉及的内容以及制定出高效的修改方案。间接读写存储数据库生僻字的方法实现也简单,简单介绍下PL_SQL的实现过程,将生僻字转换为Unicode,如"㛃" 转为Unicode为 "\u36c3"(注意:\u 是Unicode的转义字符,使用的时候要去掉),读的时候采用以下SQL转换:
select utl_raw.cast_to_nvarchar2('36c3') from dual;
待完善:开发的代码实现。
参考文献
百度百科




