转Oracle 数据类型及存储方式 【B】

§1.5  NCHAR和NVARCHAR2
如果系统需要集中管理和存储多种字符集,就需要使用这两种字符类型。在使用NCAHR和NVARCHAR2时,文本内容采用国家字符集来存储和管理。而不是默认字符集。
这两种类型的长度指的是字符数,而不是字节数。
NLS国家语言支持(National Language Support)
在oracle 9i及以后的版本,数据库的国家字符集可以是:utf-8和AL16UTF-16两种。
Oracle 9i是utf -8, Oralce 10g是AL16UTF-16.

1.新建一个表,有两列,类型分别为:nchar和nvarchar2.长度都为10
SQL> create table test_nvarchar(col_nchar nchar(10),col_nvarchar2 nvarchar2(10));
Table created

2.插入一些数据
SQL> insert into test_nvarchar values('袁','袁光东');
1 row inserted
SQL> insert into test_nvarchar values(N'袁',N'袁光东');
1 row inserted
(在9i之前的版本,插入时加上N时,在处理时跟普通方式有不同的方式。但是在10g的时候已经有了改变,加不加N都是一样,这里只是为了测试)
SQL> insert into test_nvarchar values('a','b');

1 row inserted
插入一行英文字母

3. 查看每行的col_nchar列的存储方式。
SQL> select col_nchar, dump(col_nchar) from test_nvarchar;

COL_NCHAR            DUMP(COL_NCHAR)
-------------------- --------------------------------------------------------------------------------
袁                   Typ=96 Len=20: 136,129,0,32,0,32,0,32,0,32,0,32,0,32,0,32,0,32,0,32
a                    Typ=96 Len=20: 0,97,0,32,0,32,0,32,0,32,0,32,0,32,0,32,0,32,0,32
袁                   Typ=96 Len=20: 136,129,0,32,0,32,0,32,0,32,0,32,0,32,0,32,0,32,0,32

Typ=96 与char的类型编码一样。
Len=20 每一行的长度都是20字节。这一点跟char一样。都是定长的,会以空格填充。
需要注意的是:统统以两位来表示一个字符。
136,129 表示’袁’
0,97 表示’a’
0,32 表示空格。

4. nvarchar2的储存
SQL> select col_nvarchar2, dump(col_nvarchar2) from test_nvarchar;

COL_NVARCHAR2        DUMP(COL_NVARCHAR2)
-------------------- --------------------------------------------------------------------------------
袁光东               Typ=1 Len=6: 136,129,81,73,78,28
b                    Typ=1 Len=2: 0,98
袁光东               Typ=1 Len=6: 136,129,81,73,78,28

Typ=1 与varchar2一样。
每一行的len值都不样同。不会使用空格进行填充。
每一个字符都占有两个字节两进行存储。
b 存储为: 0, 98
袁 存储为: 136,129

5.nchar和nvarchar2的数据定义。
SQL> desc test_nvarchar;
Name          Type          Nullable Default Comments
------------- ------------- -------- ------- --------
COL_NCHAR     NCHAR(20)     Y                        
COL_NVARCHAR2 NVARCHAR2(20) Y   

虽然在定义nchar和nvarchar2时,指定的长度是指字符数。但是表结构的定义中,仍然是存储着它的字节数。
在定义时nchar(10)表示可以最大存储10个字符。
在查看数据表结构时,显示该列最大占用的字节数。


需要注意的是:在char和nchar中对汉字的实际存储值是不一样的。因为采用了不同的字符集,就有了不同的字符编码。

SQL> insert into test_varchar values('袁');

1 row inserted
SQL> select col, dump(col) from test_varchar where col='袁';

COL        DUMP(COL)
---------- --------------------------------------------------------------------------------
袁         Typ=1 Len=2: 212,172
这时采用的字符集系统默认字符集ZHS16GBK。
这里很容易的把它转换成ascii码。
高位 * 256(2的8次方) + 低位.
212 * 256 + 172 = 54444

SQL> select chr(54444) from dual;

CHR(54444)
----------


而在Nchar 和Nvarchar中,采用的是UTF-8或UTF-16的字符集。

SQL> insert into test_nvarchar values('袁','袁');

1 row inserted

SQL> select col_nvarchar2, dump(col_nvarchar2) from test_nvarchar where col_nvarchar2='袁';

COL_NVARCHAR2        DUMP(COL_NVARCHAR2)
-------------------- --------------------------------------------------------------------------------
袁                   Typ=1 Len=2: 136,129

‘袁’存储的值为:136,129
Oracle 10以上对nchar和nvarchar都采用utf-16字符集了。它的好处就是对字符采用固定长度的字节存储(2字节),支持多国字符,在操作效率上会更高。但是它却无法兼容于ascii码。
§1.6  RAW
RAW与CHAR和VARCHAR2相比。RAW属于二进制数据,更可以把它称为二进制串。在对CHAR和VARCHAR2类型进行存储时,会进行字符集转换。而对二进制数据进行存储则不会进行字符集转换。
SQL> create table test_raw (col_chr varchar2(10), col_raw raw(10));

Table created
SQL> insert into test_raw values('aa','aa');

1 row inserted

SQL> commit;

Commit complete

SQL> select * from test_raw;

COL_CHR    COL_RAW
---------- --------------------
aa         AA

SQL> select col_chr,dump(col_chr) from test_raw;

COL_CHR    DUMP(COL_CHR)
---------- --------------------------------------------------------------------------------
aa         Typ=1 Len=2: 97,97
SQL> select col_raw,dump(col_raw) from test_raw;

COL_RAW              DUMP(COL_RAW)
-------------------- --------------------------------------------------------------------------------
AA                   Typ=23 Len=1: 170

通过上面的分析,虽然我们通过select查询得到的结果,raw列显示为插入的字符。但是我们通过dump函数得知到raw并不是以字符的方式存储。它是把插入的字符认为是16进制的值。
比如本例,我们向raw列插入aa,但是它占用的空间为1个字节。值为170.
170转为16进制正好是aa
向raw列插入数据时会发生一个隐式转换HEXTORAW
从raw列读取数据时会发生一个隐式转换RAWTOHEX

如果向raw列插入值不是有效的十六进制值时,会报错的。
SQL> insert into test_raw values('h','h');

insert into test_raw values('h','h')

ORA-01465: invalid hex number
原文地址:https://www.cnblogs.com/linsond/p/1767964.html