欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

Oracle基本数据类型存储格式浅析(一)字符类型

程序员文章站 2022-04-20 13:54:39
...

主要说明字符类型的存储式。主要包括char、varchar2和long等几种类型。 1 实验(数字,英文字母) 1.1 建表 SQL create table test_char(char_col char(10), varchar_col varchar2(10), long_col long) tablespace assm; Table created SQL insert into test

主要说明字符类型的存储格式。主要包括char、varchar2和long等几种类型。

1 实验(数字,英文字母)

1.1 建表

SQL> create table test_char(char_col char(10), varchar_col varchar2(10), long_col long) tablespace assm;

Table created

SQL> insert into test_char values ('abc', '123', ',fd');

1 row inserted

SQL> commit;

Commit complete

SQL> select a.*,

2 rowid,

3 dbms_rowid.rowid_object(rowid) obj#,

4 dbms_rowid.rowid_relative_fno(rowid) file#,

5 dbms_rowid.rowid_block_number(rowid) block#,

6 dbms_rowid.rowid_row_number(rowid) row#

7 from test_char a;

CHAR_COL VARCHAR_COL LONG_COL ROWID OBJ# FILE# BLOCK# ROW#

---------- ----------- ------------ ------------------ ---------- ---------- ---------- ----------

abc 123 ,fd AAANCkAAHAAAACYAAA 53412 7 152 0

1.2 dump block

FILE#为7,BLOCK#为152。

SQL> alter system dump datafile 7 block 152;

System altered

SQL> select p.spid

2 from v$session s, v$process p, v$mystat m

3 where s.paddr = p.addr

4 and s.sid = m.sid

5 and rownum = 1;

SPID

-----------

18108

1.3 查看trace文件

根据SPID找到trace文件。

……

block_row_dump:

tab 0, row 0, @0x1f82

tl: 22 fb: --H-FL-- lb: 0x1 cc: 3

col 0: [10] 61 62 63 20 20 20 20 20 20 20

col 1: [ 3] 31 32 33

col 2: [ 3] 2c 66 64

end_of_block_dump

1.4 结论分析

观察dump出来的结果,可以发现以下几点:

1.对于每个字段,除了保存字段的值以外,还会保存当前字段中数据的长度。而且,oracle显然没有把字段的长度定义或类型定义保存在block中,这些信息保存在oracle的数据字典里面。

2.根据dump的结果,可以清楚的看到,字符类型在数据库中是以Ascii格式存储的。

SQL> select chr(to_number('61', 'xx')) from dual;

CHR(TO_NUMBER('61','XX'))

-------------------------

a

SQL> select dump(char_col, 16) d_char from test_char;

D_CHAR

--------------------------------------------------------------------------------

Typ=96 Len=10: 61,62,63,20,20,20,20,20,20,20

SQL> select dump(varchar_col, 16) d_varchar2 from test_char;

D_VARCHAR2

--------------------------------------------------------------------------------

Typ=1 Len=3: 31,32,33

SQL> select dump(long_col, 16) d_varchar2 from test_char;

select dump(long_col, 16) d_varchar2 from test_char

ORA-00997: illegal use of LONG datatype

由于DUMP 不支持LONG类型,因此我们使用了alter system dump block的方式,通过比较两种方式得到的结果,发现DUMP()函数不但方便,结果清晰,而且指出了进行DUMP的数据类型,在以后的例子中,除非必要 的情况,否则都会采用DUMP()函数的方式进行说明。

2 实验(中文)

2.1 中文

SQL> select a.name, a.value$ from sys.props$ a where a.name like '%CHARACTERSET%';

NAME VALUE$

------------------------------ ----------------

NLS_CHARACTERSET ZHS16GBK

NLS_NCHAR_CHARACTERSET AL16UTF16

SQL> insert into test_char values ('定长', '变长', null);

1 row inserted

SQL> commit;

Commit complete

SQL> select dump(char_col, 16) d_char from test_char;

D_CHAR

--------------------------------------------------------------------------------

Typ=96 Len=10: 61,62,63,20,20,20,20,20,20,20

Typ=96 Len=10: b6,a8,b3,a4,20,20,20,20,20,20

SQL> select dump(varchar_col, 16) d_varchar2 from test_char;

D_VARCHAR2

--------------------------------------------------------------------------------

Typ=1 Len=3: 31,32,33

Typ=1 Len=4: b1,e4,b3,a4

根据dump结果,可以清楚的看出,普通英文字符和标点用一个字节表示,而中文字符或中文标点需要两个字节来表示。

2.2 nchar与nvarchar2

SQL> create table test_nchar(nchar_col nchar(10), nvarchar_col nvarchar2(10));

Table created

SQL> insert into test_nchar values('nchar定长', 'nvarchar变长');

1 row inserted

SQL> commit;

Commit complete

SQL> select dump(nchar_col, 16) from test_nchar;

DUMP(NCHAR_COL,16)

--------------------------------------------------------------------------------

Typ=96 Len=20: 0,6e,0,63,0,68,0,61,0,72,5b,9a,95,7f,0,20,0,20,0,20

SQL> select dump(nvarchar_col, 16) from test_nchar;

DUMP(NVARCHAR_COL,16)

--------------------------------------------------------------------------------

Typ=1 Len=20: 0,6e,0,76,0,61,0,72,0,63,0,68,0,61,0,72,53,d8,95,7f

采用nchar,nvarchar2虽然仍然是采用Ascii码存储,但是nchar使用的AL16UTF16字符集,编码长度变为2个字节。这样中文使用两个字节,对于可以用一个字节就表示的英文字符,采用了高位补0的方式凑足2位,这样,对于采用AL16UTF16字符集的nchar类型,无论中文还是英文都用2位字符表示。

转贴:http://www.itpub.net/forum.php?mod=viewthread&tid=308317