最近在阅读代码是,发现以前很多代码中,很多地方都用到了 char 类型的字符变量,今天看了相关资料,发现char类型有很多不方便
地方,总结下:
1.char变量是固定长度的变量,不足的空间会用空格填充,而varchar2是变长变量,可以根据变量具体的值来确定长度,这样显而易见
char会占据更多的空间;
2.char定义的变量或字段,在使用时要注意很多地方,很麻烦,稍不注意就会弄错,尤其在绑定变量的使用。
举个例:
1)建表t
CREATE TABLE t
(char_col CHAR(10),varchar_col VARCHAR2(10));
2)2个字段都插入‘优快云’值
INSERT INTO t (char_col,varchar_col)
VALUES ('优快云','优快云');
3)看下每个字段值得长度,可以看到同样的值‘CSND’,一个长度为10,一个长度为4
4)在看用固定值查询的时候,发现直接用char_col=‘CSND’能够查询到记录,用char_col='优快云 '也能查询到记录!!(后面随便多少个空格),这说明在比较前,肯定进行了隐式
转换。
5)我们知道,如果函数索引列上如果发生了隐式转换的话,这列上的索引将不会被优化器采用,你肯定会以为如果我在char_col建索引,这个索引将不会被使用,
但实际情况却不是这样的
t表插入值
INSERT INTO t
SELECT SUBSTR(o.OBJECT_NAME,1,5),SUBSTR(o.OBJECT_NAME,1,5)
FROM dba_objects o;
char_col列建索引
CREATE INDEX t_n1 ON t (char_col);
表分析
BEGIN
dbms_stats.gather_table_stats('ORACLE','T',cascade => TRUE);
END;
执行查询看执行计划,竟然使用了索引!我猜测, 在给char_col建索引时oracle可能自动建的是类似trim(char_col)这样的函数索引,而在sql查询的时候,
首先对char_col=‘CSND’等号两边加了trim,即:trim(char_col)=trim(‘CSND’),这样就能解释上面为什么等号右边随便多少个空格,都能查询到记录和能够
使用到索引的疑问,不过这仅仅是我自己的猜测
6)扯远了,回来再看下char对绑定变量的应用,你会发现情况又变得跟上面的分析不同了
DECLARE
a VARCHAR2(10);
b VARCHAR2(10);
BEGIN
a := 'I_IND';
SELECT t.char_col INTO b FROM t WHERE t.char_col=a;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('no_data_found');
END;
输出结果为:
这下你可能头都大了,输入固定值可以查询出来的sql,换成绑定变量就查不出来了!!所以嘛,为了自己也为了不贻害后人,不要再用char了,用varchar2多好!!