第3章  Oracle的字符集(3.9-3.11)

Oracle全球支持(即Globalization Support)允许我们使用本地语言和格式来存储和检索数据。通过全球支持,Oracle可以支持多种语言及字符集,得以展示数据库的强大魅力。这篇介绍《循序渐进Oracle》第三章的3.9-3.11节,自定义字符集的使用、更改字符集的内部方式及字符集更改的案例。

由于不同语言及字符集的共同存储存在设置上具有一定的复杂性,字符集一度成为普遍困扰大家的一个主要问题。

本章就字符集一些常见问题进行讨论,并对字符集转化等本质内容进行探索。

3.9  自定义字符的使用

很多时候,需要存储的字符可能在数据库的字符集中并不存在,这时候我们就可以通过客户端的“TrueType 造字程序”来对空闲代码点进行自定义字符的创建。

在Windows上,单击开始->运行-> eudcedit 可以启动造字程序,下面我们用造字程序在字符集ChineseGBK下使用代码点AAA1创造一个新字进行测试:

图3-15  使用造字程序自造字

造字完成以后,保存该字符,在客户端字符集我们就完成了这个新字符的定义,接下来在菜单 编辑->输入法链接 将该字符链接到当前输入法中,以便可以通过输入法输入这个字。

下面我们可以将这个字存入数据库:

图3-16  将自造字存入数据库

那么接下来的查询这个字可以被正确显示:

图3-17  自造字及代码点

我们注意,这个字的编码为170 161,转换为16进制后正是:AAA1。

也就是说服务器端只管存入了客户端发过去的编码,至于这个编码代表了什么字符数据库服务器并不管,当反向查询时,Oracle数据库将编码再返回给客户端,客户端依据编码来对应客户端的字符展现,如果客户端存在对应,那么就可以正常显示我们创建的字符,如果不存在,或者客户端定义了不同的编码,那么显示的就将是不同的字符,这和不同字符集的相互转换的原理是相同的,对于本例,我们在另外一个客户端对AAA1定义了不同的字符,则查询的结果显示为:

图3-18  自造字在不同客户端可能的不同映射

这也就是为什么我们前面说,当进行字符集转换时需要通过csscan进行扫描,其中的一个原因就是因为同一个代码点在不同的字符集下可能代表不同的字符。

总结一下,字符集的实现实际上依赖于数据库端及客户端的字符集文件,只有服务器端字符集文件存在代码点到字符的映射,数据库服务器才知道存储的代码到底代表什么字符;而同样客户端也必须存在相应的代码点到字符的映射关系,这样数据库服务器上的字符传递到客户端之后才能被正确的解码成相应的字符。这就类似调制解调的过程,在传输过程中,自始至终传递的都是字符编码。

只有遵循通用的编码规范,我们的数据才能够通用的被不同的客户端、平台所共享和识别,如果是自定义的字符,那么在不存在定义关系的客户端就无法被识别或者不能被正确识别。

3.10  更改字符集的内部方式

前面我们曾经提到,通过修改props$的方式更改字符集在Oracle 7之后是一种极其危险的方式,应该尽量避免。我们又知道,通过ALTER DATABASE CHARACTER SET更改字符集虽然安全可靠,但是有严格的子集和超集的约束,实际上很少能够用到这种方法。

除了前面提到的几种方法外,Oracle还存在另外一种更改字符集的方式:通过隐含的内部命令强制修改字符集。

当使用模板的种子数据库创建数据库时,在创建脚本中可以看到这样的一系列命令:alter system enable restricted session;

alter database "eygle" open resetlogs;

alter database rename global_name to "eygle";

ALTER TABLESPACE TEMP ADD TEMPFILE 'C:\oracle\oradata\eygle\TEMP01.DBF' SIZE 20480K REUSE AUTOEXTEND ON NEXT 640K MAXSIZE UNLIMITED;

select tablespace_name from dba_tablespaces where tablespace_name='USERS';

select sid, program, serial#, username from v$session;

alter database character set INTERNAL_CONVERT ZHS16GBK;

alter database national character set INTERNAL_CONVERT AL16UTF16;

alter user sys identified by "&&sysPassword";

alter user system identified by "&&systemPassword";

alter system disable restricted session;

在这里面,可以看到这样两条重要的、Oracle非公开的命令:alter database character set INTERNAL_CONVERT ZHS16GBK;

alter database national character set INTERNAL_CONVERT AL16UTF16;

这个命令是当选择了使用模板方式创建了种子数据库以后,Oracle会根据选择的字符集设置,把当前种子数据库的字符集更改为期望字符集,这就是这条命令的作用。

如果检查警告日志文件,可以发现相关更改操作的痕迹:alter database character set INTERNAL_CONVERT ZHS16GBK

Updating character set in controlfile to ZHS16GBK

SYS.SNAP$ (REL_QUERY) - CLOB representation altered

SYS.METASTYLESHEET (STYLESHEET) - CLOB representation altered

SYS.EXTERNAL_TAB$ (PARAM_CLOB) - CLOB representation altered

XDB.XDB$RESOURCE (SYS_NC00027$) - CLOB representation altered

ODM.ODM_PMML_DTD (DTD) - CLOB representation altered

OE.WAREHOUSES (SYS_NC00003$) - CLOB representation altered

PM.ONLINE_MEDIA (SYS_NC00042$) - CLOB representation altered

PM.ONLINE_MEDIA (SYS_NC00062$) - CLOB representation altered

PM.ONLINE_MEDIA (PRODUCT_TEXT) - CLOB representation altered

PM.ONLINE_MEDIA (SYS_NC00080$) - CLOB representation altered

PM.PRINT_MEDIA (AD_SOURCETEXT) - CLOB representation altered

PM.PRINT_MEDIA (AD_FINALTEXT) - CLOB representation altered

Completed: alter database character set INTERNAL_CONVERT ZHS1

在使用这个命令时,Oracle会跳过所有子集及超集的检查,在任意字符集之间进行强制转换,所以,使用这个命令时你必须十分小心,并必须清楚这一操作会带来的风险。

之前讲过的内容仍然有效,可以使用csscan扫描整个数据库,如果在转换的字符集之间确认没有严重的数据损坏,或者可以使用有效的方式更改,就可以使用这种方式进行转换。

这个内部命令的用户引用格式如下:alter database character set INTERNAL_USE ZHS16CGB231280

来看一下具体的操作过程及Oracle的内部操作:SQL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> STARTUP MOUNT;

Database mounted.

SQL> ALTER SYSTEM ENABLE RESTRICTED SESSION;

System altered.

SQL> ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;

System altered.

SQL> ALTER SYSTEM SET AQ_TM_PROCESSES=0;

System altered.

SQL> ALTER DATABASE OPEN;

Database altered.

SQL> alter session set events '10046 trace name context forever,level 12';

Session altered.

SQL> alter database character set INTERNAL_USE ZHS16CGB231280

Database altered.

这时警告日志文件中的记录了如下信息:Tue Oct 19 16:26:30 2004

Database Characterset is ZHS16GBK

replication_dependency_tracking turned off (no async multimaster replication found)

Completed: ALTER DATABASE OPEN

Tue Oct 19 16:27:07 2004

alter database character set INTERNAL_USE ZHS16CGB231280

Updating character set in controlfile to ZHS16CGB231280

Tue Oct 19 16:27:15 2004

Thread 1 advanced to log sequence 118

Current log# 2 seq# 118 mem# 0: /opt/oracle/oradata/primary/redo02.log

Tue Oct 19 16:27:15 2004

ARC0: Evaluating archive   log 3 thread 1 sequence 117

ARC0: Beginning to archive log 3 thread 1 sequence 117

Creating archive destination LOG_ARCHIVE_DEST_1: '/opt/oracle/oradata/primary/archive/1_117.dbf'

ARC0: Completed archiving  log 3 thread 1 sequence 117

Tue Oct 19 16:27:20 2004

Completed: alter database character set INTERNAL_USE ZHS16CGB231280

Shutting down instance: further logons disabled

Shutting down instance (immediate)

License high water mark = 1

Tue Oct 19 16:29:06 2004

ALTER DATABASE CLOSE NORMAL

...

格式化10046跟踪文件,得到以下信息(摘要):alter session set events '10046 trace name context forever,level 12'

alter database character set INTERNAL_USE ZHS16CGB231280

....

update col$ set charsetid = :1 where charsetform = :2

....

update argument$ set charsetid = :1 where charsetform = :2

....

update collection$ set charsetid = :1 where charsetform = :2

....

update attribute$ set charsetid = :1 where charsetform = :2

....

update parameter$ set charsetid = :1 where charsetform = :2

....

update result$ set charsetid = :1 where charsetform = :2

....

update partcol$ set spare1 = :1 where charsetform = :2

....

update subpartcol$ set spare1 = :1 where charsetform = :2

....

update props$ set value$ = :1 where name = :2

....

update "SYS"."KOTAD$" set SYS_NC_ROWINFO$ = :1 where SYS_NC_OID$ = :2

....

update seq$ set increment$=:2,minvalue=:3,maxvalue=:4,cycle#=:5,order$=:6,

cache=:7,highwater=:8,audit$=:9,flags=:10 where obj#=:1

....

update kopm$ set metadata = :1, length  = :2 where name='DB_FDO'

....

ALTER DATABASE CLOSE NORMAL

可以看到这个过程和之前ALTER DATABASE CHARACTER SET操作的内部过程是完全相同的,也就是说INTERNAL_USE提供的帮助就是使Oracle数据库绕过了子集与超集的校验。

这一方法在某些方面是有用处的,比如测试;但应用于产品环境时就应该格外小心,除了你以外,没有人会为此带来的后果负责!

3.11  字符集更改的案例

前面强调过,通过更新props$表修改字符集的方式是不可取的,但是仍然有很多DBA在不断冒险,曾经有朋友在更新数据库字符集为ZHS16GBK时漏写了一个S,结果更新为ZH16GBK,导致数据库无法启动。

在这种情况下,根据我们前面3.3节的探讨,数据库无法启动实际上是因为无法加载一个不存在的字符集文件导致的,针对这种情况的一个临时性解决方案是通过Oracle的Locale Builder工具创建一个临时的字符集文件(字符集名称设置为错误拼写的字符集),使得启动时的字符集文件检验可以通过,然后数据库可以被打开。

曾经有网友经历过这样一个案例:

数据库为 9.2.0.7.0 ,OS : Solaris Operating System (SPARC 64-bit)

起因是这样的,我的一客户那里UPS出现故障导致系统宕机,然后起来,大约过了十来分钟,突然操作系统找不到磁盘又一次宕机,然后再起来,有用户报一个SQL用不上索引。

这个SQL是这样的:select * from ww.test20060504 dg where dg.user_number='7290'

第一个想法是给那个索引做分析,但还是不行,我们就对这个表做了一次分析,但执行计划没有什么改变 。我们尝试加提示(包括加 rule ),但也不行,用户反映是有一批这样类似的都用不到索引。

然后通过10053做trace,居然发现优化器根本没有考虑索引。开始怀疑这个数据库的数据字典可能有问题。我们只好用一个笨方法,将其中一个表导到测试库上去测试,在导出的过程中居然发现系统报错:EXP-00056: ORACLE error 6552 encountered

ORA-06552: PL/SQL: Compilation unit analysis terminated

ORA-06553: PLS-553: character set name is not recognized

居然系统报字符集的错!我们马上仔细检查了一个alter文件发现了一条信息,系统在第一次宕机起来后就自已将controlfile 中的字符集给更改了。最后我们将系统中的字符集改回来系统就恢复正常了。

警告日志中的信息是这样的:SMON: enabling tx recovery

Mon Jun 5 09:52:52 2006

Updating character set in controlfile to ZHS16CGB231280

replication_dependency_tracking turned off (no async multimaster replication found)

其实这个信息是手工更新过数据库字符集后,重新启动,Oracle比较数据库和控制文件信息,根据数据库字符集修改控制文件字符集导致的。在这样的案例中,由于字符集的错误修改,会导致数据库出现很多混乱,所以,当我们面对字符集的问题时,应该十分谨慎。

总结一下,无论什么时候,对于DBA来说,有一个很重要的原则就是:不要把你的数据库置于危险的境地!这就要求我们,在进行任何可能对数据库结构发生改变的操作之前,先做有效的备份,很多DBA没有备份的操作中得到了惨痛的教训。

oracle 字符集 自造字,循序渐进Oracle:自定义字符集的使用、更改字符集的内部方式及字符集更改的案例...相关推荐

  1. 从四大造字法看文字所承载的文化_中国四大造字法

    古老的汉字生生不息,从形成.发展到形成文字体系,其间经历了漫长的历程.而造字法作为汉字文化长河中磨砺的珍珠,在历史的积淀下也更加璀璨夺目.下面是语文迷小编收集整理的关于中国四大造字法的介绍,欢迎大家阅 ...

  2. 循序渐进Oracle:数据库的字符集和字符集文件

    导读:本文来自『墨天轮』专栏"循序渐进Oralcle"(https://www.modb.pro/topic/6289,复制到浏览器中打开或者点击"阅读原文") ...

  3. 先随机后排序的oracle,Oracle用decode函数或CASE-WHEN实现自定义排序

    Oracle用decode函数或CASE-WHEN实现自定义排序 1 问题 对SQL排序,只要在order by后面加字段就可以了,可以通过加desc或asc来选择降序或升序.但排序规则是默认的,数字 ...

  4. oracle 查询字符代码dump,字符集问题(Linux、oracle、终端等,导入导出数据)

    locale的设定及其LANG.LC_ALL.LANGUAGE环境变量的区别 例如zh_CN.GB2312.zh_CN.GB18030或者zh_CN.UTF-8.很多人都不明白这些古里古怪的表达方式. ...

  5. 2020-01-08 Oracle 数据库储存生僻字

    在运维过程中发现了生僻字的存储和传输.生僻字的主要来源是人员姓名,传输过程中定义了生僻字的单独的特殊传输方式,但是在存储时运维人员并不能很明确的明确字体是生僻字,现就生僻字存储的方式找到以下解决方案, ...

  6. 跨平台表空间传输(摘自eygle《循序渐进Oracle》)

    需要注意的是,在Oracle 10g之前,数据文件是不能够跨平台传输使用的,从Oracle 10g开始,Oracle支持跨平台的表空间传输,这极大地增强了数据迁移的便利性. 1.  字节顺序和平台 数 ...

  7. Oracle字符集的查看查询和Oracle字符集的设置修改

    本文主要讨论以下几个部分:如何查看查询oracle字符集. 修改设置字符集以及常见的oracle utf8字符集和oracle exp 字符集问题. 一.什么是Oracle字符集 Oracle字符集是 ...

  8. oracle的homes在哪里配置,Oracle字符集 简介

    三个组成部分(语言.地域.字符集),每个成分控制了NLS子集的特性. Language:指定Oracle消息使用的语言,校验,日期中月份和日显示.[指定服务器消息的语言] Territory:指定默认 ...

  9. oracle字符集有哪几种,Oracle字符集的三大类型

    我们都知道Oracle字符集问题,可以分成三类: 即,数据库字符集, sqlplus的字符集(客户端字符集),以及 终端程序的字符集 (非Oracle的),以下的文章就是对Oracle字符集三种类型的 ...

最新文章

  1. 基于Delphi的Socket I/O模型全接触
  2. python anova_anova_lm()python:它适用于哪种模型类型?
  3. delphi控件切图界面闪烁_小程序设计,不得不说的7个坑 (附资源:新版小程序 UI 控件,Sketch 版)...
  4. 超详细!上线一个机器学习项目你需要哪些准备?
  5. 声音均衡器怎么调好听_汽车10段音效最佳设置,手把手教你调节车载音响均衡器...
  6. 1.3 将临时变量内联化
  7. linux运维常见的故障,Linux运维中遇到的常见问题
  8. The program ‘roscore‘ is currently not installed 解决办法
  9. webstorm 搜狗输入法,输入汉字变成繁体字
  10. Linux命令--vi(编辑或查看文件内容)
  11. Chrome谷歌浏览器安装与配置教程
  12. D. Berserk And Fireball(模拟)
  13. eSPI自学笔记(一):前言和简介
  14. CASS11.0亮点介绍(超越自我,再续辉煌),AutoCAD2020平台界面更加高雅了,或许您应该来体验一下新平台的高雅黑
  15. 计算机毕业设计 SpringBoot+Vue作业帮课程管理系统 作业帮信息管理系统 作业帮试题管理系统
  16. Xcode调试中如何将指定地址转换为其指向的对象
  17. 2019年9月总结,10月展望
  18. 如何提高接口自动化测试的有效性覆盖和案例有效性
  19. 判断字符串是不是回文
  20. 股票自动化交易软件的优势

热门文章

  1. 业界首个面向NLP场景深度迁移学习框架
  2. 模型也可以上网课?!一文看懂服务型蒸馏训练方案
  3. 深度度量学习的这十三年,难道是错付了吗?
  4. 当你舌吻十秒后,下面就……
  5. 订单管理之更新订单表状态数据
  6. 文档信息的向量化-词袋模型、gensim实现和词条分布
  7. Scrapy安装错误: error: Microsoft Visual C++ 14.0 is required. Get it with Microsoft Visual C++ Build To
  8. 技术09期:5分钟带你快速了解TypeScript
  9. 部署教程 | ResNet原理+PyTorch复现+ONNX+TensorRT int8量化部署
  10. 精简易懂,30 分钟学会 SVD 矩阵分解,很强!