婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 詳解mysql三值邏輯與NULL

詳解mysql三值邏輯與NULL

熱門標簽:400電話辦理服務價格最實惠 北京金倫外呼系統 400電話變更申請 武漢電銷機器人電話 大豐地圖標注app 呂梁外呼系統 html地圖標注并導航 催天下外呼系統 南太平洋地圖標注

什么是NULL

NULL 用于表示缺失的值或遺漏的未知數據,不是某種具體類型的值。數據表中的 NULL 值表示該值所處的字段為空,值為 NULL 的字段沒有值,尤其要明白的是:NULL 值與 0 或者空字符串是不同的。

兩種 NULL

這種說法大家可能會覺得很奇怪,因為 SQL 里只存在一種 NULL 。然而在討論 NULL 時,我們一般都會將它分成兩種類型來思考:“未知”(unknown)和“不適用”(not applicable,inapp licable)。

以“不知道戴墨鏡的人眼睛是什么顏色”這種情況為例,這個人的眼睛肯定是有顏色的,但是如果他不摘掉眼鏡,別人就不知道他的眼睛是什么顏色。這就叫作未知。而“不知道冰箱的眼睛是什么顏色”則屬于“不適用”。因為冰箱根本就沒有眼睛,所以“眼睛的顏色”這一屬性并不適用于冰箱。“冰箱的眼睛的顏色”這種說法和“圓的體積”“男性的分娩次數”一樣,都是沒有意義的。平時,我們習慣了說“不知道”,但是“不知道”也分很多種。“不適用”這種情況下的 NULL ,在語義上更接近于“無意義”,而不是“不確定”。這里總結一下:“未知”指的是“雖然現在不知道,但加上某些條件后就可以知道”;而“不適用”指的是“無論怎么努力都無法知道”。

關系模型的發明者 E.F. Codd 最先給出了這種分類。下圖是他對“丟失的信息”的分類

為什么必須寫成“IS NULL”,而不是“= NULL”

我相信不少人有這樣的困惑吧,尤其是相信剛學 SQL 的小伙伴。我們來看個具體的案例,假設我們有如下表以及數據

DROP TABLE IF EXISTS t_sample_null;
CREATE TABLE t_sample_null (
    id INT(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
    name VARCHAR(50) NOT NULL COMMENT '名稱',
    remark VARCHAR(500) COMMENT '備注',
    primary key(id)
) COMMENT 'NULL樣例';

INSERT INTO t_sample_null(name, remark)
VALUES('zhangsan', '張三'),('李四', NULL);

我們要查詢備注為 NULL 的記錄(為 NULL 這種叫法本身是不對的,只是我們日常中已經叫習慣了,具體往下看),怎么查,很多新手會寫出這樣的 SQL

-- SQL 不報錯,但查不出結果
SELECT * FROM t_sample_null WHERE remark = NULL;

執行時不報錯,但是查不出我們想要的結果, 這是為什么了 ?這個問題我們先放著,我們往下看

三值邏輯

這個三值邏輯不是三目運算,指的是三個邏輯值,有人可能有疑問了,邏輯值不是只有真(true)和假(false)嗎,哪來的第三個?說這話時我們需要注意所處的環境,在主流的編程語言中(C、JAVA、Python、JS等)中,邏輯值確實只有 2 個,但在 SQL 中卻存在第三個邏輯值:unknown。這有點類似于我們平時所說的:對、錯、不知道。

邏輯值 unknown 和作為 NULL 的一種的 UNKNOWN (未知)是不同的東西。前者是明確的布爾型的邏輯值,后者既不是值也不是變量。為了便于區分,前者采用小寫字母 unknown ,后者用大寫字母 UNKNOWN 來表示。為了讓大家理解兩者的不同,我們來看一個 x=x 這樣的簡單等式。x 是邏輯值 unknown 時,x=x 被判斷為 true ,而 x 是 UNKNOWN 時被判斷為 unknown

-- 這個是明確的邏輯值的比較
unknown = unknown → true

-- 這個相當于NULL = NULL
UNKNOWN = UNKNOWN → unknown

三值邏輯的邏輯值表

NOT

AND

OR

圖中藍色部分是三值邏輯中獨有的運算,這在二值邏輯中是沒有的。其余的 SQL 謂詞全部都能由這三個邏輯運算組合而來。從這個意義上講,這個幾個邏輯表可以說是 SQL 的母體(matrix)。

NOT 的話,因為邏輯值表比較簡單,所以很好記;但是對于 AND 和 OR,因為組合出來的邏輯值較多,所以全部記住非常困難。為了便于記憶,請注意這三個邏輯值之間有下面這樣的優先級順序。

AND 的情況:false > unknown > true

OR 的情況:true > unknown > false

優先級高的邏輯值會決定計算結果。例如 true AND unknown ,因為 unknown 的優先級更高,所以結果是 unknown 。而 true OR unknown 的話,因為 true 優先級更高,所以結果是 true 。記住這個順序后就能更方便地進行三值邏輯運算了。特別需要記住的是,當 AND 運算中包含 unknown 時,結果肯定不會是 true (反之,如果AND 運算結果為 true ,則參與運算的雙方必須都為 true )。

-- 假設 a = 2, b = 5, c = NULL,下列表達式的邏輯值如下

a  b AND b > c  → unknown
a > b OR b  c   → unknown
a  b OR b  c   → true
NOT (b > c)     → unknown

“IS NULL” 而非 “= NULL”

我們再回到問題:為什么必須寫成“IS NULL”,而不是“= NULL”

對 NULL 使用比較謂詞后得到的結果總是 unknown 。而查詢結果只會包含 WHERE 子句里的判斷結果為 true 的行,不會包含判斷結果為 false 和 unknown 的行。不只是等號,對 NULL 使用其他比較謂詞,結果也都是一樣的。所以無論 remark 是不是 NULL ,比較結果都是 unknown ,那么永遠沒有結果返回。以下的式子都會被判為 unknown

-- 以下的式子都會被判為 unknown
= NULL
> NULL
 NULL
> NULL
NULL = NULL

那么,為什么對 NULL 使用比較謂詞后得到的結果永遠不可能為真呢?這是因為,NULL 既不是值也不是變量。NULL 只是一個表示“沒有值”的標記,而比較謂詞只適用于值。因此,對并非值的 NULL 使用比較謂詞本來就是沒有意義的。“列的值為 NULL ”、“NULL 值” 這樣的說法本身就是錯誤的。因為 NULL不是值,所以不在定義域(domain)中。相反,如果有人認為 NULL 是值,那么我們可以倒過來想一下:它是什么類型的值?關系數據庫中存在的值必然屬于某種類型,比如字符型或數值型等。所以,假如 NULL 是值,那么它就必須屬于某種類型。

NULL 容易被認為是值的原因有兩個。第一個是高級編程語言里面,NULL 被定義為了一個常量(很多語言將其定義為了整數0),這導致了我們的混淆。但是,SQL 里的 NULL 和其他編程語言里的 NULL 是完全不同的東西。第二個原因是,IS NULL 這樣的謂詞是由兩個單詞構成的,所以我們容易把 IS 當作謂詞,而把 NULL 當作值。特別是 SQL 里還有 IS TRUE 、IS FALSE 這樣的謂詞,我們由此類推,從而這樣認為也不是沒有道理。但是正如講解標準 SQL 的書里提醒人們注意的那樣,我們應該把 IS NULL 看作是一個謂詞。因此,寫成 IS_NULL 這樣也許更合適。

溫柔的陷阱

比較謂詞和 NULL

排中律不成立排中律指同一個思維過程中,兩個相互矛盾的思想不能同假,必有一真,即“要么A要么非A”

假設我們有學生表:t_student

DROP TABLE IF EXISTS t_student;
CREATE TABLE t_student (
    id INT(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
    name VARCHAR(50) NOT NULL COMMENT '名稱',
    age INT(3) COMMENT '年齡',
    remark VARCHAR(500) NOT NULL DEFAULT '' COMMENT '備注',
    primary key(id)
) COMMENT '學生信息';

INSERT INTO t_student(name, age)
VALUE('zhangsan', 25),('wangwu', 60),('bruce', 32),('yzb', NULL),('boss', 18);

SELECT * FROM t_student;

表中數據 yzb 的 age 是 NULL,也就是說 yzb 的年齡未知。在現實世界里,yzb 是 20 歲,或者不是 20 歲,二者必居其一,這毫無疑問是一個真命題。那么在 SQL 的世界里了,排中律還適用嗎? 我們來看一個 SQL

SELECT * FROM t_student
WHERE age = 20 OR age > 20;

咋一看,這不就是查詢表中全部記錄嗎?我們來看下實際結果

yzb 沒查出來,這是為什么了?我們來分析下,yzb 的 age 是 NULL,那么這條記錄的判斷步驟如下

-- 1. 約翰年齡是 NULL (未知的 NULL !)
SELECT *
FROM t_student
WHERE age = NULL
OR age > NULL;

-- 2. 對 NULL 使用比較謂詞后,結果為unknown
SELECT *
FROM t_student
WHERE unknown
OR unknown;

-- 3.unknown OR unknown 的結果是unknown (參考三值邏輯的邏輯值表)
SELECT *
FROM t_student
WHERE unknown;

SQL 語句的查詢結果里只有判斷結果為 true 的行。要想讓 yzb 出現在結果里,需要添加下面這樣的 “第 3 個條件”

-- 添加 3 個條件:年齡是20 歲,或者不是20 歲,或者年齡未知
SELECT * FROM t_student
WHERE age = 20 
    OR age > 20
    OR age IS NULL;

CASE 表達式和 NULL

簡單 CASE 表達式如下

CASE col_1
    WHEN = 1 THEN 'o'
    WHEN NULL THEN 'x'
END

這個 CASE 表達式一定不會返回 ×。這是因為,第二個 WHEN 子句是 col_1 = NULL 的縮寫形式。正如我們所知,這個式子的邏輯值永遠是 unknown ,而且 CASE 表達式的判斷方法與 WHERE 子句一樣,只認可邏輯值為 true 的條件。正確的寫法是像下面這樣使用搜索 CASE 表達式

CASE WHEN col_1 = 1 THEN 'o'
    WHEN col_1 IS NULL THEN 'x'
END

NOT IN 和 NOT EXISTS 不是等價的

我們在對 SQL 語句進行性能優化時,經常用到的一個技巧是將 IN 改寫成 EXISTS ,這是等價改寫,并沒有什么問題。但是,將 NOT IN 改寫成 NOT EXISTS 時,結果未必一樣。

我們來看個例子,我們有如下兩張表:t_student_A 和 t_student_B,分別表示 A 班學生與 B 班學生

DROP TABLE IF EXISTS t_student_A;
CREATE TABLE t_student_A (
    id INT(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
    name VARCHAR(50) NOT NULL COMMENT '名稱',
    age INT(3) COMMENT '年齡',
    city VARCHAR(50) NOT NULL COMMENT '城市',
    remark VARCHAR(500) NOT NULL DEFAULT '' COMMENT '備注',
    primary key(id)
) COMMENT '學生信息';

INSERT INTO t_student_A(name, age, city)
VALUE
('zhangsan', 25,'深圳市'),('wangwu', 60, '廣州市'),
('bruce', 32, '北京市'),('yzb', NULL, '深圳市'),
('boss', 43, '深圳市');

DROP TABLE IF EXISTS t_student_B;
CREATE TABLE t_student_B (
    id INT(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
    name VARCHAR(50) NOT NULL COMMENT '名稱',
    age INT(3) COMMENT '年齡',
    city VARCHAR(50) NOT NULL COMMENT '城市',
    remark VARCHAR(500) NOT NULL DEFAULT '' COMMENT '備注',
    primary key(id)
) COMMENT '學生信息';

INSERT INTO t_student_B(name, age, city)
VALUE
('馬化騰', 45, '深圳市'),('馬三', 25, '深圳市'),
('馬云', 43, '杭州市'),('李彥宏', 41, '深圳市'),
('年輕人', 25, '深圳市');

 * FROM t_student_B;

需求:查詢與 A 班住在深圳的學生年齡不同的 B 班學生,也就說查詢出 :馬化騰 和 李彥宏,這個 SQL 該如何寫,像這樣?

-- 查詢與 A  班住在深圳的學生年齡不同的 B 班學生 ?
SELECT * FROM t_student_B
WHERE age NOT IN (
    SELECT age FROM t_student_A 
    WHERE city = '深圳市'
);

我們來看下執行結果

我們發現結果是空,查詢不到任何數據,這是為什么了 ?這里 NULL 又開始作怪了,我們一步一步來看看究竟發生了什么

-- 1. 執行子查詢,獲取年齡列表
SELECT * FROM t_student
WHERE age NOT IN(43, NULL, 25);

-- 2. 用NOT 和IN 等價改寫NOT IN
SELECT * FROM t_student
WHERE NOT age IN (43, NULL, 25);

-- 3. 用OR 等價改寫謂詞IN
SELECT * FROM t_student
WHERE NOT ( (age = 43) OR (age = NULL) OR (age = 25) );

-- 4. 使用德· 摩根定律等價改寫
SELECT * FROM t_student
WHERE NOT (age = 43) AND NOT(age = NULL) AND NOT (age = 25);

-- 5. 用> 等價改寫 NOT 和 =
SELECT * FROM t_student
WHERE (age > 43) AND (age > NULL) AND (age > 25);

-- 6. 對NULL 使用> 后,結果為 unknown
SELECT * FROM t_student
WHERE (age > 43) AND unknown AND (age > 25);

-- 7.如果 AND 運算里包含 unknown,則結果不為true(參考三值邏輯的邏輯值表)
SELECT * FROM t_student
WHERE false 或 unknown;

可以看出,在進行了一系列的轉換后,沒有一條記錄在 WHERE 子句里被判斷為 true 。也就是說,如果 NOT IN 子查詢中用到的表里被選擇的列中存在 NULL ,則 SQL 語句整體的查詢結果永遠是空。這是很可怕的現象!

為了得到正確的結果,我們需要使用 EXISTS 謂詞

-- 正確的SQL 語句:馬化騰和李彥宏將被查詢到
SELECT * FROM t_student_B B
WHERE NOT EXISTS ( 
    SELECT * FROM t_student_A A
    WHERE B.age = A.age
    AND A.city = '深圳市' 
);

執行結果如下

同樣地,我們再來一步一步地看看這段 SQL 是如何處理年齡為 NULL 的行的

-- 1. 在子查詢里和 NULL 進行比較運算,此時 A.age 是 NULL
SELECT * FROM t_student_B B
WHERE NOT EXISTS (
    SELECT * FROM t_student_A A
    WHERE B.age = NULL
    AND A.city = '深圳市' 
);

-- 2. 對NULL 使用“=”后,結果為 unknown
SELECT * FROM t_student_B B
WHERE NOT EXISTS (
    SELECT * FROM t_student_A A
    WHERE unknown
    AND A.city = '深圳市' 
);

-- 3. 如果AND 運算里包含 unknown,結果不會是true
SELECT * FROM t_student_B B
WHERE NOT EXISTS (
    SELECT * FROM t_student_A A
    WHERE false 或 unknown
);

-- 4. 子查詢沒有返回結果,因此相反地,NOT EXISTS 為 true
SELECT * FROM t_student_B B
WHERE true;

也就是說,yzb 被作為 “與任何人的年齡都不同的人” 來處理了。EXISTS 只會返回 true 或者false,永遠不會返回 unknown。因此就有了 IN 和 EXISTS 可以互相替換使用,而 NOT IN和 NOT EXISTS 卻不可以互相替換的混亂現象。

還有一些其他的陷阱,比如:限定謂詞和 NULL、限定謂詞和極值函數不是等價的、聚合函數和 NULL 等等。

總結

1、NULL 用于表示缺失的值或遺漏的未知數據,不是某種具體類型的值,不能對其使用謂

2、對 NULL 使用謂詞后的結果是 unknown,unknown 參與到邏輯運算時,SQL 的運行會和預想的不一樣3、 IS NULL 整個是一個謂詞,而不是:IS 是謂詞,NULL 是值;類似的還有 IS TRUE、IS FALSE4、要想解決 NULL 帶來的各種問題,最佳方法應該是往表里添加 NOT NULL 約束來盡力排除 NULL

以上就是詳解mysql三值邏輯與NULL的詳細內容,更多關于mysql三值邏輯與NULL的資料請關注腳本之家其它相關文章!

您可能感興趣的文章:
  • 為什么mysql字段要使用NOT NULL
  • MySQL中關于null值的一個小問題
  • MySQL null的一些易錯點
  • MySQL null與not null和null與空值''''''''的區別詳解
  • MySQL IFNULL判空問題解決方案
  • 區分MySQL中的空值(null)和空字符('''')
  • 詳解mysql不等于null和等于null的寫法
  • Mysql NULL導致的神坑
  • mysql中null(IFNULL,COALESCE和NULLIF)相關知識點總結

標簽:西寧 無錫 龍巖 自貢 麗水 徐州 迪慶 南充

巨人網絡通訊聲明:本文標題《詳解mysql三值邏輯與NULL》,本文關鍵詞  詳解,mysql,三值,邏輯,與,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《詳解mysql三值邏輯與NULL》相關的同類信息!
  • 本頁收集關于詳解mysql三值邏輯與NULL的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    精品日韩一区二区三区| 欧美自拍偷拍一区| 另类小说欧美激情| 免费观看成人av| 欧美aaaaa成人免费观看视频| 午夜一区二区三区视频| 亚洲午夜激情网站| 日韩av不卡在线观看| 日本不卡1234视频| 久久99国产精品尤物| 国产成人在线视频网站| 99久久综合色| 色网站国产精品| 欧美丰满美乳xxx高潮www| 日韩视频一区二区三区在线播放| 久久亚洲精品国产精品紫薇| 国产亚洲成年网址在线观看| 亚洲日本一区二区| 丝袜亚洲另类欧美| 国产精品一二三在| 欧洲精品在线观看| 精品国精品国产| 亚洲丝袜美腿综合| 美女网站一区二区| 91亚洲国产成人精品一区二区三 | 91在线视频免费91| 欧美日本不卡视频| 欧美精品一区二区三区蜜臀| 中文字幕亚洲一区二区va在线| 亚洲成人在线网站| 国产精品一二三区| 欧美丰满少妇xxxbbb| 中文字幕不卡在线播放| 天堂一区二区在线免费观看| 国产aⅴ综合色| 91精品国产91久久综合桃花| 国产欧美日韩三区| 热久久国产精品| 色综合久久综合中文综合网| 日韩欧美一区电影| 亚洲6080在线| 91色九色蝌蚪| 国产亚洲欧美中文| 久久99久久精品| 欧美精品一二三区| 亚洲美女少妇撒尿| 成人福利在线看| 久久综合久久综合久久| 亚洲午夜在线电影| 99riav一区二区三区| 久久精品一区二区三区不卡| 免费av网站大全久久| 在线视频你懂得一区| 国产女人水真多18毛片18精品视频| 美女一区二区三区| 6080午夜不卡| 香港成人在线视频| 欧美日韩国产一级| 亚洲成a人在线观看| 色偷偷久久人人79超碰人人澡| 国产精品三级视频| 粉嫩av一区二区三区在线播放| 精品国产免费一区二区三区四区| 人人狠狠综合久久亚洲| 日韩一区二区三| 久久精品久久精品| 日韩女优毛片在线| 精品亚洲国内自在自线福利| 日韩午夜激情电影| 久久精品国产99| 久久男人中文字幕资源站| 韩国精品在线观看| 国产亚洲综合av| 国产不卡在线播放| ...xxx性欧美| 在线一区二区视频| 手机精品视频在线观看| 日韩欧美高清在线| 精东粉嫩av免费一区二区三区| 精品国产乱码久久| 国产成人日日夜夜| 亚洲免费在线视频一区 二区| 91麻豆国产自产在线观看| 一区二区三区久久久| 7777精品伊人久久久大香线蕉 | 日韩精品资源二区在线| 久久99国内精品| 欧美激情一区在线| 91视频国产资源| 午夜精品福利在线| 亚洲精品一区在线观看| 99精品视频中文字幕| 首页欧美精品中文字幕| 337p粉嫩大胆色噜噜噜噜亚洲| 粉嫩久久99精品久久久久久夜| 亚洲精品久久久蜜桃| 制服丝袜亚洲色图| av一区二区三区四区| 日韩成人dvd| 国产精品乱人伦| 欧美日韩成人综合天天影院| 国产精品一区二区果冻传媒| 一区二区三区国产豹纹内裤在线| 制服丝袜一区二区三区| 成人精品鲁一区一区二区| 亚洲五月六月丁香激情| 久久久久久久久久久电影| 在线免费不卡视频| 国产盗摄一区二区| 性欧美疯狂xxxxbbbb| 国产精品久久久久影院色老大| 欧美一区二区三区播放老司机| 成人午夜免费视频| 日韩精品成人一区二区在线| **性色生活片久久毛片| 精品久久久久久无| 欧美视频在线观看一区二区| 岛国一区二区三区| 麻豆91免费观看| 亚洲国产美女搞黄色| 国产精品天美传媒沈樵| 精品久久一区二区| 欧美区视频在线观看| 97精品电影院| 丰满亚洲少妇av| 狠狠色丁香婷综合久久| 婷婷综合另类小说色区| 一区二区三区美女| 一区二区欧美在线观看| 国产精品国产三级国产三级人妇| 欧美成人高清电影在线| 在线不卡一区二区| 欧美日本在线一区| 91久久一区二区| 91精品1区2区| 色94色欧美sute亚洲线路一久| 99国产精品久久久久| av综合在线播放| bt7086福利一区国产| www.欧美日韩国产在线| av在线不卡免费看| 97se亚洲国产综合自在线不卡| 国产不卡一区视频| 粉嫩一区二区三区在线看| 国产成人免费xxxxxxxx| 岛国精品在线观看| 99热精品国产| 91麻豆免费在线观看| 91福利视频网站| 欧美久久久一区| 精品少妇一区二区三区免费观看| 2欧美一区二区三区在线观看视频| www国产成人| 国产精品家庭影院| 亚洲中国最大av网站| 天天亚洲美女在线视频| 久久精品国产成人一区二区三区| 国产一区二区免费在线| 成人网男人的天堂| 色94色欧美sute亚洲13| 91精品国产综合久久久久久久久久 | 国产精品资源在线看| 成人免费看黄yyy456| 99精品国产99久久久久久白柏| 欧美曰成人黄网| 欧美电视剧免费观看| 国产精品人妖ts系列视频| 亚洲最色的网站| 麻豆精品一区二区三区| 不卡一区二区三区四区| 欧美色视频在线观看| 欧美成人精精品一区二区频| 国产精品护士白丝一区av| 亚洲成人精品一区| 国产成人午夜精品5599| 精品视频一区 二区 三区| 久久亚洲捆绑美女| 亚洲电影第三页| 国产不卡视频在线观看| 欧美人妖巨大在线| 国产精品丝袜91| 免费久久精品视频| 99精品视频一区| 欧美精品一区视频| 亚洲国产成人精品视频| 成人毛片视频在线观看| 日韩欧美中文一区二区| 亚洲精品乱码久久久久久久久| 久草在线在线精品观看| 在线欧美一区二区| 中文一区二区完整视频在线观看| 日韩和欧美一区二区三区| 不卡在线观看av| 久久久噜噜噜久久人人看| 亚洲国产aⅴ天堂久久| www.成人网.com| 久久久久久一级片| 奇米精品一区二区三区在线观看 | 美女网站色91| 欧美日韩在线电影|