字符集分类
在Oracle中定义的字符集不能超过2个:
- 数据库字符集(nls_character)用于CHAR, VARCHAR2, LONG和CLOB数据类型中的数据;
- 数据库国家字符集(nls_nchar_character)用于存储在NCHAR, NVARCHAR2和NCLOB数据类型中的数据;
使用如下sql检查当前数据库的字符集
SQL> select * from nls_database_parameters where PARAMETER in ('NLS_CHARACTERSET','NLS_NCHAR_CHARACTERSET');
PARAMETER VALUE
------------------------------ --------------------
NLS_CHARACTERSET AL32UTF8
NLS_NCHAR_CHARACTERSET AL16UTF16
使用如下sql检查当前数据库使用的字符集
SQL> select distinct(nls_charset_name(charsetid)) CHARACTERSET,
decode(type#, 1, decode(charsetform, 1, 'VARCHAR2', 2, 'NVARCHAR2','UNKNOWN'),
9, decode(charsetform, 1, 'VARCHAR', 2, 'NCHAR VARYING', 'UNKNOWN'),
96, decode(charsetform, 1, 'CHAR', 2, 'NCHAR', 'UNKNOWN'),
8, decode(charsetform, 1, 'LONG', 'UNKNOWN'),
112, decode(charsetform, 1, 'CLOB', 2, 'NCLOB', 'UNKNOWN')) TYPES_USED_IN
from sys.col$ where charsetform in (1,2) and type# in (1, 8, 9, 96, 112)
order by CHARACTERSET, TYPES_USED_IN;
CHARACTERSET TYPES_USED_IN
---------------------------------------- -------------
AL16UTF16 NCHAR
AL16UTF16 NCLOB
AL16UTF16 NVARCHAR2
AL32UTF8 CHAR
AL32UTF8 CLOB
AL32UTF8 LONG
AL32UTF8 VARCHAR2
7 rows selected.
数据库字符集
Oracle建议使用AL32UTF8字符集。是Unicode字符集。
统一码(Unicode),也叫万国码、单一码,由统一码联盟开发,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。
统一码是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
AL32UTF8:
- AL32UTF8是Oracle数据库中的一种字符编码字符集。
- 它是一种可变长度编码,使用1至4个字节来表示不同的Unicode字符。
- 大多数亚洲文字的字符用3个字节表示。补充字符用4个字节表示。
- AL32UTF8能够表示几乎所有的Unicode字符,包括各种语言的字符、符号和特殊字符。
- AL32UTF8在存储数据时相对节省空间,特别适用于包含大量非英文字符的数据。
- 它是Oracle数据库中多语言支持的常用字符集之一。
NLS_LANG
NLS_LANG是用来让Oracle知道你的客户端操作系统正在使用什么字符集,以便Oracle可以做(如果需要)从客户端字符集到数据库字符集的转换。
国家字符集
NLS_NCHAR_CHARACTERSET是在创建数据库时定义的。
从9i开始,NLS_NCHAR_CHARACTERSET只能有2个值:UTF8或AL16UTF16,它们都是Unicode字符集。
如果没有指定,NLS_NCHAR_CHARACTERSET默认为AL16UTF16,这是推荐值。
N-types在编程语言和应用层通常只有很少的支持。使用N-types需要客户端应用/程序的明确支持。
AL16UTF16:
- AL16UTF16也是Oracle数据库中的一种字符编码字符集。
- UTF-16是Unicode的16位编码形式。在UTF-16中,一个字符可以由一个16位整数值(两个字节)或两个16位整数值(四个字节)表示。来自基本多语言平面的所有字符都用两个字节表示,这些字符是日常文本中使用最多的字符。补充字符用四个字节表示。编码单个补充字符的两个代码单元(整数值)称为代理对。
- AL16UTF16能够表示全球范围内的字符,包括各种语言的字符和符号。
- AL16UTF16适用于需要在数据库中保留完整的Unicode字符表示的场景。
从存储空间而言:
如果你有很多非西方的数据(西里尔文、中文、日文、印地语……),那么对这些列使用N-types是有利的,因为这些字符将在UTF8中使用3个字节,在AL16UTF16中使用2个字节。
西方数据(英语、法语、西班牙语、荷兰语、德语、葡萄牙语等)UTF8 / AL32UTF8在大多数情况下使用的磁盘空间比AL16UTF16少。
国家字符集的使用
使用N-types,在编码时确实使用(N’…’)语法,以便通过在字母前面加上 ‘N’ 前缀来表示是使用国家字符集的:
create table test(a varchar2(100),b nvarchar2(100));
insert into test values('董',N'董');
commit;
--验证
SQL> select a,b,dump(a,1016),dump(b,1016) from test;
A B DUMP(A,1016) DUMP(B,1016)
---------- ---------- -------------------------------------------------- --------------------------------------------------
董 董 Typ=1 Len=3 CharacterSet=AL32UTF8: e8,91,a3 Typ=1 Len=2 CharacterSet=AL16UTF16: 84,63
SQL>
可以看到AL32UTF8中汉字‘董’占用3个字节,AL16UTF16中汉字‘董’占用2个字节。
因此,最好使用AL16UTF16作为NLS_NCHAR_CHARACTERSET,这将使存储的汉字比UTF8字符集更多。
可以通过如下网站查看unicode字符集对应编码:
https://symbl.cc/en/
Oracle中UTF8和AL32UTF8的一些区别
UTF8和AL32UTF8都是 UTF-8 编码的字符集;
UTF8(Oracle8 和 8i 中引入)的设计没有补充字符的概念,因此 UTF8 的每个字符最多为 3 个字节;
AL32UTF8(Oracle9i 引入) 提供了对新定义的补充字符的支持。所有补充字符都以 4 个字节的方式存储;
Emoji表情插入数据库测试
SQL> insert into test values('😂',N'😂');
1 row created.
SQL> commit ;
Commit complete.
--结果展示
SQL> select a,b,dump(a,1016),dump(b,1016) from test;
A B DUMP(A,1016) DUMP(B,1016)
---------- ---------- -------------------------------------------------- --------------------------------------------------
😂 😂 Typ=1 Len=4 CharacterSet=AL32UTF8: f0,9f,98,82 Typ=1 Len=4 CharacterSet=AL16UTF16: d8,3d,de,2
SQL>
生僻字插入数据库测试
SQL>
insert into test values('囮',N'囮');
insert into test values('𠁃',N'𠁃');
commit;
SQL> select a,b,dump(a,1016),dump(b,1016) from test;
A B DUMP(A,1016) DUMP(B,1016)
---------- ---------- -------------------------------------------------- --------------------------------------------------
囮 囮 Typ=1 Len=3 CharacterSet=AL32UTF8: e5,9b,ae Typ=1 Len=2 CharacterSet=AL16UTF16: 56,ee
𠁃 𠁃 Typ=1 Len=4 CharacterSet=AL32UTF8: f0,a0,81,83 Typ=1 Len=4 CharacterSet=AL16UTF16: d8,40,dc,43
SQL>
ASCII国家字符集形式插入数据库测试
说明AL16UTF16字符集最少占用2个字节
SQL>
insert into test values('A',N'A');
commit;
SQL> select a,b,dump(a,1016),dump(b,1016) from test;
A B DUMP(A,1016) DUMP(B,1016)
---------- ---------- -------------------------------------------------- --------------------------------------------------
A A Typ=1 Len=1 CharacterSet=AL32UTF8: 41 Typ=1 Len=2 CharacterSet=AL16UTF16: 0,41
SQL>
参考文档
https://docs.oracle.com/en/database/oracle/oracle-database/21/nlspg/supporting-multilingual-databases-with-unicode.html#GUID-98BD4E64-99AE-4AD8-8CAD-EE438D988318
The National Character Set ( NLS_NCHAR_CHARACTERSET ) in Oracle 9i, 10g , 11g and 12c (Doc ID 276914.1)
Unicode Character Sets In The Oracle Database (Doc ID 260893.1)
订阅号:DongDB手记
墨天轮:https://www.modb.pro/u/231198