暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle的N-数据类型困惑

1482

Oracle中存储字符串,我们通常会用CHAR、VARCHAR2等,但是有时就会碰到使用NCHAR、NVARCHAR2的情况,当做数据迁移时,格外要注意,避免因为存储空间的问题,导致插入失败。


谈到N-数据类型,不得不提到国家字符集(National Character Set),国家字符集是用于像NCHAR、NVARCHAR2、NCLOB这种数据类型的,他是由参数NLS_NCHAR_CHARACTERSET控制。普通的数据库字符集,则用于CHAR、VARCHAR2、LONG和CLOB数据类型的,则是参数NLS_CHARACTERSET控制的。


从9i开始,NLS_NCHAR_CHARACTERSET只能有2个取值,UTF8或者AL16UTF16,默认值是AL16UTF16,如果无特殊需求,推荐用该值。


使用国家字符集的数据类型主要有三种,

NCHAR - 定长类型的国家字符集字符串,列的长度按照字符个数计算(即CHAR的语义)。

NVARCHAR2 - 变长类型的国家字符集字符串,列的长度按照字符个数计算(即CHAR的语义)。

NCLOB - 存储最多4GB字符串,即使NLS_NCHAR_CHARACTERSET定义为UTF8,在这种数据类型,数据都会按照UCS2或者AL16UTF16进行存储,影响有限,具体可参考Possible action for CLOB/NCLOB storage after 10g upgrade(Doc ID 258114.1)。


CHAR语义和BYTE语义,可以参考《NLS_LENGTH_SEMANTICS参数引申的问题》,N-类型只能定义为CHAR语义,不能定义为BYTE语义。


The National Character Set(NLS_NCHAR_CHARACTERSET) in Oracle 9i, 10g , 11g and 12c (Doc ID 276914.1)给了一张图,


从图上可知,如果字符集是UTF8,最小需要1个字节存储,4000/1=4000,4000是字段可定义的最大长度,最大需要3个字节存储,例如中文,4000/3=1333+1,1333是字段可定义的最大长度。


如果用的AL16UTF16,都是按照2个字节存储,可以体验下,


因此字段可定义的最大长度就是2000,如下所示,超过就提示错误,

SQL>  create table t1(id nvarchar2(2001));
create table t1(id nvarchar2(2001))
*
ERROR at line 1:
ORA-00910: specified length too long for its datatype


定义为2000,才可执行,

SQL> create table t1(id nvarchar2(2000));
Table created.


但是虽然我们定义了NVARCHAR2(2000),实际插入超过2000的字符,并不会提示错误,

SQL> update t1 set id = lpad('你', 4000, '你');
1 row updated.


然而实际存储的,是截断的,所以要注意,


如果数据库采用Unicode作为默认字符集,其实没任何必要用到NVARCHAR2类型,而且在Oracle关于国际化的官方文档中,推荐使用AL32UTF8字符集。这个帖子,解释的很明白,

https://community.oracle.com/mosc/discussion/comment/11489625


VARCHAR2和NVARCHAR2在使用上的一些问题,


因此,数据库采用UTF8字符集就可以忽略国家字符集了,



近期更新的文章:

问题定位的思考

国足世界杯畅想

小白学习MySQL - varchar类型字段为什么经常定义成255?

介绍一款Oracle的利器小工具-SQLcl

ClickHouse的ontime测试数据集


文章分类和索引:

《公众号800篇文章分类和索引

文章转载自bisal的个人杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论