Tại sao chúng ta không nên cho phép NULL?


125

Tôi nhớ đã đọc một bài viết này về thiết kế cơ sở dữ liệu và tôi cũng nhớ nó nói rằng bạn nên có các thuộc tính trường của KHÔNG NULL. Tôi không nhớ tại sao đây là trường hợp.

Tất cả những gì tôi dường như có thể nghĩ là, là một nhà phát triển ứng dụng, bạn sẽ không phải kiểm tra NULL một giá trị dữ liệu không tồn tại có thể (ví dụ: một chuỗi trống cho chuỗi).

Nhưng bạn sẽ làm gì trong trường hợp ngày, thời gian và thời gian (SQL Server 2008)? Bạn sẽ phải sử dụng một số ngày lịch sử hoặc chạm đáy.

Bất cứ ý tưởng về điều này?


4
Câu trả lời này có cái nhìn sâu sắc về việc sử dụng NULL dba.stackexchange.com/questions/5176/iêu
Derek Downey

10
Có thật không? Tại sao RDBMS cho phép chúng tôi sử dụng NULL, nếu chúng tôi không nên sử dụng chúng? Không có gì sai với NULL miễn là bạn biết cách đối phó với chúng.
Fr0zenFyr

3
Đây có phải là mô hình dữ liệu BI? Nói chung, bạn không nên cho phép null trong các bảng thực tế ... nếu không, null là bạn của bạn khi được sử dụng đúng cách. =)
sam yi

2
@ Fr0zenFyr, chỉ vì RDBMS cho phép chúng tôi làm điều gì đó không nhất thiết phải làm như vậy. Không có gì buộc chúng ta phải khai báo một khóa chính hoặc một khóa duy nhất trong một bảng, nhưng với một vài ngoại lệ, dù sao chúng ta cũng làm như vậy.
Lennart

3
Tôi nghĩ rằng một điều trị hoàn chỉnh của chủ đề này sẽ phải tham chiếu đến yêu cầu ban đầu của Codd rằng RDBMS phải có cách xử lý dữ liệu bị thiếu có hệ thống. Trong thế giới thực, có những tình huống tạo ra một vị trí cho dữ liệu, nhưng không có dữ liệu để đặt vào đó. Data Architect phải đưa ra một số phản hồi cho việc này, cho dù nó liên quan đến thiết kế cơ sở dữ liệu, lập trình ứng dụng hoặc cả hai. SQL NULL kém hoàn hảo hơn trong việc đáp ứng yêu cầu này, nhưng tốt hơn là không có gì cả.
Walter Mitty

Câu trả lời:


230

Tôi nghĩ rằng câu hỏi được đặt ra rất kém, vì từ ngữ ngụ ý rằng bạn đã quyết định NULL là xấu. Có lẽ bạn có nghĩa là "Chúng ta có nên cho phép NULL không?"

Dù sao, đây là sự đảm nhận của tôi: Tôi nghĩ rằng NULL là một điều tốt. Khi bạn bắt đầu ngăn chặn NULL chỉ vì "NULL xấu" hoặc "NULL khó", bạn bắt đầu tạo dữ liệu. Ví dụ, nếu bạn không biết ngày sinh của tôi thì sao? Bạn sẽ đặt gì vào cột cho đến khi bạn biết? Nếu bạn giống như nhiều người chống NULL, bạn sẽ nhập 1900-01-01. Bây giờ tôi sẽ được đưa vào phòng lão khoa và có thể nhận được một cuộc gọi từ đài tin tức địa phương chúc mừng tôi về cuộc sống lâu dài của tôi, hỏi tôi những bí mật để sống một cuộc đời dài như vậy, v.v.

Nếu một hàng có thể được nhập vào nơi có thể bạn không biết giá trị của cột, tôi nghĩ NULL có ý nghĩa hơn nhiều so với việc chọn một số giá trị mã thông báo tùy ý để thể hiện sự thật rằng nó không xác định - một giá trị mà người khác sẽ biết phải biết, kỹ sư đảo ngược, hoặc hỏi xung quanh để tìm hiểu ý nghĩa của nó.

Tuy nhiên, có một sự cân bằng - không phải mọi cột trong mô hình dữ liệu của bạn đều không có giá trị. Thường có các trường tùy chọn trên một biểu mẫu hoặc các mẩu thông tin mà nếu không được thu thập tại thời điểm hàng được tạo. Nhưng điều đó không có nghĩa là bạn có thể trì hoãn việc điền tất cả dữ liệu. :-)

Ngoài ra khả năng sử dụng NULL có thể bị hạn chế bởi các yêu cầu quan trọng trong cuộc sống thực. Trong lĩnh vực y tế, ví dụ, nó có thể là vấn đề sống hay chết để biết tại sao một giá trị không được biết đến. Là nhịp tim NULL vì không có mạch đập, hay vì chúng ta chưa đo được? Trong trường hợp như vậy, chúng ta có thể đặt NULL vào cột nhịp tim và có ghi chú hoặc cột khác với lý do NULL không?

Đừng sợ NULL, nhưng sẵn sàng tìm hiểu hoặc ra lệnh khi nào và nơi nào chúng nên được sử dụng, và khi nào và ở đâu không nên sử dụng.


3
"Một số giá trị mã thông báo tùy ý để thể hiện thực tế là không xác định" đây được gọi là giá trị trọng tâm
Alexander

4
Nhưng điều gì ngăn cản bạn tạo bảng riêng biệt birth_datenơi bạn lưu trữ ngày sinh? Nếu không biết ngày sinh thì chỉ cần không chèn ngày sinh vào birth_date. Nulls là thảm họa.
Eldar Agalarov

6
@EldarAgalarov Nghe có vẻ giống như lý luận của Trump (thảm họa tại sao? Làm thế nào? Đối với ai? Ý kiến ​​của bạn rằng một cái gì đó là một "thảm họa" không làm cho nó trở nên như vậy). Dù sao ngày sinh chỉ là một ví dụ. Nếu bạn có nhân sự hoặc thành viên hoặc khách hàng có 15 cột có khả năng vô hiệu, bạn sẽ tạo 15 bảng phụ? Nếu bạn có 50 thì sao? Nếu bảng thực tế DW của bạn có 500 thì sao? Việc bảo trì để giữ các NULL đáng sợ xấu xa khỏi cơ sở dữ liệu của bạn trở nên tồi tệ gấp 10 lần bất kỳ thảm họa nào mà bạn sợ ...
Aaron Bertrand

3
@AaronBertrand nếu bảng của bạn có 15 cột có khả năng vô hiệu, nó có mùi rất tệ ^^ Không phải là một số lượng lớn cột vốn đã xấu, nhưng nó có thể chỉ ra một thiết kế xấu HOẶC yêu cầu không chuẩn hóa. Nhưng nó sẽ đặt ra câu hỏi.
chương trình

2
@Wildcard Vì vậy, bạn chưa bao giờ thấy mọi người lưu trữ 1900-01-01để tránh có giá trị ngày / giờ NULL? Được rồi Ngoài ra, NULL = chưa biết và chưa biết = sai. Tôi không chắc vấn đề này có thể gây ra gì ngoài những người không được sinh ra khi biết rằng (giống như họ không được sinh ra đã biết rất nhiều điều vốn có trong một RDBMS phức tạp). Một lần nữa, vẫy tay và nói "Vấn đề! Thảm họa!" không làm cho nó như vậy.
Aaron Bertrand

57

Lý do thành lập là:

  • NULL không phải là một giá trị và do đó không có kiểu dữ liệu nội tại. Nulls cần xử lý đặc biệt ở mọi nơi khi mã mà phụ thuộc vào các loại thực tế cũng có thể nhận được NULL chưa gõ.

  • NULL phá vỡ logic hai giá trị (đúng hoặc sai) và yêu cầu logic ba giá trị. Điều này phức tạp hơn nhiều để thậm chí thực hiện chính xác, và chắc chắn là hầu hết các DBA và hầu hết các DBA không hiểu rõ. Kết quả là, nó tích cực mời nhiều lỗi tinh vi trong ứng dụng.

  • Ý nghĩa ngữ nghĩa của bất kỳ NULL cụ thể nào được để lại cho ứng dụng , không giống như các giá trị thực tế.

    Các ngữ nghĩa như không thể áp dụng được và không biết đến các ứng dụng và không rõ ràng và khác. Chúng thường được sử dụng đồng thời trong cùng một cơ sở dữ liệu, thậm chí trong cùng một mối quan hệ; và tất nhiên là không có ý nghĩa rõ ràng và không thể phân biệt và không tương thích .

  • Chúng không cần thiết phải có cơ sở dữ liệu quan hệ , như đã được lập luận trong phần Cách xử lý thông tin bị thiếu mà không cần Nulls . Chuẩn hóa hơn nữa là bước đầu tiên rõ ràng để thử loại bỏ một bảng NULL.

Điều này không có nghĩa là NULL không bao giờ được phép. Nó không cho rằng có nhiều lý do chính đáng để không cho phép NULL bất cứ nơi nào khả thi.

Đáng kể, nó lập luận rằng đã rất cố gắng - thông qua thiết kế lược đồ tốt hơn, và các công cụ cơ sở dữ liệu tốt hơn và các ngôn ngữ cơ sở dữ liệu tốt hơn - để làm cho việc tránh NULL thường xuyên hơn là khả thi.

Fabian Pascal trả lời một số lập luận, trong Nulls Nullified ' .


3
Liên kết của bạn đến "Cách xử lý thông tin thiếu mà không có thông tin" cho thấy khá rõ lý do tại sao chúng tôi không thể làm gì nếu không có null: Một số đề xuất sẽ không thể thực hiện theo cách hợp lý trên các RDBMS chính khi chúng hiện đang tồn tại.
Jack Douglas

7
Jack: Đúng vậy, nhưng các ứng dụng hiện tại không thể thực hiện được. Đây không phải là một đối số cho hiện trạng :-)
bignose

17
Có phải kiểu như chúng ta không nên bay vì máy bay không hoàn hảo?
Aaron Bertrand

11
Không, nó nói rằng các nhà cung cấp nên ngừng viện cớ cho các null có thể là hợp lệ bốn mươi năm trước, nhưng từ lâu đã vượt quá thời gian duy trì hợp lý của họ. Thời gian I / O không còn theo thứ tự cường độ 80ms. Các chu kỳ CPU đơn không còn theo thứ tự độ lớn của micro giây. Giới hạn bộ nhớ không còn theo thứ tự cường độ của một vài Megs. Không giống như bốn mươi năm trước, tốc độ và dung lượng phần cứng cần thiết để làm việc mà không có null bây giờ DO tồn tại với chi phí không bị cấm. Anh ấy nói rằng đã đến lúc phải tiếp tục.
Erwin Smout

2
Liên kết "nhầm lẫn NULL" đã chết.
jpmc26

32

Tôi không đồng ý, null là một yếu tố thiết yếu của thiết kế cơ sở dữ liệu. Sự thay thế, như bạn đã ám chỉ, sẽ là sự phổ biến của các giá trị đã biết để thể hiện sự thiếu hoặc chưa biết. Vấn đề nằm ở chỗ null bị hiểu lầm quá rộng rãi và kết quả là được sử dụng không phù hợp.

IIRC, Codd đề xuất việc triển khai null hiện tại (có nghĩa là không có / thiếu) có thể được cải thiện bằng cách có hai điểm đánh dấu null thay vì một, "không hiện diện nhưng có thể áp dụng" và "không hiện diện và không áp dụng". Cá nhân này không thể hình dung được các thiết kế quan hệ sẽ được cải thiện như thế nào.


2
Tôi khuyên bạn nên có một tập hợp các loại khác nhau do nullngười dùng định nghĩa và logic đa giá trị do người dùng định nghĩa đi kèm với chúng: p
Jack Douglas

13
Đó không phải là những lựa chọn duy nhất. Bạn loại trừ phương án chuẩn hóa: Thay vì các cột có thể có hoặc không có giá trị, hãy sử dụng một bảng khác có thể có hoặc không có hàng tương ứng cho bảng đầu tiên. Ý nghĩa của sự hiện diện hay vắng mặt của một hàng được đặt theo nghĩa của các bảng và không có giá trị đặc biệt của các giá trị NULL hoặc sentinel, v.v.
bignose

7
Sự hiện diện của NULL không đòi hỏi các giá trị vỏ đặc biệt hoặc trọng tâm. Đó chỉ là những triệu chứng về cách một số người quyết định đối phó với NULL.
Aaron Bertrand

Điều đáng chú ý là '' khác với null trên PostgreSQL (mặc dù không phải là Oracle) và do đó cung cấp cho bạn một điểm đánh dấu hai lần và bạn có thể sử dụng 0 cho các cột số. Vấn đề với 0 mặc dù là nó không hoạt động đối với khóa ngoại.
Chris Travers

13

Hãy để tôi bắt đầu bằng cách nói rằng tôi không phải là một DBA, tôi là một nhà phát triển và tôi duy trì và cập nhật cơ sở dữ liệu của chúng tôi dựa trên nhu cầu của chúng tôi. Điều đó đang được nói, tôi đã có cùng một câu hỏi vì một vài lý do.

  1. Giá trị Null làm cho sự phát triển khó khăn hơn và dễ bị lỗi.
  2. Các giá trị Null làm cho các truy vấn, các thủ tục được lưu trữ và các khung nhìn phức tạp hơn và dễ bị lỗi hơn.
  3. Các giá trị Null chiếm không gian (? Byte dựa trên chiều dài cột cố định hoặc 2 byte cho chiều dài cột thay đổi).
  4. Giá trị Null có thể và thường ảnh hưởng đến việc lập chỉ mục và toán học.

Tôi dành một khoảng thời gian rất dài để sàng lọc thông qua vô số phản hồi, bình luận, bài viết và lời khuyên trên internet. Không cần phải nói hầu hết các thông tin đều giống như phản hồi của @ AaronBertrand. Đó là lý do tại sao tôi cảm thấy cần phải trả lời câu hỏi này.

Đầu tiên tôi muốn đặt một cái gì đó thẳng cho tất cả các độc giả trong tương lai ... Các giá trị NULL đại diện cho dữ liệu không xác định KHÔNG phải dữ liệu không được sử dụng. Nếu bạn có một bảng nhân viên có trường ngày chấm dứt. Giá trị null trong ngày kết thúc là bởi vì đó là trường bắt buộc trong tương lai hiện chưa biết. Mỗi nhân viên có thể hoạt động hoặc chấm dứt tại một thời điểm nào đó sẽ có ngày được thêm vào lĩnh vực đó. Theo ý kiến ​​của tôi, đó là lý do duy nhất và duy nhất cho trường Nullable.

Điều đó được nói rằng cùng một bảng nhân viên rất có thể sẽ chứa một số loại dữ liệu xác thực. Điều phổ biến trong môi trường doanh nghiệp là nhân viên sẽ được liệt kê trong cơ sở dữ liệu về nhân sự và kế toán nhưng không phải lúc nào cũng có hoặc cần chi tiết xác thực. Hầu hết các câu trả lời sẽ khiến bạn tin rằng không có gì để loại bỏ các trường đó hoặc trong một số trường hợp tạo tài khoản cho họ nhưng không bao giờ gửi cho họ thông tin đăng nhập. Cái trước sẽ khiến nhóm phát triển của bạn viết mã để kiểm tra NULL và xử lý chúng cho phù hợp và cái sau có nguy cơ bảo mật rất lớn! Các tài khoản chưa bao giờ được sử dụng trong hệ thống chỉ làm tăng số lượng điểm truy cập có thể có cho tin tặc, cộng với việc chúng chiếm không gian cơ sở dữ liệu có giá trị cho những thứ không bao giờ được sử dụng.

Với các thông tin ở trên, cách tốt nhất để xử lý dữ liệu không thể sử dụng SILL được sử dụng là cho phép các giá trị nullable. Thật đáng buồn nhưng sự thật và các nhà phát triển của bạn sẽ ghét bạn vì điều đó. Loại dữ liệu không thể thứ hai nên được đặt trong một bảng có liên quan (IE: Tài khoản, Thông tin xác thực, v.v.) và có mối quan hệ Một-Một. Điều này cho phép người dùng tồn tại mà không cần thông tin đăng nhập trừ khi họ cần thiết. Điều này loại bỏ rủi ro bảo mật thêm, không gian cơ sở dữ liệu có giá trị và cung cấp cho cơ sở dữ liệu sạch hơn nhiều.

Dưới đây là cấu trúc bảng rất đơn giản hiển thị cả cột không thể yêu cầu và mối quan hệ Một đối một.

Mối quan hệ Nullable và One-to-One không xác định

Tôi biết tôi đến bữa tiệc muộn một chút vì câu hỏi này đã được hỏi từ nhiều năm trước nhưng hy vọng điều này sẽ giúp làm sáng tỏ vấn đề này và cách giải quyết tốt nhất.


2
Tôi sẽ chỉ thay đổi nó để không có TerminationDatetrong hồ sơ nhân viên, nhưng có một bảng TerminatedEmployeemà nhân viên được chuyển đến (không được sao chép) bởi ứng dụng khi họ bị chấm dứt. Rõ ràng điều này hoạt động độc đáo với bảng Tài khoản vì sẽ không có tài khoản được liên kết trên TerminatedEmployeebảng. Nếu bạn vẫn cần số điện thoại, tôi sẽ đảo ngược các khóa ngoại để nhân viên và bảng nhân viên bị chấm dứt có id của số điện thoại thay vì cách khác.
trình viên

2
Tôi thực sự có thể tiếp tục trong nhiều ngày về lý do tại sao điều này sẽ là xấu. Các bảng dự phòng, các thực tiễn SQL xấu, khiến các nhà phát triển của bạn phải tìm kiếm hai vị trí cho dữ liệu nhân viên, các vấn đề về báo cáo, các vấn đề với URI trực tiếp cho một nhân viên không tồn tại (đã được di chuyển) và danh sách sẽ tiếp tục và hơn thế nữa. Hoàn toàn ổn khi có NULLS cho các trường mà một ngày nào đó sẽ có giá trị, đó là một câu chuyện khác để có các trường không bao giờ được điền và không bao giờ có sử dụng. Một số vấn đề tiềm năng và cách giải quyết để thực hiện công việc này sẽ không đáng là vấn đề nhỏ khi kiểm tra NULL trên một lĩnh vực.
Nicholas Aguirre

1
Tôi không đồng ý. Điều duy nhất dư thừa là trường null cho ngày kết thúc có thể không bao giờ được điền. Các nhà phát triển chỉ phải tìm trong bảng thích hợp cho dữ liệu họ muốn và có thể cải thiện hiệu suất. Nếu vì một lý do nào đó, bạn muốn cả nhân viên bị chấm dứt và không bị chấm dứt, nó được giải quyết bằng cách tham gia, nhưng 90% thời gian ứng dụng của bạn có thể sẽ muốn cái này hoặc cái kia. Tôi nghĩ rằng bố cục tôi đã chỉ định là tốt hơn bởi vì không thể có ngày chấm dứt đối với nhân viên và anh ta vẫn có tài khoản.
trình viên

2
Tôi không nói dữ liệu dư thừa, tôi nói bảng dự phòng. Thêm vào đó, bất kỳ thay đổi nào đối với các bảng nhân viên phải nhỏ giọt xuống các bảng đã kết thúc; điều này làm cho ứng dụng dễ bị lỗi và nó làm cho công việc của nhà phát triển khó khăn hơn nhiều. Ngoài ra, trường ngày chấm dứt sẽ được điền cho hầu hết mọi người. Thật lãng phí và có vấn đề khi tạo cấu trúc bảng giống hệt thứ hai và cũng di chuyển dữ liệu xung quanh. Không bao gồm kiểm tra mỗi lần để đảm bảo dữ liệu bảng đã được di chuyển và làm sạch. Đó là thực hành xấu để loại bỏ dữ liệu từ một bảng, ngay cả khi chỉ để di chuyển nó. Nếu bạn quá quan tâm đến một lĩnh vực duy nhất ...
Nicholas Aguirre

1
... Điều đó hầu như sẽ luôn được lấp đầy theo thời gian sau đó tạo một bảng kết thúc với mối quan hệ 1to1 trở lại với nhân viên. Tôi làm việc với nhiều loại cơ sở dữ liệu cả ngày với tư cách là một DBA và là một nhà phát triển và tôi rất vui vì tôi chưa bắt gặp một cơ sở với cấu trúc mà bạn đề xuất. Đặc biệt theo quan điểm của một nhà phát triển, sẽ là một cơn ác mộng khi viết và kiểm tra lỗi mọi thứ bởi vì bạn sẽ không biết nó đến từ bảng nào. Ngay cả khi viết một liên kết, dữ liệu được trả về phần mềm sẽ có một trường có dữ liệu null vẫn sẽ yêu cầu bạn kiểm tra điều đó.
Nicholas Aguirre

13

Ngoài tất cả các vấn đề với các nhà phát triển khó hiểu của NULL, các NULL còn có một nhược điểm rất nghiêm trọng khác: Hiệu suất

Các cột NULL'able là một thảm họa từ góc độ hiệu suất. Hãy xem xét số nguyên là số học. Trong một thế giới lành mạnh không có NULL, thật dễ dàng để vectơ số học số nguyên trong mã công cụ cơ sở dữ liệu bằng cách sử dụng các lệnh SIMD để thực hiện bất kỳ phép tính nào với tốc độ nhanh hơn 1 hàng trên mỗi chu kỳ CPU. Tuy nhiên, thời điểm bạn giới thiệu NULL, bạn cần xử lý tất cả các trường hợp đặc biệt mà NULL tạo ra. Các bộ hướng dẫn CPU hiện đại (đọc: x86 / x64 / ARM và logic GPU cũng vậy) đơn giản là không được trang bị để thực hiện điều này một cách hiệu quả.

Hãy xem xét phân chia như một ví dụ. Ở mức rất cao, đây là logic bạn cần với số nguyên không null:

if (b == 0)
  do something when dividing by error
else
  return a / b

Với NULL, điều này trở nên khó khăn hơn một chút. Cùng với bbạn sẽ cần một chỉ báo nếu blà null và tương tự cho a. Kiểm tra bây giờ trở thành:

if (b_null_bit == NULL)
   return NULL
else if (b == 0) 
   do something when dividing by error
else if (a_null_bit == NULL)
   return NULL
else 
   return a / b

Số học NULL chạy chậm hơn đáng kể trên CPU hiện đại so với số học không null (theo hệ số khoảng 2-3 lần).

Nó trở nên tồi tệ hơn khi bạn giới thiệu SIMD. Với SIMD, CPU Intel hiện đại có thể thực hiện các phép chia số nguyên 4 x 32 bit trong một lệnh, như sau:

x_vector = a_vector / b_vector
if (fetestexception(FE_DIVBYZERO))
   do something when dividing by zero
return x_vector;

Bây giờ, có nhiều cách để xử lý NULL trong vùng đất SIMD, nhưng điều này đòi hỏi phải sử dụng nhiều vectơ và thanh ghi CPU hơn và thực hiện một số mặt nạ bit thông minh. Ngay cả với các thủ thuật tốt, hình phạt hiệu suất của creep số học NULL vào phạm vi chậm hơn 5-10 lần cho các biểu thức tương đối đơn giản.

Một cái gì đó giống như ở trên giữ cho tổng hợp và ở một mức độ nào đó, cho tham gia quá.

Nói cách khác: Sự tồn tại của NULL trong SQL là sự không phù hợp trở kháng giữa lý thuyết cơ sở dữ liệu và thiết kế thực tế của các máy tính hiện đại. Có một lý do khá chính đáng để NULL nhầm lẫn các nhà phát triển - bởi vì một số nguyên không thể là NULL trong hầu hết các ngôn ngữ lập trình lành mạnh - đó không phải là cách máy tính hoạt động.


10

Câu hỏi thú vị.

Tất cả những gì tôi dường như có thể nghĩ là, là một nhà phát triển ứng dụng, bạn sẽ không phải kiểm tra NULL và một giá trị dữ liệu không tồn tại có thể (ví dụ: một chuỗi trống cho chuỗi).

Nó phức tạp hơn thế. Null có một số ý nghĩa riêng biệt và một lý do thực sự quan trọng không cho phép null trong nhiều cột là khi cột không có nghĩa thì điều này có nghĩa là một và chỉ một điều (cụ thể là nó không xuất hiện trong một liên kết ngoài). Ngoài ra, nó cho phép bạn thiết lập các tiêu chuẩn nhập dữ liệu tối thiểu thực sự hữu ích.

Nhưng bạn sẽ làm gì trong trường hợp ngày, thời gian và thời gian (SQL Server 2008)? Bạn sẽ phải sử dụng một số ngày lịch sử hoặc chạm đáy.

Điều đó minh họa một vấn đề với null ngay lập tức, cụ thể là một giá trị được lưu trữ trong bảng có thể có nghĩa là "giá trị này không áp dụng" hoặc "chúng tôi không biết." Với các chuỗi, một chuỗi rỗng có thể đóng vai trò là "điều này không áp dụng" nhưng với ngày và thời gian, không có quy ước nào như vậy bởi vì không có giá trị hợp lệ nào có nghĩa là quy ước này. Thông thường ở đó bạn sẽ bị mắc kẹt khi sử dụng NULL.

Có nhiều cách để khắc phục điều này (bằng cách thêm nhiều mối quan hệ và tham gia) nhưng những cách đó đặt ra các vấn đề rõ ràng về ngữ nghĩa chính xác giống như có NULL trong cơ sở dữ liệu. Đối với các cơ sở dữ liệu này, tôi sẽ không lo lắng về điều này. Không có bất cứ điều gì bạn có thể làm về nó thực sự.

EDIT: Một khu vực nơi NULLs không thể thiếu trong các phím nước ngoài. Ở đây chúng thường chỉ có một nghĩa, giống hệt với null trong nghĩa nối ngoài. Đây là một ngoại lệ cho vấn đề tất nhiên.


10

Bài viết của Wikipedia về SQL Null có một số nhận xét thú vị về giá trị NULL và như một câu trả lời không xác định cơ sở dữ liệu, miễn là bạn biết về các ảnh hưởng tiềm năng của việc có các giá trị NULL cho RDBMS cụ thể của bạn, chúng có thể được chấp nhận trong thiết kế của bạn. Nếu không, bạn sẽ không thể chỉ định các cột là nullable.

Chỉ cần lưu ý về cách RDBMS của bạn xử lý chúng trong các hoạt động CHỌN như toán học và cả trong Chỉ mục.


-12

Ồ, câu trả lời đúng "Không cho phép NULL khi bạn không phải làm thế vì chúng làm giảm hiệu suất" bằng cách nào đó là câu trả lời được xếp hạng cuối cùng. Tôi sẽ nâng cấp nó và xây dựng. Khi RDBMS cho phép NULL cho một cột không thưa thớt, cột đó được thêm vào một bitmap để theo dõi xem giá trị có phải là NULL cho mỗi hàng riêng lẻ hay không. Vì vậy, bằng cách thêm khả năng NULL vào một cột trong bảng trong đó tất cả các cột không cho phép NULL, bạn đang tăng không gian lưu trữ cần thiết để lưu bảng. Hơn nữa, bạn đang yêu cầu RDBMS đọc và ghi vào bitmap, làm giảm hiệu suất trên tất cả các hoạt động.

Hơn nữa, trong một số trường hợp, cho phép NULL sẽ phá vỡ 3NF. Mặc dù tôi không phải là người gắn bó với 3NF như nhiều đồng nghiệp của mình, hãy xem xét tình huống sau:

Trong bảng Person có một cột, được gọi là DateOfDeath, không có giá trị. Nếu một người đã chết, nó sẽ được điền vào DateOfDeath của họ, nếu không, nó sẽ bị bỏ lại NULL. Ngoài ra còn có một cột bit không nullable được gọi là IsAlive. Cột này được đặt thành 1 nếu người còn sống và 0 nếu người đó đã chết. Phần lớn các thủ tục được lưu trữ sử dụng cột IsAlive, họ chỉ quan tâm nếu một người còn sống chứ không phải DateOfDeath của họ.

Tuy nhiên, cột IsAlive phá vỡ chuẩn hóa cơ sở dữ liệu, vì nó hoàn toàn có thể lấy được từ DateOfDeath. Nhưng vì IsAlive được kết nối cứng vào phần lớn các SP, giải pháp đơn giản là làm cho DateOfDeath không thể rỗng và gán giá trị mặc định cho cột trong trường hợp người đó vẫn còn sống. Một số SP sử dụng DateOfDeath sau đó có thể được viết lại để kiểm tra cột IsAlive và chỉ tôn vinh DateOfDeath nếu người đó không còn sống. Một lần nữa, vì phần lớn các SP chỉ quan tâm đến IsAlive (một chút) chứ không phải DateOfDeath (một ngày) sử dụng mẫu này tăng tốc truy cập đáng kể.

Một tập lệnh T-SQL hữu ích để tìm các cột không thể có không có NULL trên tất cả các lược đồ là:

select 'IF NOT EXISTS (SELECT 1 FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' WHERE ' + QUOTENAME(c.name) + ' IS NULL)
    AND (SELECT COUNT(*) FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ') > 1 PRINT ''' + s.name + '.' + t.name + '.' + REPLACE(c.name, '''', '''''') + ''''
    from sys.columns c
    inner join sys.tables t ON c.object_id = t.object_id
    inner join sys.schemas s ON s.schema_id = t.schema_id
    where c.is_nullable = 1 AND c.is_computed = 0
    order by s.name, t.name, c.name;

Nếu bạn chạy nó trên một bản sao của cơ sở dữ liệu sản xuất của bạn, bạn có thể tìm thấy các nhà phát triển cột được đánh dấu là cho phép các NULL không có NULL trong thực tế. Phần lớn trong số này có thể được đánh dấu là KHÔNG NULL, do đó tăng hiệu suất và giảm không gian lưu trữ.

Có thể không thể loại bỏ tất cả các NULL trong tất cả các bảng và vẫn có thiết kế rõ ràng, nhưng có một lợi thế đáng kể trong việc loại bỏ càng nhiều NULL càng tốt. Trình tối ưu hóa hoạt động nhanh hơn nhiều với thông tin này và nếu bạn có thể loại bỏ tất cả NULL trong một bảng, bạn có thể lấy lại một lượng không gian lưu trữ đáng kể.

Tôi biết rằng hiệu năng không phải là thứ mà các DBA nghĩ về tất cả, nhưng bạn chỉ có thể ném một lượng bộ nhớ và bộ xử lý hạn chế vào một giải pháp, một số điểm bạn sẽ phải bắt đầu nghĩ về thiết kế logic và vật lý .

Cũng lưu ý rằng điều này chỉ dành cho các RDBMS thực sự và tôi đang dựa vào phần kỹ thuật trong các câu trả lời của mình ngoài SQL Server. T-SQL được liệt kê để tìm các cột không có giá trị mà không có null cũng là từ SQL Server.


1
Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
Paul White
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.