主要说明字符类型的存储式。主要包括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