当前位置:  数据库>oracle

Oracle 11g中的char类型使用

    来源: 互联网  发布时间:2017-06-21

    本文导语: 在Oracle数据表和程序类型中,字符类型可能是使用最多的一种了。从历史上看,Oracle首先推出了固定长度char类型字段,之后才推出了变长度类型varchar2。目前,主流Oracle应用开发都已经普遍接受了varchar2作为数据表字段类型表示...

在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

从执行计划上,我们看不出什么过多的端倪。filter条件中也没有对chr_a取值进行格外的处理。这个过程其实是针对char类型进行的特殊处理,如果我们在where条件后面人为加上空格,会如何呢?

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

  COUNT(*)

----------

        6

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

  COUNT(*)

----------

        6

同样可以正确找到结果。对应执行计划为:

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

执行计划上同样看不到什么变化。

上面的实验,告诉我们char常量使用规则:如果在where条件后面使用常量取值,Oracle会根据字段类型和常量情况进行自动补齐空格动作。常量后面人为添加的空格也会作为自动空格加以处理。

下面讨论如果是rpad函数在常量上,效果如何呢?

3、函数操作效果

在一些比较老的版本Oracle版本里面,一些开发人员为了避免char空格影响,广泛使用了rpad函数,自动的添加后面的空格。

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

  COUNT(*)

----------

        6

正常是可以找到结果的。执行计划上,filter部分显然是先计算出函数取值,之后再进行处理。

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

Explained

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

PLAN_TABLE_OUTPUT

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

Plan hash value: 2966233522

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

(篇幅原因,有省略……)

Predicate Information (identified by operation id):

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

  2 - filter("CHR_A"='SCOTT

                                                                ')

Column Projection Information (identified by operation id):

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

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

40 rows selected

但是,如果设置函数补齐的长度不是“一步到位”,而是部分长度的。Oracle是不能够找到对应结果的。

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

  COUNT(*)

----------

        0

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

  COUNT(*)

----------

        0

使用常量时候的自动补齐动作不再生效了!这就表明:优化器在处理常量时候,有一些特殊的规则逻辑,这部分在应用函数之后就不再使用了。另外一种可能性就是针对等号两端取值进行类型匹配的时候,常量和函数量的取值方式是有差别的。rpad返回的虽然是一个字符类型,但是变长度还是固定长度是不容易确定的。如果Oracle将常量认可为char,rpad结果认可为varchar2,那么结果不一样是可以理解的。

4、绑定变量处理

SQL优化器是目前Oracle中非常复杂的组件之一。其中很多步骤和逻辑都需要我们不断地进行测试和合理猜测得到的。绑定变量是我们在实际开发过程中常常使用的技术之一。下面我们测试一下在PL/SQL代码片段中绑定变量的使用。

SQL> declare

  2    a char(100);

  3    coun number;

  4  begin

  5    a := 'SCOTT';

  6    execute immediate 'select count(*) from t where chr_a=:1'

  7                into coun

  8                using a;

  9    dbms_output.put_line('Result Is : '||to_char(coun));

 10  end;

 11  /

Result Is : 6

PL/SQL procedure successfully completed

绑定变量使用上,关键的一个问题就是绑定变量定义的类型。在上面的代码中,如果使用了char类型的变量,虽然定义取值的时候后面没有空格,Oracle还是事先了常量变量中的“自动补齐动作”。

如果和常量时候一样,赋值是有空格结尾的,那么会如何呢?

SQL> set serveroutput on size 10000;

SQL> declare

  2    a char(100);

  3    coun number;

  4  begin

  5      a := 'SCOTT  ';

  6      execute immediate 'select count(*) from t where chr_a=:1'

  7                    into coun

  8                    using a;

  9      dbms_output.put_line('Result Is : '||to_char(coun));

 10  end;

 11  /

Result Is : 6

PL/SQL procedure successfully completed

效果相同。那么,可以得到结论:如果使用char类型的绑定变量,效果和常量是一样的。那么,如果使用varchar2类型绑定变量,效果如何呢?

SQL> declare

  2    a varchar(100);

  3    coun number;

  4  begin

  5    a := 'SCOTT';

  6    execute immediate 'select count(*) from t where chr_a=:1'

  7                into coun

  8                using a;

  9    dbms_output.put_line('Result Is : '||to_char(coun));

 10  end;

 11  /

Result Is : 0

PL/SQL procedure successfully completed

SQL> set serveroutput on size 10000;

SQL> declare

  2    a varchar(100);

  3    coun number;

  4  begin

  5      a := 'SCOTT  ';

  6      execute immediate 'select count(*) from t where chr_a=:1'

  7                    into coun

  8                    using a;

  9      dbms_output.put_line('Result Is : '||to_char(coun));

 10  end;

 11  /

Result Is : 0

PL/SQL procedure successfully completed

如果绑定变量明确是varchar2,自动补齐效果是不发生的!和之前函数的问题是没有关系的。如果我们在char类型中使用rpad函数进行赋值,看结果应该是可以进行自动补齐的。

SQL> set serveroutput on size 10000;

SQL> declare

  2    a char(100);

  3    coun number;

  4  begin

  5      a := rpad('SCOTT',10,' ');

  6      execute immediate 'select count(*) from t where chr_a=:1'

  7                    into coun

  8                    using a;

  9      dbms_output.put_line('Result Is : '||to_char(coun));

 10  end;

 11  /

Result Is : 6

PL/SQL procedure successfully completed

结果和预计相同。

5、结论

综合上述的实验分析,我们可以得到如下结论:

  • 对char类型,优化器方面会有一定的优化动作,主要在于末尾空格的自动补齐动作;
  • 但是,自动补齐动作出现的条件是类型的匹配,就是进行比较时候变量类型一定是char类型;
  • 如果是varchar2类型,自动补齐动作是不会出现的;
  • 很多字符串相关函数的返回值,都是varchar2类型。


    
 
 

您可能感兴趣的文章:

  • ORACLE数据库常用字段数据类型介绍
  • oracle中的空类型与c语言的空类型相匹配吗?
  • 关于Oracle BLOB类型,一个String字符怎么写入BLOB字段?
  • Oracle中查看某列数据类型
  • 测试添加Oracle中Blob数据类型对象
  • jsp文件上传smartupload到oracle数据库中没有longblob的数据类型如何处理的?
  • oracle中 VARCHAR2是什么数据类型
  • 请问保存文章内容的字段应用什么类型的(oracle),急!!!
  • oracle中怎么没有boolean类型的字段?应该用什么代替?
  • 如何向oracle库中字段类型是date的添加数据
  • 请问:ORACLE中的数据取出来后,需不需要进行一定的转换才能变为C语言的数据类型啊?
  • jsp中在oracle中查询日期类型时sql语句该怎么写啊?
  • 怎样将当前时间写到Oracle中date类型的字段中!!!!!!!!!!!!
  • 急!急!oracle 中 long 类型在 tomcat 中的问题
  • 不能把几百个以上的汉字插入oracle varchar2类型的问题!
  • Oracle里long类型
  • jsp显示oracle中varchar2类型字段 在线等待
  • Oracle中的Raw类型解释
  • 我要向oracle中插入大文本,用的是lang类型的字段,但是只能插3000字,再多就抱错,说我字符串过长。谁遇到过此问题?
  • Oracle返回表类型的自定义函数
  • Oracle中字符集的类型决定varchar2的字符长度
  • linux下安装oracle后使用命令行启动的方法 linux启动oracle
  • Oracle9i 9.0.1的JDBC Drivers 可以给Oracle 8.0.5使用马?
  • Suse linux使用oracle问题
  • 请问:在使用oracle数据库作开发时,是使用pro*c作开发好些,还是使用库函数如oci等好一些啊?或者它们有什么区别或者优缺点啊?
  • jbuilder中使用oracle的问题
  • 求redhat linux 9.0下可以使用的oracle 10g或9i,还有redhat linux 9.0下可以使用的eclipse下载地址
  • Oracle事务!使用游标提交过程
  • 在Jbuilder7下,使用DbPilot.exe连接oracle,报错!请教高手!
  • AIX 64位系统上如何使用32位OCI oracle driver
  • Oracle中SQL语句连接字符串的符号使用介绍
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 浅析Oracle中char和varchar2的区别
  • oracle to_char函数将number转成string
  • 关于jsp连接oracle char类型数据显示问题
  • Oracle中CHAR类型自动补足空格的问题解决
  • Oracle to_char 日期转换字符串语句分享
  • Oracle to_char函数的使用方法
  • Oracle 12c发布简单介绍及官方下载地址
  • 在linux下安装oracle,如何设置让oracle自动启动!也就是让oracle那个服务自动启动,不是手动的
  • oracle 11g最新版官方下载地址
  • 请问su oracle 和su - oracle有什么不同?
  • Oracle 数据库(oracle Database)Select 多表关联查询方式
  • 虚拟机装Oracle R12与Oracle10g
  • Oracle数据库(Oracle Database)体系结构及基本组成介绍
  • Oracle 数据库开发工具 Oracle SQL Developer
  • 如何设置让Oracle SQL Developer显示的时间包含时分秒
  • Oracle EBS R12 支持 Oracle Database 11g
  • Oracle 10g和Oracle 11g网格技术介绍
  • SCO unix下安装oracle,但没有光盘,请大家推荐一个oracle下载站点(unix版本的)。谢谢!!!!
  • oracle中如何把表中具有相同值列的多行数据合并成一行
  • 请问大家用oracle数据库, 用import oracle.*;下的东西么? 还是用标准库?
  • Oracle 数据库(oracle Database)性能调优技术详解
  • Linux /$ORACLE_HOME $ORACLE_HOME
  • ORACLE日期相关操作
  • Linux系统下Oracle的启动与Oracle监听的启动
  • Oracle 12c的九大最新技术特性介绍
  • 请问在solaris下安装ORACLE,用root用户和用oracle用户安装有什么区别么?
  • ORACLE中DBMS_RANDOM随机数生成包
  • 网间Oracle的连接,远程连接Oracle服务器??


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    HTML教程 iis7站长之家