2010-01-22 153 views
34

什麼優點和使用NULL值在SQL而不是默認值利弊SQL:使用NULL值與默認值

PS。在這裏有許多類似的問題,但沒有回答我的問題。

+0

具有默認值使得WHERE語句可以跨數據庫移植,有多種方法可以處理NULL。如果你有一個默認值,你可以像使用=的任何其他值一樣測試它,而不必執行IS/IS NOT。 –

回答

38

在數據庫中的NULL值是一個系統 值佔用的 存儲一個字節並且指示值是 不存在,而不是一個空間或 零或任何其他的默認值。包含 NULL值的數據庫中的 字段意味着 該單元格的內容在 查看時未知。允許使用NULL值的列還允許在 列中插入沒有值的行爲 。有幾個優點和 缺點使用NULL值,而不是 爲默認值的:

優點

NULL值不具有數據 類型,因此可以插入到任何 數據結構和任何數據庫 列。默認值,另 另一方面,需要有自己的數據類型指定 和一個 列的默認值可能看起來相同的另一 列,但它可能是一個不同的 類型。

NULL通常用於模式中,其中 值是可選的。這是一種方便的 方法,用於省略 未知字段的數據輸入,而不必 實施其他規則,如 將負值存儲在整數 字段中以表示省略的數據。

由於NULL值僅佔用內存空間的1 位,所以在優化數據庫時它們可能是 有用。 使用這些值比默認值有效得多,例如 。 字符的8位和整數的 16位。

當您的系統需求可能會隨着時間的變化 和默認值 類型和他們在一起,NULL值始終 NULL,所以沒有必要更新 類型的數據。

分配不爲空表模式 也可以用表的有效性, 幫助從某種意義上說與不 空條件的列,需要一個值 插入。默認值不是 具有這些功能。

缺點

NULL值很容易與 空字符串,當 選擇哪個返回 空值給用戶混淆。從這個意義上講,默認值 的值較不易混淆,並且是更安全的選項,除非默認值 設置爲空字符串。

如果允許空值在 數據庫,它們可能會導致設計者 一些額外的時間和工作,因爲他們可以 使數據庫邏輯更 複雜,尤其是當有 很多比較爲空值 地方。

來源:Pro and cons

+5

另外,使用NULLS會產生三個有價值的邏輯。如果X爲3,則布爾值(例如X = 3)的值爲true。如果X的值不是3,而是不爲NULL,則其值爲false。如果X爲NULL,則布爾值的值爲「未知」。未知是第三個邏輯值。這對於習慣了兩種有價值邏輯的人來說可能很神祕。 –

+0

[link](http://www.arthurjach.co.uk/blog/2009/03/25/pros-and-cons-of-using-null-values-in-databases-and-sql/)是腐 –

4

對我來說,它們有點正交。

默認值允許您在無需修改客戶端代碼的情況下正常演變數據庫模式(想想添加列)。此外,他們節省了一些打字,但依靠默認值這是國際海事組織不好。

空值只是:null s。在處理Three-Valued Logic時缺少價值和巨大的PITA。

+3

缺失值本身就是一個值......有很多「無值」具有特定含義的用例,用「魔術值」(如-99999)代替空值不會簡化任何事情;消費代碼必須檢查「如果X.HasValue()」或「如果X == -99999」。 – STW

19

我不知道爲什麼你甚至想這些比較的情況。 null意味着某列是空的/沒有值,而當我們沒有直接在查詢中設置它時,默認值爲列提供了一些值。

也許一些例子會更好的解釋。假設我們有member表。每個成員都有一個ID和用戶名。可選他可能有一個電子郵件地址(但他不必)。同時每個成員都有一個postCount列(每次用戶寫一篇文章時都會增加)。因此,電子郵件列可以具有null值(因爲電子郵件是可選的),而postCount列是NOT NULL,但具有默認值0(因爲當我們創建新成員時,他沒有任何帖子)。

+4

因爲我不完全理解使用這兩個概念,謝謝。 –

5

NULL值表示該屬性不適用或未知。有些宗教戰爭是因爲它們是好事還是壞事而戰,但我陷入了「好事」的陣營。

在許多情況下,他們通常有必要將已知值與未知值區分開來,並且對於那些沒有合適默認值的屬性,他們不需要定位值。

例如,雖然銀行餘額的默認值可能爲零,但手機號碼的默認值是多少。您可能需要區分「客戶沒有手機」和「客戶的手機號碼尚未(已知)」,在這種情況下,空白列將不會執行(並且有額外的列來決定該列是一個還是其他不是一個好主意)。

默認值就是數據庫管理系統將在列中放入的內容,如果沒有明確指定它的話。

+0

000-000-0000或555-555-5555或任何其他無效的電話號碼是一個很好的默認電話號碼,任何可以測試的電話號碼都與理論上的NULL檢測一樣好,但在實踐中更容易。 –

+2

我不同意,模糊。你正在使用的是一個哨兵,一個虛假的實際價值來表明該領域的元數據。有些情況下,所有可能的值都是有效的,而且沒有一個可以用作標記。另外,在查詢中加入「null」並不難,比「='000-000-0000'」(並且通常有更多的空間來存儲null),所以我不確定你有什麼麻煩這使得它更難。 – paxdiablo

10

空值不是...值!

Null意味着'沒有價值'......除數據庫方面外,非值變量或字段的一個重要維度是不可能使用'='(或'>','<'),當比較變量時。

書面方式類似(VB):

if myFirstValue = mySecondValue 

不會返回true或false如果變量的一個或兩個是不重視。你將不得不使用「週轉」,如:

if (isnull(myFirstValue) and isNull(mySecondValue)) or myFirstValue = mySecondValue 

在這種情況下使用的「常態」的代碼是

if Nz(myFirstValue) = Nz(mySecondValue, defaultValue) 

是不完全正確,如不重視的變量將被視爲'等於'defaultValue'值(通常爲零長度字符串)。儘管這種不愉快的行爲,永遠不會永遠不會永遠不會打開你的默認值爲零長度的字符串(或'0's)沒有有價值的原因,並且在代碼中簡化值比較不是一個有價值的原因。

+0

對你有好處,指出NULL不是值。 –

4

與許多事情一樣,每個人都有好的和壞的點。

有關默認值的好處:它們使您能夠在未給出其他值時將列設置爲已知值。例如,當創建BOOLEAN列時,我通常會給該列一個默認值(TRUE或FALSE,無論什麼是合適的)並將該列設置爲NOT NULL。通過這種方式,我可以確信該列將具有價值,並且將被設置爲適當的。

有關默認值的壞點:並非所有東西都有默認值。

關於NULL的好處:並非所有的東西都具有已知的值。例如,當創建一個代表一個人的新行時,我可能沒有所有列的值 - 假設我知道他們的名字,但不知道他們的出生日期。將生日設置爲默認值是不合適的 - 如果他們的生日實際上是7月22日,那麼人們不會喜歡在1月1日生日卡(如果這是默認設置)。

有關NULL的壞事:NULL需要謹慎處理。在通常實現的關係模型上構建的大多數數據庫中,NULL是有毒的 - 在計算中出現NULL會導致計算結果爲NULL。在比較中使用的NULL也會導致意外的結果,因爲與NULL的任何比較都會返回UNKNOWN(既不是TRUE也不是FALSE)。例如,考慮下面的PL/SQL腳本:

declare 
    nValue NUMBER; 
begin 
    IF nValue > 0 THEN 
    dbms_output.put_line('nValue > 0'); 
    ELSE 
    dbms_output.put_line('nValue <= 0'); 
    END IF; 

    IF nValue <= 0 THEN 
    dbms_output.put_line('nValue <= 0'); 
    ELSE 
    dbms_output.put_line('nValue > 0'); 
    END IF; 
end; 

的上述的輸出是:

nValue <= 0 
nValue > 0 

這可能是有點令人驚訝。您的NUMBER(nValue)小於或等於零且大於零,至少根據此代碼。發生這種情況的原因是nValue實際上是NULL,所有與NULL的比較都會導致UNKNOWN而不是TRUE或FALSE。這可能會導致難以理解的細微錯誤。

分享和享受。

4

這取決於情況,但它確實很簡單。哪一個更接近事實?

很多人處理數據就好像它只是數據,事實並不重要。但是,無論何時與數據中的利益相關者交談,您都會發現真相總是很重要。有時更多,有時更少,但總是很重要。當你可以假定如果用戶(或其它數據源)提供了一個值,該值將是默認

的默認值是有用的。如果這種推定的好處更大,那麼NULL更好,儘管處理NULL對於SQL來說是一種痛苦。

請注意,有三種不同的方式可以實現默認值。首先,在插入新數據之前,在應用程序中。數據庫永遠不會看到用戶提供的默認值或應用程序提供的默認值之間的差異!

其次,通過聲明爲列的默認值,並利用現有的數據插入缺失。

第三,通過在檢索時替換默認值,每當檢測到NULL時。只有少數DBMS產品允許在數據庫中聲明第三種模式。

在理想的世界中,數據永遠不會丟失。如果您正在爲真實世界開發,所需的數據最終會丟失。你的應用程序可以做一些有意義的事情,或者做一些在事情發生時沒有意義的事情。

2

Null S和默認值是用於不同的目的不同的東西。如果你試圖通過給所有東西默認值來避免使用null,這是一個不好的做法,我會解釋一下。

Null意味着我們不知道這個值是什麼,或者會。例如,假設你有一個enddate字段。您不知道錄製過程何時結束,因此null是唯一合適的值;在未來使用某種假日期方式的默認值會導致編寫程序時與處理null一樣多的麻煩,並且更可能以我的經驗創建返回不正確結果的問題。

現在有的時候我們可能知道的值應該是什麼,如果插入記錄的人沒有。例如,如果您有一個date inserted字段,則應該有當前日期的默認值,並且不要求用戶填寫該字段。您可能實際上擁有更好的信息。

有時候,這是一個主觀判斷,並取決於你應用的業務規則。假設您有一個speaker honoraria字段(發言人將獲得支付的金額)。默認值0可能會很危險,因爲它可能意味着揚聲器被僱用,我們打算不向他們付錢。也有可能偶爾會有演講者爲某個特定項目捐贈時間(或者是公司的僱員,因此沒有額外付費發言),其中零是正確的值,因此您不能使用零作爲確定你不知道這個發言者要付多少錢的價值。在這種情況下,Null是唯一合適的值,如果有人試圖將揚聲器添加到會議中,代碼應該觸發問題。在另一種情況下,您可能已經知道所有發言人的最低支付金額爲3000,而只有通過協商達成不同費率的發言人纔會在honoraria字段中輸入數據。在這種情況下,可以輸入默認值3000。在另一種情況下,不同的客戶端可能有不同的最小值,因此默認的通常應該通過自動填充數據錄入形式對客戶的最低honoraria值查找表不同的(處理。

所以我覺得最好的規則如果您在輸入數據時確實無法知道該字段的值應該如何,則將該值保留爲null。使用默認值只有它對於特定情況始終具有含義,並且如果在不同情況下可能會有所不同,則使用其他一些技術來填寫該值。

2

在數據倉庫中,您總是希望擁有默認值而不是NULL。

相反,你將是有價值的,如「未知」,「沒有準備好」,「失蹤」

這使得內部連接要在事實和維度表作爲「凡事總有值」

有效地執行
1

正如一位響應者已經說過的,NULL不是一個值。

對任何人說「NULL值」就好像它是一種價值的東西是非常好的東西。

NULL不等於自身。如果x和y都爲NULL,則x = y會產生false。如果x和y都是默認值,則x = y會生成true。

這個看似非常簡單的差別幾乎有無盡的後果。而這些後果中的大部分都是誘餌陷阱,它們會讓你感到非常不好。

0

空不會在DB2 for OS/390和z/OS中節省存儲空間。每個可爲空的列都需要一個額外的空字節存儲空間。因此,可以爲空的CHAR(10)列將需要每行11個字節的存儲空間 - 數據爲10,空指示符爲1。無論列是否設置爲空,都是這種情況。

DB2 for Linux,Unix和Windows有一個壓縮選項,允許將列設置爲空以節省空間。使用此選項會導致DB2從列設置爲空的行中消除未使用的空間。不過,該選項在大型機上不可用。

REF:http://www.craigsmullins.com/bp7.htm

因此,對於DB2 z/OS的最佳造型的做法是使用 「WITH DEFAULT NOT NULL」 作爲所有列的標準。在我認識的一些主要商店中也是如此。通過消除爲NULL INDICATOR使用額外字節的需要,使程序員的生活更輕鬆,無需處理空指示符並實際節省存儲空間。

0

我很欣賞所有這些討論。我正在建立一個數據倉庫,並且嚴格使用Kimball模型。然而,有一個非常聲樂的用戶,他們不喜歡代理鍵,並且希望NULL遍佈整個地方。我告訴他,對於尺寸屬性和計算中使用的任何日期或數字,可以使用NULLable列,因爲默認值會導致數據不正確。我同意,在某些列中允許NULL是有利的,但是如果每個維度的外鍵都有代理鍵,那麼即使代理對於虛擬記錄是-1或0,它也會使立方體變得更好,更可靠。 SQL喜歡用於連接的整數,如果缺少維度值,並且提供了一個啞元作爲代理鍵,那麼您將使用一個維度獲取相同數量的記錄,就像在另一維上進行多維數據集一樣。但是,計算必須正確完成,並且必須適應那些空值。例如,生日應該爲NULL,以便不計算年齡。我相信良好的數據治理能力,並通過用戶的決策迫使他們以比以往更多的方式來思考他們的數據。