从执行计划上,我们看不出什么过多的端倪。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