电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

詳解mysql三值邏輯與NULL

瀏覽:19日期:2023-10-02 18:08:31
目錄什么是NULL兩種 NULL為什么必須寫成“IS NULL”,而不是“= NULL”三值邏輯三值邏輯的邏輯值表“IS NULL” 而非 “= NULL”溫柔的陷阱比較謂詞和 NULLNOT IN 和 NOT EXISTS 不是等價的總結(jié)什么是NULL

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

兩種 NULL

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

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

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

詳解mysql三值邏輯與NULL

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

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

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 這種叫法本身是不對的,只是我們?nèi)粘V幸呀?jīng)叫習(xí)慣了,具體往下看),怎么查,很多新手會寫出這樣的 SQL

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

詳解mysql三值邏輯與NULL

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

三值邏輯

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

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

-- 這個是明確的邏輯值的比較unknown = unknown → true-- 這個相當(dāng)于NULL = NULLUNKNOWN = UNKNOWN → unknown三值邏輯的邏輯值表

NOT

詳解mysql三值邏輯與NULL

AND

詳解mysql三值邏輯與NULL

OR

詳解mysql三值邏輯與NULL

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

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

AND 的情況:false > unknown > true

OR 的情況:true > unknown > false

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

-- 假設(shè) a = 2, b = 5, c = NULL,下列表達(dá)式的邏輯值如下a < b AND b > c → unknowna > b OR b < c → unknowna < b OR b < c → trueNOT (b <> c) → unknown“IS NULL” 而非 “= NULL”

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

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

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

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

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

溫柔的陷阱比較謂詞和 NULL

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

假設(shè)我們有學(xué)生表: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 ’學(xué)生信息’;INSERT INTO t_student(name, age)VALUE(’zhangsan’, 25),(’wangwu’, 60),(’bruce’, 32),(’yzb’, NULL),(’boss’, 18);SELECT * FROM t_student;

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

SELECT * FROM t_studentWHERE age = 20 OR age <> 20;

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

詳解mysql三值邏輯與NULL

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

-- 1. 約翰年齡是 NULL (未知的 NULL !)SELECT *FROM t_studentWHERE age = NULLOR age <> NULL;-- 2. 對 NULL 使用比較謂詞后,結(jié)果為unknownSELECT *FROM t_studentWHERE unknownOR unknown;-- 3.unknown OR unknown 的結(jié)果是unknown (參考三值邏輯的邏輯值表)SELECT *FROM t_studentWHERE unknown;

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

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

CASE 表達(dá)式和 NULL

簡單 CASE 表達(dá)式如下

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

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

CASE WHEN col_1 = 1 THEN ’o’ WHEN col_1 IS NULL THEN ’x’ENDNOT IN 和 NOT EXISTS 不是等價的

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

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

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 ’學(xué)生信息’;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 ’學(xué)生信息’;INSERT INTO t_student_B(name, age, city)VALUE(’馬化騰’, 45, ’深圳市’),(’馬三’, 25, ’深圳市’),(’馬云’, 43, ’杭州市’),(’李彥宏’, 41, ’深圳市’),(’年輕人’, 25, ’深圳市’); * FROM t_student_B;

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

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

我們來看下執(zhí)行結(jié)果

詳解mysql三值邏輯與NULL

我們發(fā)現(xiàn)結(jié)果是空,查詢不到任何數(shù)據(jù),這是為什么了 ?這里 NULL 又開始作怪了,我們一步一步來看看究竟發(fā)生了什么

-- 1. 執(zhí)行子查詢,獲取年齡列表SELECT * FROM t_studentWHERE age NOT IN(43, NULL, 25);-- 2. 用NOT 和IN 等價改寫NOT INSELECT * FROM t_studentWHERE NOT age IN (43, NULL, 25);-- 3. 用OR 等價改寫謂詞INSELECT * FROM t_studentWHERE NOT ( (age = 43) OR (age = NULL) OR (age = 25) );-- 4. 使用德· 摩根定律等價改寫SELECT * FROM t_studentWHERE NOT (age = 43) AND NOT(age = NULL) AND NOT (age = 25);-- 5. 用<> 等價改寫 NOT 和 =SELECT * FROM t_studentWHERE (age <> 43) AND (age <> NULL) AND (age <> 25);-- 6. 對NULL 使用<> 后,結(jié)果為 unknownSELECT * FROM t_studentWHERE (age <> 43) AND unknown AND (age <> 25);-- 7.如果 AND 運算里包含 unknown,則結(jié)果不為true(參考三值邏輯的邏輯值表)SELECT * FROM t_studentWHERE false 或 unknown;

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

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

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

執(zhí)行結(jié)果如下

詳解mysql三值邏輯與NULL

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

-- 1. 在子查詢里和 NULL 進行比較運算,此時 A.age 是 NULLSELECT * FROM t_student_B BWHERE NOT EXISTS ( SELECT * FROM t_student_A A WHERE B.age = NULL AND A.city = ’深圳市’ );-- 2. 對NULL 使用“=”后,結(jié)果為 unknownSELECT * FROM t_student_B BWHERE NOT EXISTS ( SELECT * FROM t_student_A A WHERE unknown AND A.city = ’深圳市’ );-- 3. 如果AND 運算里包含 unknown,結(jié)果不會是trueSELECT * FROM t_student_B BWHERE NOT EXISTS ( SELECT * FROM t_student_A A WHERE false 或 unknown);-- 4. 子查詢沒有返回結(jié)果,因此相反地,NOT EXISTS 為 trueSELECT * FROM t_student_B BWHERE true;

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

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

總結(jié)

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

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

以上就是詳解mysql三值邏輯與NULL的詳細(xì)內(nèi)容,更多關(guān)于mysql三值邏輯與NULL的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: MySQL 數(shù)據(jù)庫
相關(guān)文章:
主站蜘蛛池模板: 橡胶接头_橡胶软接头_套管伸缩器_管道伸缩器厂家-巩义市远大供水材料有限公司 | 交变/复合盐雾试验箱-高低温冲击试验箱_安奈设备产品供应杭州/江苏南京/安徽马鞍山合肥等全国各地 | 菲希尔X射线测厚仪-菲希尔库伦法测厚仪-无锡骏展仪器有限责任公司 | 微动开关厂家-东莞市德沃电子科技有限公司 | VOC检测仪-甲醛检测仪-气体报警器-气体检测仪厂家-深恒安科技有限公司 | 酒糟烘干机-豆渣烘干机-薯渣烘干机-糟渣烘干设备厂家-焦作市真节能环保设备科技有限公司 | 低气压试验箱_高低温低气压试验箱_低气压实验箱 |林频试验设备品牌 | IHDW_TOSOKU_NEMICON_EHDW系列电子手轮,HC1系列电子手轮-上海莆林电子设备有限公司 | 南京展台搭建-南京展会设计-南京展览设计公司-南京展厅展示设计-南京汇雅展览工程有限公司 | Dataforth隔离信号调理模块-信号放大模块-加速度振动传感器-北京康泰电子有限公司 | 德国UST优斯特氢气检漏仪-德国舒赐乙烷检测仪-北京泽钏 | 钢绞线万能材料试验机-全自动恒应力两用机-混凝土恒应力压力试验机-北京科达京威科技发展有限公司 | 高精度-恒温冷水机-螺杆式冰水机-蒸发冷冷水机-北京蓝海神骏科技有限公司 | 爆破器材运输车|烟花爆竹运输车|1-9类危险品厢式运输车|湖北江南专用特种汽车有限公司 | LNG鹤管_内浮盘价格,上装鹤管,装车撬厂家-连云港赛威特机械 | 阴离子聚丙烯酰胺价格_PAM_高分子聚丙烯酰胺厂家-河南泰航净水材料有限公司 | 无菌实验室规划装修设计-一体化实验室承包-北京洁净净化工程建设施工-北京航天科恩实验室装备工程技术有限公司 | 浙江筋膜枪-按摩仪厂家-制造商-肩颈按摩仪哪家好-温州市合喜电子科技有限公司 | 翰墨AI智能写作助手官网_人工智能问答在线AI写作免费一键生成 | 斗式提升机,斗式提升机厂家-淄博宏建机械有限公司| 达利园物流科技集团- | 安全阀_弹簧式安全阀_美标安全阀_工业冷冻安全阀厂家-中国·阿司米阀门有限公司 | 车间除尘设备,VOCs废气处理,工业涂装流水线,伸缩式喷漆房,自动喷砂房,沸石转轮浓缩吸附,机器人喷粉线-山东创杰智慧 | 液压扳手-高品质液压扳手供应商 - 液压扳手, 液压扳手供应商, 德国进口液压拉马 | 大型果蔬切片机-水果冬瓜削皮机-洗菜机切菜机-肇庆市凤翔餐饮设备有限公司 | 球形钽粉_球形钨粉_纳米粉末_难熔金属粉末-广东银纳官网 | 球磨机,节能球磨机价格,水泥球磨机厂家,粉煤灰球磨机-吉宏机械制造有限公司 | 东莞猎头公司_深圳猎头公司_广州猎头公司-广东万诚猎头提供企业中高端人才招聘服务 | 考勤系统_考勤管理系统_网络考勤软件_政企|集团|工厂复杂考勤工时统计排班管理系统_天时考勤 | 派克防爆伺服电机品牌|国产防爆伺服电机|高低温伺服电机|杭州摩森机电科技有限公司 | 河南不锈钢水箱_地埋水箱_镀锌板水箱_消防水箱厂家-河南联固供水设备有限公司 | 农业四情_农业气象站_田间小型气象站_智慧农业气象站-山东风途物联网 | 耙式干燥机_真空耙式干燥机厂家-无锡鹏茂化工装备有限公司 | 冷却塔减速机器_冷却塔皮带箱维修厂家_凉水塔风机电机更换-广东康明冷却塔厂家 | 香港新时代国际美容美发化妆美甲培训学校-26年培训经验,值得信赖! | 上海小程序开发-上海小程序制作公司-上海网站建设-公众号开发运营-软件外包公司-咏熠科技 | 活性炭-蜂窝-椰壳-柱状-粉状活性炭-河南唐达净水材料有限公司 | 威客电竞(vk·game)·电子竞技赛事官网 | 锥形螺带干燥机(新型耙式干燥机)百科-常州丰能干燥工程 | 二手Sciex液质联用仪-岛津气质联用仪-二手安捷伦气质联用仪-上海隐智科学仪器有限公司 | 济南ISO9000认证咨询代理公司,ISO9001认证,CMA实验室认证,ISO/TS16949认证,服务体系认证,资产管理体系认证,SC食品生产许可证- 济南创远企业管理咨询有限公司 郑州电线电缆厂家-防火|低压|低烟无卤电缆-河南明星电缆 |