分类: Oracle
2008-05-23 20:24:40
|
前一阵看完文档,对oracle的基本数据类型的存储格式有了一些,最近有做了一些测试进行了验证。 打算整理总结一下,这一篇主要说明字符类型的存储格式。主要包括char、varchar2和long等几种类型。
SQL> create table test_char (char_col char(10), varchar_col varchar2(10), long_col long); 表已创建。 SQL> insert into test_char values ('abc', '123', ',fd'); 已创建 1 行。 SQL> commit; 提交完成。 SQL> select rowid from test_char; ROWID 根据rowid的定义规则,第7~9位是表示的是数据文件,F表示5,而10~15位表示的是在这个数据文件中的第几个BLOCK,g表示32。(rowid编码相当于64进制。用A~Z a~z 0~9 + /共64个字符表示。A表示0,B表示1,……,a表示26,……,0表示52,……,+表示62,/表示63。) 我们根据的结果去dump这个block。 SQL> ALTER SYSTEM DUMP DATAFILE 5 BLOCK 32; 系统已更改。 打开产生的trace文件: data_block_dump,data header at 0x3421064 观察dump出来的结果,可以发现以下几点: 1.对于每个字段,除了保存字段的值以外,还会保存当前字段中数据的长度。而且,oracle显然没有把字段的长度定义或类型定义保存在block中,这些保存在oracle的数据字典里面。 2. 根据dump的结果,可以清楚的看到,字符类型在数据库中是以ascii格式存储的。 SQL> select chr(to_number('61', 'xx')) from dual; CH 3.char类型为定长格式,存储的时候会在字符串后面填补空格,而varchar2和long类型都是变长的。 SQL> SELECT DUMP(CHAR_COL, 16) D_CHAR FROM TEST_CHAR; D_CHAR SQL> SELECT DUMP(VARCHAR_COL, 16) D_VARCHAR2 FROM TEST_CHAR; D_VARCHAR2 SQL> SELECT DUMP(LONG_COL, 16) D_VARCHAR2 FROM TEST_CHAR; 由于DUMP不支持LONG类型,因此我们使用了alter system dump block的方式,通过比较两种方式得到的结果,发现DUMP()函数不但方便,结果清晰,而且指出了进行DUMP的数据类型,在以后的例子中,除非必要的情况,否则都会采用DUMP()函数的方式进行说明。 下面看一下插入中文的情况,首先看一下数据库的字符集 SQL> select name, value $ from sys.props $ where name like '%CHARACTERSET%'; NAME VALUE $ SQL> insert into test_char values ('定长', '变长', null); 已创建 1 行。 SQL> SELECT DUMP(CHAR_COL, 16) D_CHAR FROM TEST_CHAR; D_CHAR SQL> SELECT DUMP(VARCHAR_COL, 16) D_VARCHAR2 FROM TEST_CHAR; D_VARCHAR2 根据dump结果,可以清楚的看出,普通字符和标点用一个字节表示,而中文字符或中文标点需要两个字节来表示。 下面,对比一下nchar和nvarchar2与char、varchar2类型有什么不同。 SQL> create table test_nchar (nchar_col nchar(10), nvarchar_col nvarchar2(10)); 表已创建。 SQL> insert into test_nchar values ('nchar定长', 'nvarchar变长'); 已创建 1 行。 从这里已经可以看出一些不同了,如果按照刚才中文的计算方法,'nvarchar变长'的长度是8+2*2=12已经超过了数据类型定义的大小,可是为什么插入成功了? 还是dump一下看看结果吧。 SQL> select dump(nchar_col, 16) from test_nchar; DUMP(NCHAR_COL,16) SQL> select dump(nvarchar_col, 16) from test_nchar; DUMP(NVARCHAR_COL,16) 这下就明白了,虽然仍然是采用ascii码存储,但是nchar使用的AL16UTF16字符集,编码长度变为2个字节。这样中文使用两个字节,对于可以用一个字节就表示的英文字符,采用了高位补0的方式凑足2位,这样,对于采用AL16UTF16字符集的nchar类型,无论中文还是英文都用2位字符表示。因此'nvarchar变长'的长度是10,并没有超过数据类型的限制。 |