1,、SQL中的bool類型的值有三種普通編程語言里的布爾型只有 true 和 false 兩個(gè)值,,這種邏輯體系被稱為二值邏輯。而 SQL 語言里,,除此之外還有第三個(gè)值 unknown ,,因此這種邏輯體系被稱為三值邏輯(three-valued logic)。 2,、null不是值,,與數(shù)學(xué)運(yùn)算符結(jié)果的結(jié)果永遠(yuǎn)是unknown常聽到的“列的值為 NULL ” ,、“NULL 值”這樣的說法本身就是錯(cuò)誤的。因?yàn)?NULL 不是值,,NULL 不是值NULL 不是值?。ㄈ绻腥苏J(rèn)為 NULL 是值,那么它是什么類型的值,?關(guān)系數(shù)據(jù)庫(kù)中存在的值必然屬于某種類型,,比如字符型或數(shù)值型等。所以,,假如 NULL 是值,,那么它就必須屬于某種類型。) 另外,,注意:要想和null比較只能用 is null 或者 is not null,,這樣才會(huì)返回true或者false。另外永遠(yuǎn)記住一點(diǎn),,null和<,<,=,<>這些放在一起結(jié)果永遠(yuǎn)是unknown,,如 2=null,結(jié)果肯定是unknown,,而unknown可在三值邏輯中不是true或者false,,在寫where子句的篩選條件時(shí)尤其要注意。舉例來講:
接下來我們總結(jié)一下 SQL 遵循的三值邏輯的真值規(guī)律(理解下面這些非常重要),。 先看下圖:(t:true,f:false,u:unknown,。not unknown 的結(jié)果是 unknown)
我們經(jīng)常會(huì)遇到判斷篩選條件的結(jié)果(為true/false/unknown的一種,且SQL只會(huì)取返回結(jié)果是true的記錄),,它們通常是and 或or連接這些單個(gè)條件的,,如:where age>18 and sex=0或where age<18 and sex =unknown。所以我們要牢牢記住上面這個(gè)圖,,才能對(duì)各種情況下返回的數(shù)據(jù)心里有底,。 記憶方式1: and運(yùn)算,只要有一邊是unknown,,另一邊是false,,那結(jié)果就是false,其它情況下,,只要任意一邊有unknown,,結(jié)果就是unknown。 or運(yùn)算,,只要一邊是unknown,,那么結(jié)果永遠(yuǎn)就是unknown 記憶方式2: 在判斷and或or的最終結(jié)果時(shí),請(qǐng)注意true/false/unknown之間有下面這樣的優(yōu)先級(jí)順序,。 優(yōu)先級(jí)高的真值會(huì)決定計(jì)算結(jié)果,。例如 true AND unknown ,因?yàn)?unknown 的優(yōu)先級(jí)更高,,所以結(jié)果是 unknown ,。而 true OR unknown 的話,因?yàn)?true 優(yōu)先級(jí)更高,,所以結(jié)果是 true ,。記住這個(gè)順序后就能更方便地進(jìn)行三值邏輯運(yùn)算了。特別需要記住的是,,當(dāng) AND 運(yùn)算中包含 unknown 時(shí),,結(jié)果肯定不會(huì)是 true (反之,如果 AND 運(yùn)算結(jié)果為 true ,,則參與運(yùn)算的雙方必須都為 true ),。這一點(diǎn)對(duì)理解后文非常關(guān)鍵。 3,、NOT IN 和 NOT EXISTS 不是等價(jià)的如果 NOT IN 子查詢中用到的表里被選擇的列中存在 NULL ,,則 SQL 語句整體的查詢結(jié)果永遠(yuǎn)是空。EXISTS 謂詞永遠(yuǎn)不會(huì)返回 unknown ,。EXISTS 只會(huì)返回 true 或者 false ,。因此就有了 IN 和 EXISTS 可以互相替換使用,而 NOT IN 和 NOT EXISTS 卻不可以互相替換的混亂現(xiàn)象,。 4,、ALL 運(yùn)算符與null以下是ALL 運(yùn)算符語法: scalar_expression comparison_operator ALL ( subquery )
在上面語法中, scalar_expression 是任何有效的表達(dá)式,。
comparison_operator 是任何有效的比較運(yùn)算符,,包括等于(= ),不等于(<> ),,大于(> ),,大于或等于(>= ),小于(< ),,小于或等于(<= ),。
括號(hào)內(nèi)的子查詢(subquery )是一個(gè)SELECT語句,它返回單個(gè)列的結(jié)果,。 此外,,返回列的數(shù)據(jù)類型必須與標(biāo)量表達(dá)式的數(shù)據(jù)類型相同。
如果所有比較對(duì)(scalar_expression,,v) 的計(jì)算結(jié)果為TRUE ,,則ALL 運(yùn)算符返回TRUE ; v 是單列結(jié)果中的值。 如果其中一對(duì)(scalar_expression,,v) 返回FALSE ,,則ALL 運(yùn)算符返回FALSE ,。 如果all里面的子查詢返回的單列中有null的存在,那么這個(gè)all表達(dá)式就永遠(yuǎn)不會(huì)篩選出任何數(shù)據(jù),,結(jié)果肯定為空,。 因?yàn)锳LL 謂詞其實(shí)是多個(gè)以 AND 連接的邏輯表達(dá)式的省略寫法。
如果all里面的子查詢返回的單列中有null的存在,,比如子查詢結(jié)果如下面這個(gè)情況,,那么具體的分析步驟如下所示。 --1. 執(zhí)行子查詢獲取年齡列表
SELECT *
FROM Class_A
WHERE age < ALL ( 22, 23, NULL );
--2. 將ALL 謂詞等價(jià)改寫為AND
SELECT *
FROM Class_A
WHERE (age < 22) AND (age < 23) AND (age < NULL);
--3. 對(duì)NULL 使用“<”后,,結(jié)果變?yōu)?unknown
SELECT *
FROM Class_A
WHERE (age < 22) AND (age < 23) AND unknown;
--4. 如果AND 運(yùn)算里包含unknown,,則結(jié)果不為true
SELECT *
FROM Class_A
WHERE false 或 unknown;
--5.查詢結(jié)果為空
|