Oracle的N-数据类型困惑

Posted bisal

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle的N-数据类型困惑相关的知识,希望对你有一定的参考价值。

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篇文章分类和索引

以上是关于Oracle的N-数据类型困惑的主要内容,如果未能解决你的问题,请参考以下文章

基于时间复杂度的这些片段真的很困惑

哈斯克尔。我很困惑这个代码片段是如何工作的

支持动态或静态片段的不同屏幕尺寸?

如何在 Toad for Oracle 中使用自定义代码片段?

oracle中的日期类型不包括时间值

Oracle PL/SQL 数据类型