Oracle 11g中的char类型使用

Oracle数据表和程序类型中,字符类型可能是使用最多的一种了。从历史上看,Oracle首先推出了固定长度char类型字段,之后才推出了变长度类型varchar2。目前,主流Oracle应用开发都已经普遍接受了varchar2作为数据表字段类型表示。如果存在超长字符,都考虑使用CLOB这类大对象进行存储。

但是,我们在实际领域中,还是会在各种遗留系统中发现很多char类型字段。而且连带这些遗留系统的下游系统中,char类型也会经常出现。在这样的背景下,开发运维人员其实还是有很多的接触char的机会的。

Char最大的特点就是固定长度存储,例如定义长度char(10),保存的字符串为’kkk’三位长度。在保存的时候,Oracle会自动将其尾部补齐空格。这样就确保了每个保存在char(10)的字段都是10位长度。根据笔者的猜测,char的策略是在Oracle对于存储空间管理能力较弱的背景下提出的一种折中策略。随后,varchar2的出现逐步将这种变通策略加以替代。

在一些时候,笔者还是会遇到一些朋友的问题:明明检索全表时候看到字符串取值是xxx,但是用SQL加在后面where条件的时候,就没有检索结果,仿佛“见鬼一样”。究其根源,常常是char在里面“捣乱”,where条件后面加上若干个空格或者使用rpad命令进行补全。

本篇主要介绍几个在11g里面常见的使用场景。注意:随着版本的升级,Oracle对于char的支持其实也在不断升级(默默地),尽可能让其靠近varchar2的使用效果。所以,本文中的实验内容,在其他版本下可能会有不同的测试结果,请注意。

1、环境说明

本文使用Oracle 11gR2进行测试,具体版本为11.2.0.4。

SQL> select * from v$version;

BANNER

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

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

PL/SQL Release 11.2.0.4.0 - Production

CORE    11.2.0.4.0    Production

TNS for Linux: Version 11.2.0.4.0 - Production

NLSRTL Version 11.2.0.4.0 – Production

创建实验数据表T。

SQL> create table t (chr_a char(100), vchar_a varchar2(100));

Table created

SQL> desc t;

Name    Type          Nullable Default Comments 

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

CHR_A  CHAR(100)    Y                         

VCHAR_A VARCHAR2(100) Y                         

SQL> insert into t select owner, owner from dba_objects;

119498 rows inserted

SQL> commit;

Commit complete

SQL> exec dbms_stats.gather_table_stats(user,'T',cascade => true);

PL/SQL procedure successfully completed

数据取值’SCOTT’的记录数目为6。

SQL> select count(*) from t where vchar_a='SCOTT';

COUNT(*)

----------

6

2、常量where条件测试

首先我们测试一下单独写常量条件的情况。

SQL> select count(*) from t where chr_a='SCOTT';

COUNT(*)

----------

6

SQL> select length(chr_a) from t where chr_a='SCOTT';

LENGTH(CHR_A)

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

100

100

100

100

100

100

6 rows selected

上面两个SQL语句表明:在使用常量作为条件的where语句时候,即使字段类型是char,系统会自动进行右侧空格的“补齐”动作,让其满足char条件,检索出正确的结果。借助length函数,我们也可以确定长度为100。

笔者一直想了解这个“偷天换日”的过程,从执行计划角度也不能看出实际的情况。

SQL> explain plan for select count(*) from t where chr_a='SCOTT';

Explained

SQL> select * from table(dbms_xplan.display(format => 'advanced'));

PLAN_TABLE_OUTPUT

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

Plan hash value: 2966233522

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

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time    |

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

|  0 | SELECT STATEMENT  |      |    1 |  101 |  510  (1)| 00:00:07 |

|  1 |  SORT AGGREGATE    |      |    1 |  101 |            |          |

|*  2 |  TABLE ACCESS FULL| T    |    11 |  1111 |  510  (1)| 00:00:07 |

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

Query Block Name / Object Alias (identified by operation id):

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

1 - SEL$1

2 - SEL$1 / T@SEL$1

Outline Data

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

/*+

PLAN_TABLE_OUTPUT

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

BEGIN_OUTLINE_DATA

FULL(@"SEL$1" "T"@"SEL$1")

OUTLINE_LEAF(@"SEL$1")

ALL_ROWS

DB_VERSION('11.2.0.4')

OPTIMIZER_FEATURES_ENABLE('11.2.0.4')

IGNORE_OPTIM_EMBEDDED_HINTS

END_OUTLINE_DATA

*/

Predicate Information (identified by operation id):

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

2 - filter("CHR_A"='SCOTT')

Column Projection Information (identified by operation id):

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

1 - (#keys=0) COUNT(*)[22]

39 rows selected

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/df1b630696950fbc4747c9dd9d0dc3af.html