国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > 綜合 > 正文

SQL Story摘錄(七)————觸摸NULL值

2024-07-21 02:09:04
字體:
供稿:網(wǎng)友

前面的文章中,我們初步見識了null這個不可思議的小東西。今天,我盡可能詳細(xì)的介紹一下它。依照慣例,這是一次盡量淺顯但并不嚴(yán)謹(jǐn)?shù)挠懻摚踔量赡軆?nèi)容也不那么嚴(yán)肅。我的目的在于幫助讀者更輕松地工作,并且有興趣對數(shù)據(jù)庫進(jìn)一步的學(xué)習(xí)。從另一方面講,我相信自己論點中的錯誤,肯定會有其他人也在犯,所以請發(fā)現(xiàn)不妥的朋友一定要公開指出。這樣,才有助于我和我的讀者朋友們進(jìn)步。衷心感謝每一個提出批評和指正的朋友,特別是公開提出批評和指正的朋友們。特別感謝sunshine19,專程發(fā)來e-mail,指出了《sql story》 的種種不足,并提出了寶貴意見。我期望他繼續(xù)關(guān)心這個專題,并期望他為我們帶來優(yōu)秀的作品。

無可回避的不存在

例:雙人房間。

假設(shè)某個學(xué)校,它的單身職工公寓中,每個房間有兩個床位。這樣做有很多好處,比如安全,都是半大不小的年輕人,不管男孩女孩,有個伴一起住總讓人放心些,互相也有個照應(yīng);如果有誰結(jié)了婚,由于每個房間最多住兩個人,還可以比較容易地找出一間,先給他們安個家,慢慢等著分房。這些事當(dāng)然不要我們程序員多操心(除非我們就住在里面)。現(xiàn)在要關(guān)心的是,有人做了一個公寓管理數(shù)據(jù)庫。其中的房間管理表這樣子設(shè)計:

create table rooms(

roomid char(5),

masterid char(10) ,

secondid char(10),

constraint pk_room primary key(roomid),

constraint fk_master foreign key (masterid) references livers(id),

constraint fk_second foreign key (secondid) references livers(id)

)

簡單介紹一下,管理員為了方便管理(比如收個水電費什么的),要求每一個住人的房間有一個房主;兩個人更詳細(xì)的信息保存在了 livers表中,所以我們看到有兩個外鍵約束。當(dāng)然,這個設(shè)計并非無懈可擊,不過它也自有它的理由,在這里我們先不討論了。

這里要關(guān)注的是,房客少于兩個人的房間,我們該在空出來的地方填什么?有一個方法,就是填入一個空字符串,可這樣一來,就等于我們默認(rèn)了存在一個id號為空字符串的住戶存在。因為空字符串也是字符串嘛。兩個外鍵約束也說明了這一點。事實上,在類似這樣的設(shè)計中,我就見過一些例子,其作者為了避免無可引用的情況,憑空造出一個不存在的信息,做為數(shù)據(jù)庫結(jié)構(gòu)的一部分。具體到這個例子,可能會有人真的用一個空字符串或?qū)懸粋€“none”什么的,寫在livers表中,表示沒有人居住。通常這會引起很多問題,比如我們可能要加一個約束,使得一個人不能出現(xiàn)在rooms表中兩次。可現(xiàn)在這個虛擬出來表示沒有人的房客怎么辦?可有很多位置都沒有人啊,比如只要有一個空房,就會在這一條記錄上有兩個“none”!在更離奇(但在某些應(yīng)用中絕非不可能)的情況下,有一個房客,他的id就是“none”,如何??而且如果極端情況下,房客全搬出去了,怎么辦?想要“delet from livers”都不行,“none” 可刪不掉啊。當(dāng)你工作在這樣一個數(shù)據(jù)庫中,得時時提醒自己不要得罪了這個不存在的家伙。要記住,他沒有性別,所以男女職工的房間他都要住;別人一個人只能睡一張床,他卻可以要所有空閑的;別人都搬出去后,他老人家一個人占了所有的房間,我們的法律規(guī)章對他全沒有意義。這種特殊值給我們帶來的最大問題,就是把信息和數(shù)據(jù)庫結(jié)構(gòu)攪在了一起。也就是說,關(guān)系和關(guān)系的模式混為一談了。如果一個數(shù)據(jù)庫中有上幾個這種表,誰都會瘋的。

這就是null的意義,當(dāng)你把一個數(shù)據(jù)定義為null時,就等于告訴系統(tǒng),這個數(shù)據(jù)不存在,或未知。不要管它了,它的內(nèi)容沒有意義(當(dāng)然,這本身也是一種意義)。在房間中有一個null,只表示沒有人,而不會被認(rèn)為是一個叫“沒有人”的人住在里面。更不會有一個霸占了所有房間的惡客存在。要清空livers,那就清吧,只要你設(shè)置了級聯(lián)約束,就不會有任何離奇的事出現(xiàn)。唯一的后果只是一個無人居住的公寓而已,這不正是我們所要的嗎?

null是真實存在的,盡管從某種意義上講,我們無法解釋它的存在。它是關(guān)系世界的黑洞。也許會讓一些人不舒服,但回避它只會給我們帶來更多的麻煩。

看不見摸不到

在《sql-3參考大全》中,作者這樣解釋null的含義:未知或未定義。對null來說,有很多有趣的特性。

null是一個數(shù)據(jù)值,而且它屬于一個域(?)。是的,例如一個字符串字段,其中的空值只能是一個字符串。盡管它的內(nèi)容沒有定義,或者未知,但它是字符串,這一點無可置疑。

null不是非法數(shù)據(jù),這一點sql-3 標(biāo)準(zhǔn)也說的很清楚。我們沒有辦法保存零分之一,但可以保存空值。雖然它是空值,是未定義,是未知,可它也的確是 一個合法的信息。

運算黑洞:對于null,一般的運算都會返回null。比如加減乘除,這簡直就是一個黑洞一樣。永遠(yuǎn)不會有什么數(shù)據(jù)等于null。當(dāng)然,1不等于null,2也一樣。可是,null也不等于null。說一個null等于null是錯誤的。所以我們只能比較它“是”或“不是”。為了避免混亂,sql-3標(biāo)準(zhǔn)有一些約定。比如表達(dá)式 x=null,結(jié)果應(yīng)當(dāng)是unkown 。 而表達(dá)式“x is null”,就得看情況,如果x是null或 false,就返回ture(?);x是非null,返回false。有點奇怪是不是,它基于null不等于null。 這個規(guī)則的確為sql標(biāo)準(zhǔn)所支持,遇到這樣的數(shù)據(jù)庫系統(tǒng),可不要感到驚訝。

三值邏輯:《鹿鼎記》中的韋小寶,整人的秘訣之一就是“我問你話,是就點頭,不是就搖頭,不許你出聲!”的確,通常我們的邏輯觀點,總是基于這種二值邏輯體系,對就是對,錯就是錯。可在關(guān)系理論中,沒有這么簡單。有一種沒有絕對是非的情況存在:null。這就是關(guān)系理論的三值邏輯。

還有一些常見的與null相關(guān)的情況。比如,統(tǒng)計函數(shù)(也有的文檔稱之為聚集函數(shù)、集函數(shù))通常會忽略null。不過,假設(shè)有這樣一個表t:

c

-----

1

2

null

null

我們分別執(zhí)行兩個查詢:select count(*) from t和select count(c) from t, 猜猜會有什么不同?起初,我以為兩個結(jié)果應(yīng)當(dāng)一樣。結(jié)果,前一個是4,后一個是2。前一個等于4,顯然基于null也是數(shù)據(jù)這個事實;而后一個結(jié)果為2,是由于統(tǒng)計c列時,count忽略了null。

sql-3標(biāo)準(zhǔn)中,搜索條件(where和having)只接受true,而約束卻只拒絕false,二者對null的接受態(tài)度相反。所以我們前面見到的rooms表才可以把空值寫入人員字段。而在排序時,卻又沒什么規(guī)律。sql標(biāo)準(zhǔn)只作出了一個補充定義,所以每個dbms的處理 order by的方法并不相同,當(dāng)然null不是高于所有值就是低于所有值。

在《sql-3參考大全》中介紹了更詳細(xì)的關(guān)于null的內(nèi)容。另外,書中還介紹了兩位數(shù)據(jù)庫專家c.j.date和e.f.codd關(guān)于null的不同論點(e.f.codd甚至希望有四值邏輯)有興趣的朋友可以找來一讀。在實踐中,我們還會遇到一些有趣的事,特別是聯(lián)接查詢中, null讓我們的人生變得 “豐富多彩”。

由于種種原因,近幾天我可能會放慢寫作速度,但這并不代表我會放棄。在休整和充電之后,我會回到我所擅長的實戰(zhàn)領(lǐng)域。再次感謝每一位關(guān)心《sql story》的讀者。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 黎川县| 游戏| 江门市| 井研县| 清丰县| 黄陵县| 池州市| 象州县| 金溪县| 湟中县| 成安县| 紫金县| 云浮市| 临夏县| 新绛县| 葵青区| 瓮安县| 麻栗坡县| 通渭县| 乌拉特后旗| 厦门市| 中西区| 灵石县| 白水县| 永嘉县| 勃利县| 保康县| 浦北县| 凤庆县| 新邵县| 子洲县| 富顺县| 东莞市| 冀州市| 介休市| 丹江口市| 库尔勒市| 海南省| 岚皋县| 乌鲁木齐市| 紫云|