Có một lý do thuyết phục tại sao các cột trong SQL là nullable theo mặc định?


8

Là một sinh viên CS, tôi đã học được một số lượng lớn các ngôn ngữ lập trình trong nhiều năm qua, hầu hết trong số đó có một số khái niệm về loại "không thể" hoặc "tùy chọn". Lưu ý rằng tôi không nói về các con trỏ hoặc tham chiếu null hoặc các ngôn ngữ được gõ yếu như JavaScript, nơi mọi thứ đều có thể null. Ví dụ về những gì tôi đang nói đến bao gồm boost::optional(C ++), java.util.Optional(Java 8.0), prelude.Maybe(Haskell) và tất cả các '?' loại (ví dụ int?, float?, C # và Kotlin). Đây là các cấu trúc thêm nullable vào một loại không nullable trước đây trong một hệ thống loại tĩnh, nghiêm ngặt.

SQL có một khái niệm tương tự: một loại như INTEGERcó thể được tạo thành nullable hoặc không nullable - nhưng có một sự thay đổi. Trong SQL, không thể INTEGERrỗng theo mặc định và phải được viết rõ ràng như INTEGER NOT NULLlà không thể rỗng.

Nó gây cho tôi sự phản cảm và cực kỳ nguy hiểm khi cho phép NULL trở thành hành vi mặc định. Rõ ràng SQL đã xuất hiện từ rất lâu tại thời điểm này (hầu hết) các nhà phát triển SQL đã phát triển nhận thức lành mạnh về những cạm bẫy của NULL. Nhưng tôi không thể không tưởng tượng rằng trong những ngày đầu, NULL thường xuất hiện ở những nơi không ngờ tới và có vấn đề.

SQL có trước tất cả các ví dụ tôi đã cung cấp, vì vậy có thể đây đơn giản là vấn đề cho sự tiến hóa lịch sử. Tuy nhiên, tôi phải hỏi, liệu có lý do chính đáng nào để ngôn ngữ được thiết kế theo cách này, với các loại là không thể mặc định?

Nếu vậy, nó chỉ là một lý do lịch sử, hay logic giữ vững thiết kế cơ sở dữ liệu ngày nay?

Chỉnh sửa: Tôi không hỏi tại sao NULL là một phần của SQL hoặc tại sao các cột không thể hữu ích. Tôi chỉ hỏi tại sao cột là nullable theo mặc định . Ví dụ, tại sao chúng ta viết:

column1 FLOAT,
column2 FLOAT NOT NULL

Thay vì:

column1 FLOAT NULLABLE,
column2 FLOAT

2
Học cách chấp nhận câu trả lời này: "Không có lý do, đó chỉ là chính sách của chúng tôi."

2
Bởi vì đôi khi khái niệm "Tôi không biết" phải được trình bày trong cơ sở dữ liệu một cách rõ ràng
Newtopian

@Newtopian giải thích tại sao NULL có trong ngôn ngữ. Tôi đang hỏi tại sao NULL được cho phép các cột theo mặc định.
Tiếp

4
Bởi vì "tôi không biết" rất phổ biến trong thông tin cơ sở dữ liệu. Để minh họa điểm này bằng một ví dụ. Tưởng tượng các biểu mẫu web trong đó MỌI trường bắt buộc theo mặc định và mức độ khó chịu đó sẽ như thế nào. Trong cơ sở dữ liệu, bạn phải điền vào MỌI trường với một cái gì đó, luôn luôn. Tuy nhiên, trong đại diện tên miền của bạn, rất có thể nhiều thông tin này không cần thiết và có thể bị "không xác định" mà không có ảnh hưởng xấu (miễn là bạn bảo vệ mã của mình đúng cách). Trong thực tế, tôi muốn đặt cược rằng trong hầu hết các ứng dụng, hầu hết các thông tin đều thuộc loại không thiết yếu này, do đó được nhìn thấy mặc định
Newtopian

@ Newtopian Được rồi. Hãy trả lời
Tiếp

Câu trả lời:


24

Tại Uni tôi được dạy rằng điều ngược lại là đúng. Nó nguy hiểm hơn nhiều để làm một cái gì đó not nullmà không có lý do. Với một trường không thể, điều tồi tệ nhất có thể xảy ra là bạn vấp phải ứng dụng truy cập dữ liệu. Trời ơi, quay lại và sửa ứng dụng ...

Với trường không null, bạn không thể thêm bản ghi vì một số trường tùy ý không khả dụng. Bây giờ bạn cần thay đổi mô hình dữ liệu và có khả năng sửa kết quả ở RẤT NHIỀU nơi khác nhau ...

Thật tốt khi nghĩ về null"không biết". Nếu có bất kỳ lý do chính đáng nào khiến bạn muốn nhập một bản ghi mà không biết điều gì thì nó sẽ không thể thực hiện được.

Một trong những giảng viên đại học của tôi đã mô tả nó như thế này:

Apocryphally Tôi đã nghe nói về một hệ thống bán hàng ở Hoa Kỳ yêu cầu số an sinh xã hội của khách hàng để bán hàng. Tất cả các nhà khai thác đã làm khi một người nước ngoài đến cho đến khi được nhập 000-00-0000. Nhưng sau đó, những người khác sẽ nhập 123-45-6789. Điều này làm cho nó không thể xác định rác. Sẽ tốt hơn nhiều nếu cho phép một trường trống hơn là buộc nó chứa rác.

Hoặc một câu chuyện khác. Tôi thực sự đã bị từ chối bảo hiểm xe hơi vì tôi không có hai số điện thoại. Họ tuyệt đối sẽ không cho tôi bảo hiểm trừ khi tôi cho họ hai. Anh chàng bán hàng đề nghị tôi chỉ đưa ra một cái giả. Cuối cùng, tôi từ chối nói dối với một công ty bảo hiểm và chỉ đi với một công ty khác.

Trong thực tế dự trữ not nullcho các lĩnh vực được yêu cầu để có ý nghĩa của hồ sơ. Ví dụ:

Một bảng các địa điểm có các trường (ID, Tên địa điểm, Quốc gia, Kinh độ, Vĩ độ) ... "kinh độ" "vĩ độ" sẽ không có giá trị để bạn có thể lưu trữ sự tồn tại của một địa điểm trước khi bạn biết vị trí của nó.

Nhưng nếu bạn có một bảng, mục đích duy nhất của họ là lưu trữ các tọa độ địa lý với các trường (Item_id, kinh độ, vĩ độ) thì toàn bộ bản ghi là vô nghĩa nếu kinh độ và vĩ độ là null. Do đó, trong trường hợp này, chúng không phải là null

Theo kinh nghiệm chuyên môn của tôi kể từ uni, có nhiều lĩnh vực có thể tùy chọn hơn là bắt buộc.


Bạn đang trích dẫn ai trong khối trích dẫn ở trên?
Robert Harvey

Giảng viên đại học.
Philip Couling

8

Nó đánh tôi là cực kỳ phản trực giác ...

Trực giác là trong mắt của kẻ si tình và ý kiến ​​của bạn về điều đó được hình thành bởi những điều mà bạn đã tiếp xúc. Tôi đã có một thời gian khi loại an toàn đó không phải là tiêu chuẩn và các công cụ không chỉ ra khi bạn đi lên. Tôi đã sử dụng cưa xích mà không có bộ phận bảo vệ lưỡi đủ lâu để bản năng đầu tiên của tôi là tránh hoàn toàn trực giác, quay trở lại DDL và tìm hiểu chính xác giả định nào mà lược đồ sẽ cho tôi thực hiện về dữ liệu của nó.

... Và có khả năng nguy hiểm khi cho phép NULL là hành vi mặc định.

Tôi nghĩ rằng bạn đang phóng đại những mối nguy hiểm tương đối. NOT NULLcó những cạm bẫy riêng có thể dẫn đến những lỗi không kém phần nguy hiểm. (Việc liệt kê chúng sẽ là thức ăn cho một câu hỏi khác.)

Người thiết kế một bảng luôn có tùy chọn ràng buộc một cột NULLhoặc NOT NULLvà sẽ thực hiện cái này hoặc cái kia để đi xung quanh mặc định, bất kể đó là gì. Không ràng buộc một cột chính xác là việc nhà phát triển không tuân thủ các quy tắc kinh doanh. Không làm điều đúng đắn ở nơi khác dựa trên định nghĩa của cột là sự thất bại của nhà phát triển để hiểu dữ liệu mà anh ta đang trao. Không có sửa chữa kỹ thuật cho một trong hai.

Tuy nhiên, tôi phải hỏi, liệu có lý do chính đáng nào để ngôn ngữ được thiết kế theo cách này, với các loại là không thể mặc định?

Không, không có. Bởi vì cả hai đều có những mối nguy hiểm, cũng không có lý do chính đáng nào để ngôn ngữ được thiết kế theo cách khác. Nó sôi sùng sục để nhặt chất độc của bạn.


6

Các cột không có giá trị là cần thiết trong SQL do các phép nối ngoài (còn được gọi là các phép nối trái hoặc các phép nối phải). Khi hàng ở một bên của liên kết không khớp với bên kia, các trường cho phía bên kia phải có NULL. Do đầu ra của phép nối có thể có các cột không thể, nên các bảng cơ sở cũng phải hỗ trợ chúng do nguyên tắc đóng quan hệ (về cơ bản nêu rõ kết quả của truy vấn hoặc chế độ xem không thể phân biệt được với bảng cơ sở).

Vì điều này, SQL phải hỗ trợ các cột rỗng. Mặt khác, các cột không thể rỗng là một tính năng phụ - SQL vẫn có thể hoạt động mà không có chúng.


4

Hãy quay lại và nói rằng bạn đúng. Giả sử số nguyên của bạn không phải là null theo mặc định.

Có nghĩa là nó phải có giá trị aa theo mặc định. Ngay cả khi nó không được biết đến.

Vì vậy, khi bạn cập nhật bảng người và bạn có hai lựa chọn: Không thể cập nhật bảng vì bạn không nhập trọng lượng. Hoặc khi bạn không cung cấp đối số trọng lượng, nó sẽ đặt trong "-1 kilo" tiêu chuẩn khi không xác định.

Cả hai tình huống đều không mong muốn. Bạn muốn có thể thêm khách hàng, ngay cả khi bạn không biết trọng lượng của họ. Nhưng ngoài ra, bạn không muốn có các giá trị "proxy". Ví dụ, các giá trị giữ chỗ nhưng có thể có ý nghĩa thực sự: có thể được sử dụng trong các hàm toán học như "trung bình" nhưng không phải là giá trị thực.

Ý tôi là khi tính trọng số trung bình, -1 là một giá trị hợp lệ trong hàm trung bình toán của bạn, nhưng không phải là trọng số của một người. Bạn sử dụng null và bây giờ hàm trung bình của bạn biết bỏ qua giá trị đó.

Ngoài ra, tôi thực sự sẽ không so sánh SQL với các ngôn ngữ lập trình khi thảo luận về null, chúng vốn khác nhau, null trong SQL là một phần của lý thuyết thiết kế cơ sở dữ liệu quan hệ.


3

Không. Không có lý do thuyết phục tại sao SQL mặc định là nullable. Trên thực tế, nhiều nhà nghiên cứu nổi tiếng về lý thuyết cơ sở dữ liệu quan hệ đã không đồng ý với quyết định thiết kế này, có lẽ đáng chú ý nhất là Chris Date , một cộng tác viên thường xuyên với nhà thiết kế ban đầu của cơ sở dữ liệu quan hệ, Edgar Codd . Date (cùng với đồng tác giả Hugh Darwen) đã xuất bản một cuốn sách nổi tiếng về lý thuyết quan hệ (" Tuyên ngôn thứ ba ") mô tả các nguyên tắc cho các thiết kế thay thế cho một gia đình ngôn ngữ quan hệ mà họ gọi là "D", cùng với một ví dụ như ngôn ngữ gọi là " Hướng dẫn D ".

Các ngôn ngữ D được đăng ký rõ ràng từ việc hỗ trợ các giá trị NULL ("D sẽ không bao gồm khái niệm về mối quan hệ của mối quan hệ, trong đó một số tuple vụng trộm bao gồm một số thuộc tính của Drake mà không có giá trị."). Thay vào đó, các giá trị tùy chọn được hỗ trợ bằng cách có các loại dữ liệu thay thế bao gồm dấu vị trí "không có mặt" hoặc các giá trị tương tự. Các ngôn ngữ D cung cấp một mô hình phong phú cho các loại do người dùng xác định sẽ cho phép bất kỳ loại gốc nào được mở rộng với các giá trị bổ sung như vậy.

Có nhiều lý do thuyết phục tại sao đây là một ý tưởng hay và Date & Darwen đã viết rất nhiều về điều này, cũng như các quyết định khác mà họ đưa ra trong thiết kế của họ. Tôi rất khuyên bạn nên đọc công việc của họ về chủ đề này.


1
Tôi không làm theo / không đồng ý với logic của bạn. Tôi tin rằng bạn đang nhầm lẫn hai vấn đề riêng biệt. Vấn đề a) một ngôn ngữ nên đại diện cho null? Vấn đề b) trong một ngôn ngữ sử dụng null có nghĩa là "không có mặt" nên các trường cho phép null (không có mặt) theo mặc định? Có lẽ bạn đã bỏ lỡ một bước trong câu trả lời của mình ... Có một mục c) Trong D, các thuộc tính không được phép không xuất hiện theo mặc định vì .... <chèn đối số ở đây>
Philip Couling

2
Nhận xét đầu tiên của tôi rất khó để theo dõi vì vậy tôi sẽ chỉ đơn giản là: Representing x with null is a bad ideaKhông suy luận điều đó allowing x by default is bad. Ergo nó không ngụ ý rằngallowing null by default is bad where null is the only available representation of x
Philip Couling

1
@jules sự khác biệt mang thai giữa một trường int là nullable và một int-field có một kiểu dữ liệu thay thế: 'không có mặt'? Không phải nó giống với một cái tên khác sao? Null cũng là một kiểu dữ liệu thay thế cho int.
Pieter B

1
@PieterB Có và không. Vấn đề cơ bản của null là nó được sử dụng để chỉ quá nhiều thứ khác nhau. Trong SQL, nó có nghĩa là "không tồn tại" hoặc nó có nghĩa là "không xác định". Đối số D là tất cả những điều này nên được xác định rõ ràng và không bao giờ nên sử dụng "null" tất cả. Không nghiên cứu chi tiết, tôi nghi ngờ rằng những người đề xuất D sẽ ủng hộ việc Not Present = Not PresentSQL không đúng null = nullhoặc null != nullkhông đúng.
Philip Couling

Codd nói rằng nên có nhiều loại Null hơn, tôi nghĩ rằng anh ấy đã đề xuất 4 loại ban đầu và sau đó mở rộng thành 17. Các lập trình viên nói: Tại sao chúng ta lãng phí nỗ lực để phân biệt các cách nói "Tôi không biết"? Chắc chắn, có những ẩn số đã biết, và những ẩn số chưa biết, nhưng thực sự, dữ liệu là những điều đã biết đã biết, và không nhiều điều khác.

1

Tôi không đồng ý với tiền đề của bạn về mặc định là gì, nhưng đó là một cách thực hành tốt để không coi là nhà phát triển. Kiểm tra thông số kỹ thuật trên bảng cơ sở dữ liệu không nên quá khó khăn.

Thêm từ góc độ DBA, nơi bạn sẽ được yêu cầu tải dữ liệu hàng loạt, đặc biệt là khi hợp nhất từ ​​các hệ thống khác, bạn nên biết rõ hơn về cài đặt cho từng trường cho dù bạn có bất kỳ dữ liệu nào để đưa vào đó hay không.

Các doanh nghiệp và ứng dụng được điều hành bởi mọi người. Nếu họ không phải là lập trình viên, định nghĩa "không bao giờ" và "luôn luôn" không hoàn toàn giống nhau và sẽ thay đổi theo thời gian. Cài đặt null hiện tại trên một trường nhất định không nên mờ.


Phải, tải số lượng lớn, di chuyển và cuối cùng vấp phải tất cả các mối quan tâm khác, bởi vì dữ liệu là thực và giá trị, và các chương trình chỉ là công cụ tạm thời định hình nó. Có ai nhìn thấy một thẻ đục lỗ hoặc các máy ghi âm từ điều tra dân số năm 1900? Không, nhưng dữ liệu vẫn có sẵn. Đã bao nhiêu lần nó được chuyển từ hệ thống này sang hệ thống khác, ngay cả trong năm qua? Mỗi khi ai đó sử dụng nó, tôi cho rằng.

0

Cơ sở dữ liệu là những con thú khác nhau từ các ngôn ngữ lập trình bình thường.

Bởi vì lược đồ của bảng được đặt, tất cả dữ liệu cần phải có khi lưu thông tin vào một hàng. Tuy nhiên, nhiều dữ liệu này có thể không được yêu cầu để tạo một đại diện hợp lệ của một đối tượng mô hình một khi được tải trong mã của bạn. Yêu cầu tất cả dữ liệu phải không có giá trị và được điền sẽ có nghĩa là các trường không bắt buộc này sẽ phải chứa một giá trị và chúng chưa có một giá trị nào, chúng là "không xác định".

Hãy tưởng tượng bạn phải điền TẤT CẢ các trường trên các biểu mẫu web TẤT CẢ thời gian vì chúng không thể rỗng trong cơ sở dữ liệu, chúng phải nhận được một giá trị ... một công thức cho sự điên rồ đó là!

Bạn có thể đặt một số giá trị dành riêng để thể hiện sự vắng mặt của dữ liệu, một chuỗi trống, một số cụ thể, một ngày cụ thể, vv tùy thuộc vào loại dữ liệu nhưng nên chọn giá trị nào? Sau đó, bạn cần đảm bảo rằng tất cả mọi người đồng ý rằng các giá trị tùy ý này thực sự có nghĩa là "không xác định" chứ không phải "ngày 1 tháng 1 năm 1970" chẳng hạn. Null ác cảm có thể có nhiều hình thức và đưa bạn đi đường vòng dài phức tạp chỉ vì ai đó nói null là xấu. Làm thế nào phức tạp bạn đã sẵn sàng để có được chỉ để tránh giao dịch với null?

Có một giá trị phổ quát duy nhất cho mọi thứ chưa biết tôi thấy thích hợp hơn là sử dụng một số giá trị hằng số tùy ý. Tôi không nói rằng các giá trị không đổi là xấu và null tốt hơn, nếu mô hình của bạn được phục vụ tốt bởi một hằng số để thể hiện thông tin này thì bằng mọi cách sử dụng điều đó nhưng có nhiều tình huống trong đó null là thứ phù hợp nhất. Đối với tất cả những người ghét null, đây là một tình huống nếu null bị từ chối thì nó sẽ phải được phát minh ra!

Xem mức độ phổ biến của khái niệm "không xác định" trong cơ sở dữ liệu thì phải, tôi nói rằng việc làm cho các giá trị trở thành không thể làm mặc định có ý nghĩa rất lớn.

Đi sâu hơn và xem xét các câu trả lời khác ở đây tôi sẽ không ngạc nhiên khi biết rằng null không chỉ là một "tính năng ngôn ngữ" mà là một phần không thể thiếu của lý thuyết cơ bản mà SQL dựa trên. Người ta có thể loại bỏ C (tốc độ ánh sáng) khỏi thuyết tương đối, nhưng khái niệm tốc độ tối đa tuyệt đối vẫn còn và vẫn phải được thể hiện để nó sẽ trở lại dưới hình dạng hoặc hình dạng nào đó.


0

Câu trả lời ngắn: tương thích ngược.

Câu trả lời dài:

Trong cơ sở dữ liệu được chuẩn hóa hoàn toàn, NULL không được phép trong bất kỳ cột nào. Ví dụ: giả sử có một bảng có tên là MailingAddress có cột PostOfficeBox, đây là một số nguyên. Vì không phải ai cũng có hộp thư bưu điện, nên có hai cách để thực hiện việc này.

Đầu tiên, NULL có thể được cho phép trong cột.

Thứ hai, PostOfficeBox được xóa khỏi MailingAddress và một bảng mới, PostOfficeBox được tạo với Số cột và PK của nó là FK thành MailingAddress. Nhưng bây giờ cần có hai truy vấn để nhận địa chỉ gửi thư: một cho những người không có hộp thư bưu điện và một cho những người có.

SQL cho phép NULL trong các cột cho các mục đích thực tế.

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.