今天在论坛看到一个比较有趣的问题:’AA ’和’AA’是否相等。其中第一个字符串中包含一个空格。
有人认为二者不相等,也有人认为二者相等。其实无论哪种说法都是对的。
首先通过SQL证明二者不相等:
SQL> SELECT DECODE(‘AA ‘, ‘AA‘, ‘=‘, ‘!=‘) FROM DUAL;
DE
--
!=
下面证明二者相等:
SQL> SELECT CASE WHEN ‘AA ‘ = ‘AA‘ THEN ‘=‘ ELSE ‘!=‘ END FROM DUAL;
CA
--
=
为什么DECODE和CASE得到的结果不一样呢,到底’AA ’和’AA’是否相等呢,这个要从ORACLE的数据类型说起。
Oracle表示字符串有两种常用类型,定长的CHAR类型和变长的VARCHAR2类型。
比较是否相等,首先要确定数据类型:
对于VARCHAR2类型,二者显然是不等的。一个长度是3,另一个长度是2。
而对于CHAR类型,二者确实是相等的,因此Oracle会自动用空格去补齐位数。所以说讨论’AA ’和’AA’是否相等,首先要确定数据类型。
下面说明DECODE和CASE为什么得到不同的结果。
首先明确一点:DECODE是函数,而CASE是Oracle提供的SQL语句。
SQL> SELECT DUMP(‘AA ‘), DUMP(‘AA‘) FROM DUAL;
DUMP(‘AA‘) DUMP(‘AA‘)
---------------------- -------------------
Typ=96 Len=3: 65,65,32 Typ=96 Len=2: 65,65
Oracle会自动认为字符串常量为CHAR类型(type96为char类型)。因此,在CASE语句中,比较的是两个CHAR类型的字符串,因此得到相等的结果。
如果强制将其转化为VARCHAR2类型,则会得到不等的结果:
SQL> SELECT CASE WHEN CAST(‘AA ‘ AS VARCHAR2(3)) = CAST(‘AA‘ AS VARCHAR2(3))
2 THEN ‘=‘ ELSE ‘!=‘ END FROM DUAL;
CA
--
!=
既然默认是CHAR类型,为什么DECODE可以得到不等的结果呢:
SQL> DESC SYS.STANDARD
.
.
.
FUNCTION DECODE RETURNS NUMBER
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
EXPR NUMBER IN
PAT NUMBER IN
RES NUMBER IN
FUNCTION DECODE RETURNS VARCHAR2
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
EXPR NUMBER IN
PAT NUMBER IN
RES VARCHAR2 IN
FUNCTION DECODE RETURNS DATE
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
EXPR NUMBER IN
PAT NUMBER IN
RES DATE IN
FUNCTION DECODE RETURNS NUMBER
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
EXPR VARCHAR2 IN
PAT VARCHAR2 IN
RES NUMBER IN
FUNCTION DECODE RETURNS VARCHAR2
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
EXPR VARCHAR2 IN
PAT VARCHAR2 IN
RES VARCHAR2 IN
FUNCTION DECODE RETURNS DATE
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
EXPR VARCHAR2 IN
PAT VARCHAR2 IN
RES DATE IN
FUNCTION DECODE RETURNS NUMBER
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
EXPR DATE IN
PAT DATE IN
RES NUMBER IN
FUNCTION DECODE RETURNS VARCHAR2
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
EXPR DATE IN
PAT DATE IN
RES VARCHAR2 IN
FUNCTION DECODE RETURNS DATE
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
EXPR DATE IN
PAT DATE IN
RES DATE IN
FUNCTION DECODE RETURNS STANDARD
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
EXPR STANDARD IN
PAT STANDARD IN
RES STANDARD IN
FUNCTION DECODE RETURNS STANDARD
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
EXPR STANDARD IN
PAT STANDARD IN
RES STANDARD IN
.
.
.
通过查询标准包中DECODE函数的定义,发现DECODE函数的输入字符串类型统一为VARCHAR2,而不包含CHAR类型的重载。因此,在传递给DECODE函数前,两个CHAR类型已经转化为VARCHAR2类型,最终比较的是两个VARCHAR2类型,因此得到不等的结果。
类似的方法,如果将’AA’转化为CHAR(3)类型,那么DECODE函数也可以得到相等的结果:
SQL> SELECT DECODE(‘AA ‘, CAST(‘AA‘ AS CHAR(3)), ‘=‘, ‘!=‘) FROM DUAL;
DE
--
=
联系客服