今天在論壇看到一個(gè)比較有趣的問題:’AA ’和’AA’是否相等。其中第一個(gè)字符串中包含一個(gè)空格。
有人認(rèn)為二者不相等,也有人認(rèn)為二者相等。其實(shí)無論哪種說法都是對的。
首先通過SQL證明二者不相等:
SQL> SELECT DECODE(‘AA ‘, ‘AA‘, ‘=‘, ‘!=‘) FROM DUAL;
DE
--
!=
下面證明二者相等:
SQL> SELECT CASE WHEN ‘AA ‘ = ‘AA‘ THEN ‘=‘ ELSE ‘!=‘ END FROM DUAL;
CA
--
=
為什么DECODE和CASE得到的結(jié)果不一樣呢,到底’AA ’和’AA’是否相等呢,這個(gè)要從ORACLE的數(shù)據(jù)類型說起。
Oracle表示字符串有兩種常用類型,定長的CHAR類型和變長的VARCHAR2類型。
比較是否相等,首先要確定數(shù)據(jù)類型:
對于VARCHAR2類型,二者顯然是不等的。一個(gè)長度是3,另一個(gè)長度是2。
而對于CHAR類型,二者確實(shí)是相等的,因此Oracle會(huì)自動(dòng)用空格去補(bǔ)齊位數(shù)。所以說討論’AA ’和’AA’是否相等,首先要確定數(shù)據(jù)類型。
下面說明DECODE和CASE為什么得到不同的結(jié)果。
首先明確一點(diǎn):DECODE是函數(shù),而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會(huì)自動(dòng)認(rèn)為字符串常量為CHAR類型(type96為char類型)。因此,在CASE語句中,比較的是兩個(gè)CHAR類型的字符串,因此得到相等的結(jié)果。
如果強(qiáng)制將其轉(zhuǎn)化為VARCHAR2類型,則會(huì)得到不等的結(jié)果:
SQL> SELECT CASE WHEN CAST(‘AA ‘ AS VARCHAR2(3)) = CAST(‘AA‘ AS VARCHAR2(3))
2 THEN ‘=‘ ELSE ‘!=‘ END FROM DUAL;
CA
--
!=
既然默認(rèn)是CHAR類型,為什么DECODE可以得到不等的結(jié)果呢:
SQL> DESC SYS.STANDARD
.
.
.
FUNCTION DECODE RETURNS NUMBER
參數(shù)名稱 類型 輸入/輸出默認(rèn)值?
------------------------------ ----------------------- ------ --------
EXPR NUMBER IN
PAT NUMBER IN
RES NUMBER IN
FUNCTION DECODE RETURNS VARCHAR2
參數(shù)名稱 類型 輸入/輸出默認(rèn)值?
------------------------------ ----------------------- ------ --------
EXPR NUMBER IN
PAT NUMBER IN
RES VARCHAR2 IN
FUNCTION DECODE RETURNS DATE
參數(shù)名稱 類型 輸入/輸出默認(rèn)值?
------------------------------ ----------------------- ------ --------
EXPR NUMBER IN
PAT NUMBER IN
RES DATE IN
FUNCTION DECODE RETURNS NUMBER
參數(shù)名稱 類型 輸入/輸出默認(rèn)值?
------------------------------ ----------------------- ------ --------
EXPR VARCHAR2 IN
PAT VARCHAR2 IN
RES NUMBER IN
FUNCTION DECODE RETURNS VARCHAR2
參數(shù)名稱 類型 輸入/輸出默認(rèn)值?
------------------------------ ----------------------- ------ --------
EXPR VARCHAR2 IN
PAT VARCHAR2 IN
RES VARCHAR2 IN
FUNCTION DECODE RETURNS DATE
參數(shù)名稱 類型 輸入/輸出默認(rèn)值?
------------------------------ ----------------------- ------ --------
EXPR VARCHAR2 IN
PAT VARCHAR2 IN
RES DATE IN
FUNCTION DECODE RETURNS NUMBER
參數(shù)名稱 類型 輸入/輸出默認(rèn)值?
------------------------------ ----------------------- ------ --------
EXPR DATE IN
PAT DATE IN
RES NUMBER IN
FUNCTION DECODE RETURNS VARCHAR2
參數(shù)名稱 類型 輸入/輸出默認(rèn)值?
------------------------------ ----------------------- ------ --------
EXPR DATE IN
PAT DATE IN
RES VARCHAR2 IN
FUNCTION DECODE RETURNS DATE
參數(shù)名稱 類型 輸入/輸出默認(rèn)值?
------------------------------ ----------------------- ------ --------
EXPR DATE IN
PAT DATE IN
RES DATE IN
FUNCTION DECODE RETURNS STANDARD
參數(shù)名稱 類型 輸入/輸出默認(rèn)值?
------------------------------ ----------------------- ------ --------
EXPR STANDARD IN
PAT STANDARD IN
RES STANDARD IN
FUNCTION DECODE RETURNS STANDARD
參數(shù)名稱 類型 輸入/輸出默認(rèn)值?
------------------------------ ----------------------- ------ --------
EXPR STANDARD IN
PAT STANDARD IN
RES STANDARD IN
.
.
.
通過查詢標(biāo)準(zhǔn)包中DECODE函數(shù)的定義,發(fā)現(xiàn)DECODE函數(shù)的輸入字符串類型統(tǒng)一為VARCHAR2,而不包含CHAR類型的重載。因此,在傳遞給DECODE函數(shù)前,兩個(gè)CHAR類型已經(jīng)轉(zhuǎn)化為VARCHAR2類型,最終比較的是兩個(gè)VARCHAR2類型,因此得到不等的結(jié)果。
類似的方法,如果將’AA’轉(zhuǎn)化為CHAR(3)類型,那么DECODE函數(shù)也可以得到相等的結(jié)果:
SQL> SELECT DECODE(‘AA ‘, CAST(‘AA‘ AS CHAR(3)), ‘=‘, ‘!=‘) FROM DUAL;
DE
--
=