null知多少?

来源:http://www.cnblogs.com/i6first/archive/2016/03/01/5229633.html
-Advertisement-
Play Games

null是什麼? 不知道。我是說,他的意思就是不知道(unknown)。 它和true、false組成謂詞的三個邏輯值,代表“未知”。與true和false相比,null最難以令人捉摸,因為它沒有明確的值,在不同的場景下,它能代表不同的含義。下文以例子的方式給大家分享下null使用的典型場景及對應的


null是什麼?

不知道。我是說,他的意思就是不知道(unknown)。

它和true、false組成謂詞的三個邏輯值,代表“未知”。與true和false相比,null最難以令人捉摸,因為它沒有明確的值,在不同的場景下,它能代表不同的含義。下文以例子的方式給大家分享下null使用的典型場景及對應的用法。

1.check約束與null

之前在SQL ServerCentral.com上看到一個關於check約束的null問題,

作者創建了一個表,在欄位orderstatus上設置了check約束,只能插入指定的value的行,現在插入幾行數據,其中有一行的value為null,最後問最終有幾行可以插入成功。

原文如下:

I want to ensure that the status column for my Orders table only contains specific values. I decide to use this code:

create table Orders
( OrderID int primary key
, OrderTotal MONEY
, OrderStatus VARCHAR(20)
constraint Orders_Status_Code check( OrderStatus in ('ACTIVE', 'INACTIVE', 'TBD'))
);
go

Now I want to insert data into the table. I run this batch.

insert Orders select 1, 435.43, 'Active'
insert Orders select 2, 554.66, 'InActive'
insert Orders select 3, 129.12, 'Not Active'
insert Orders select 4, 1228.00, NULL

How many rows are in the table? I am running on a default, SQL Server 2014 instance with US English defaults.

(大家先想想答案,如果沒有把握就找個測試環境試一試)

《T-SQL基礎教程》中關於check約束與null的描述,著者用了一句言簡意賅的口訣“check約束拒絕false,接受true和null”。

在上面的例子中,當orderstatus為‘Avative’和’InActive’時,check約束判斷的結果是true,所以會插入成功,當為'Not Active’判斷的結果為false,插入不成功,最後當為'Null’時,判斷的結果是null,插入成功。

所以,正確答案是3。

 

2.比較運算與null

null一個特殊性在於它無法比較(和計算)。null與任何值的任何比較(和計算)都等於null。(unique約束除外,在unique約束中,null是相等的,同一個欄位不允許出現兩次null)

比如判斷null=null的結果是null,判斷null<>null的結果也還是null。下麵我以不等於(<>)為例,演示比較運算對null的判斷。

我先創建一個表,然後插入多行數據,其中有一行orderstatus的值為null,

 
if object_id(N’Orders’) is not null drop table orders
 
create table Orders
( OrderID int primary key
, OrderTotal MONEY
, OrderStatus VARCHAR(20)
);
go
 
 
insert Orders select 1, 435.43, 'Active'
insert Orders select 2, 554.66, 'InActive'
insert Orders select 3, 129.12, 'Not Active'
insert Orders select 4, 1228.00, NULL
 
 

現在我執行了一個where orderstatus<>'Active' 的查詢,

select * from orders where OrderStatus<>'Active'

大家想想null所在的行會不會在查詢結果裡面。

在上面的例子中,當orderstatus為'InActive''Not Active' 時,where條件判斷的結果為true,但當orderstatus為'null' 時,where OrderStatus<>'Active'等價於where null <>'Active',而null與任何一個值的比較結果還是null,所以where條件判斷的結果為null。

在SQL Server中,where篩選的原則是“接受true,拒絕false和null”(《T-SQL基礎教程》)。所以orderstatus'InActive' 'Not Active'的行顯示在結果集總,而orderstatus為null的行不會出現在結果集中

最終,正確答案是:只會返回兩行

image

 

3.Not in與null和Not exists與null

not in和not exists都可以用來判斷某個對象的存在與否,在大多數場景下兩者可以相互替換,但在遇到null時,因為前者是三值邏輯(true|false|unknow)判斷而後者只會返回true或false,因此處理的結果會有很大不同。

為了演示兩者的區別,我們還是沿用上文的表,分別使用not in和not exists執行一個查詢,找出OrderStatus 不為'Active'和'InActive'的行。

 
if object_id(N’Orders’) is not null drop table orders
 
create table Orders
( OrderID int primary key
, OrderTotal MONEY
, OrderStatus VARCHAR(20)
);
go
 
 
insert Orders select 1, 435.43, 'Active'
insert Orders select 2, 554.66, 'InActive'
insert Orders select 3, 129.12, 'Not Active'
insert Orders select 4, 1228.00, NULL
 

 

3.1Not In與null

在下麵這個查詢中,where子句中使用not in來過濾數據,where子句的條件是OrderStatus not in ('Active','InActive'),我們期望結果集中包含orderstatus為'Not Active'、'NULL'這兩行的數據。



select * from orders where OrderStatus not in ('Active','InActive')

這個查詢中,當OrderStatus為null時, 原where子句等價於where null <>'Active' OR  null<>'InActive',這就變成了上文中介紹的比較運算與null的問題。where的判斷結果還是null,所以該行不會出現在結果集中。而當OrderStatus為'Not Active'時,滿足where篩選的為true的條件,會顯示在結果集中。

最終,正確答案是:只有一行。

image

說明:in與null的關係與此同理。

 

3.2Not exists與null

現在我們還是期望結果集中包含orderstatus為'Not Active'、'NULL'這兩行的數據,這次用Not exists。

在這個查詢中,子查詢先求出OrderStatus='Active' or  OrderStatus='InActive的行,然後外部查詢用not exists過濾子查詢的結果,將剩下的行顯示在最終結果集中。

SELECT *
FROM orders AS o1
WHERE NOT EXISTS( 
                  SELECT *
                  FROM orders AS o2
                  WHERE o1.OrderStatus = o2.OrderStatus
                    AND ( o2.OrderStatus = 'Active'
                       OR o2.OrderStatus = 'InActive'
                        ));

 

image

 

為了方便理解,我們將子查詢改寫成自表連接的方式,

select * from orders as o2 where  o1.OrderStatus=o2.OrderStatus and (o2.OrderStatus='Active' or  o2.OrderStatus='InActive' ))

改寫成:

SELECT *
FROM orders AS o2
     INNER JOIN orders o1 ON o1.OrderStatus = o2.OrderStatus
                         AND ( o2.OrderStatus = 'Active'
                            OR o2.OrderStatus = 'InActive'
                             );

返回的結果集為:

image

然後我們再看外層查詢,

外部查詢期望使用not exists返回orders表中不包含子查詢結果集的行,也就是說,只要orders表沒有子查詢結果集中的行就返回true,否則返回false(只有存在和不存在,沒有unknown的說法)。

按照這個邏輯,orderID為3和4的行不在子查詢的結果集中,因此not exists判斷為true,而orderID為1和2的行已包含在子查詢的結果集中,所以not exists判斷為false。最後根據where篩選“接受true,拒絕false和null”的原則,最終只有orderID為3和4的行顯示在結果集中。

image

說明:exists與null的關係與此同理。

 

3.3Not  in和Not exists的區別

not in實際上是對一個對象的比較運算,而比較存在true|false|unknow三種邏輯值。

not exsits判斷某個對象存在或者不存在,它只有這兩種狀態,沒有unknown的說法。因此相比not in而言,not exists只會有true和false這兩種邏輯值。

 

總結:

上文介紹了null在不同場景中的含義,考慮到SQL不同的語言元素對null的不同處理方式,平常我們在寫SQL語句的時候應該清晰思考自己編寫的每個查詢對null或三值邏輯的處理,避免出現邏輯錯誤。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這個叫指讀的App設計簡約,走MD風格,UI設計很清新,我個人挺喜歡。 這次上傳的源碼是在Eclipse環境開發的,儘管放心啦上次找源碼的時候不知道來源,也不知道原作者,很抱歉。這個設計精美的app是來自洋蔥先森大神的。大家可以向他學習 源碼下載:http://code.662p.com/list/
  • 一,效果圖。 二,工程圖。 三,代碼。 RootViewController.h #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> @interface RootViewController : UIViewControlle
  • 這個世界上有兩種人-從經驗教訓中學習的人以及聽從別人建議的人。這裡是我一路走來學到的一些東西,分享給大家: 在添加任何第三方party之前,請三思:這真的是一個成熟的項目嗎? 如果一個東西用戶看不到,就不要繪製它! 除非真的需要,否則別使用資料庫; 達到65k方法數限制來的非常快,真的,非常快!不過
  • 最近碰到一個問題,需求如下: 需求:在某個storyboard中有一個單獨的控制器VC(沒有連線),在storyboard中給此VC隨便拖幾個控制項在上面,同時自定義一個類綁定此VC,問如何獲取到此VC並且顯示storyboard中此VC設置的界面。如下圖: 1,首先要知道是哪個storyboard,
  • 佈局layout中使用: 1 <ProgressBar 2 android:id="@+id/progress_bar" 3 style="?android:attr/progressBarStyleHorizontal" <!--必須設置為水平--> 4 android:progressDrawa
  • 分類:C#、Android、VS2015; 創建日期:2016-03-01 一、簡介 本章主要演示Started Service、帶Intent過濾器的Started Service、IntentService的基本用法,並簡單介紹Android提供的系統服務。 二、本章示例主界面 1、運行截圖 2...
  • 獲取【下載地址】 QQ: 313596790 【免費支持更新】支持三大資料庫 mysql oracle sqlsever 更專業、更強悍、適合不同用戶群體【新錄針對本系統的視頻教程,手把手教開發一個模塊,快速掌握本系統】A 代碼生成器(開發利器); 增刪改查的處理類,service層,mybatis
  • 游標(Cursor)是處理數據的一種方法,為了查看或者處理結果集中的數據,游標提供了在結果集中一次以行或者多行前進或向後瀏覽數據的能力。我們可以把游標當作一個指針,它可以指定結果中的任何位置,然後允許用戶對指定位置的數據進行處理。 1.游標的組成 游標包含兩個部分:一個是游標結果集、一個是游標位置。
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...