it-swarm-vi.com

SQL: chuỗi rỗng so với giá trị NULL

Tôi biết chủ đề này là một chút tranh cãi và có rất nhiều bài viết/ý kiến ​​khác nhau nổi trên internet. Thật không may, hầu hết trong số họ cho rằng người đó không biết sự khác biệt giữa NULL và chuỗi rỗng là gì. Vì vậy, họ kể những câu chuyện về kết quả đáng ngạc nhiên với các phép nối/tổng hợp và thường làm các bài học SQL nâng cao hơn một chút. Bằng cách này, họ hoàn toàn bỏ lỡ toàn bộ vấn đề và do đó vô dụng đối với tôi. Vì vậy, hy vọng câu hỏi này và tất cả các câu trả lời sẽ di chuyển chủ đề một chút về phía trước.

Giả sử tôi có một bảng chứa thông tin cá nhân (tên, ngày sinh, v.v.) trong đó một trong các cột là địa chỉ email có kiểu varchar. Chúng tôi cho rằng vì một số lý do, một số người có thể không muốn cung cấp địa chỉ email. Khi chèn dữ liệu đó (không có email) vào bảng, có hai lựa chọn khả dụng: đặt ô thành NULL hoặc đặt thành chuỗi trống (''). Giả sử rằng tôi nhận thức được tất cả các ý nghĩa kỹ thuật của việc chọn một giải pháp trên một giải pháp khác và tôi có thể tạo các truy vấn SQL chính xác cho cả hai kịch bản. Vấn đề là ngay cả khi cả hai giá trị khác nhau ở cấp độ kỹ thuật, chúng hoàn toàn giống nhau ở mức logic. Sau khi nhìn vào NULL và '' Tôi đã đi đến một kết luận duy nhất: Tôi không biết địa chỉ email của anh chàng. Ngoài ra, bất kể tôi đã cố gắng thế nào, tôi cũng không thể gửi e-mail bằng cách sử dụng NULL hoặc chuỗi trống, vì vậy rõ ràng hầu hết các máy chủ SMTP ngoài đó đều đồng ý với logic của tôi. Vì vậy, tôi có xu hướng sử dụng NULL khi tôi không biết giá trị và coi chuỗi rỗng là một điều xấu.

Sau một số cuộc thảo luận căng thẳng với các đồng nghiệp, tôi đã đưa ra hai câu hỏi:

  1. tôi có đúng không khi cho rằng việc sử dụng chuỗi rỗng cho một giá trị không xác định sẽ khiến cơ sở dữ liệu "nói dối" về các sự kiện? Nói chính xác hơn: sử dụng ý tưởng của SQL về giá trị là gì và không phải là gì, tôi có thể đi đến kết luận: chúng tôi có địa chỉ email, chỉ bằng cách tìm ra nó không phải là null. Nhưng sau đó, khi cố gắng gửi e-mail, tôi sẽ đi đến kết luận mâu thuẫn: không, chúng tôi không có địa chỉ e-mail, rằng cơ sở dữ liệu @! # $ Phải nói dối!

  2. Có kịch bản logic nào trong đó một chuỗi rỗng '' có thể là một nhà cung cấp thông tin quan trọng tốt như vậy (bên cạnh giá trị và không có giá trị), sẽ gây rắc rối/không hiệu quả khi lưu trữ theo bất kỳ cách nào khác (như cột bổ sung). Tôi đã thấy nhiều bài đăng cho rằng đôi khi sử dụng chuỗi rỗng cùng với các giá trị thực và NULL là tốt, nhưng cho đến nay vẫn chưa thấy một kịch bản nào hợp lý (về mặt thiết kế SQL/DB).

P.S. Một số người sẽ bị cám dỗ để trả lời, rằng đó chỉ là vấn đề sở thích cá nhân. Tôi không đồng ý. Đối với tôi đó là một quyết định thiết kế với những hậu quả quan trọng. Vì vậy, tôi muốn xem câu trả lời trong đó opion về điều này được hỗ trợ bởi một số lý do hợp lý và/hoặc kỹ thuật.

73
Jacek Prucia

Tôi sẽ nói rằng NULL là lựa chọn chính xác cho "không có địa chỉ email". Có nhiều địa chỉ email "không hợp lệ" và "" (chuỗi trống) chỉ là một. Ví dụ: "foo" không phải là địa chỉ email hợp lệ, "a @ b @ c" không hợp lệ, v.v. Vì vậy, chỉ vì "" không phải là một địa chỉ email hợp lệ là không có lý do để sử dụng nó làm giá trị "không có địa chỉ email".

Tôi nghĩ rằng bạn đã đúng khi nói rằng "" không phải là cách chính xác để nói "Tôi không có giá trị cho cột này". "" một giá trị.

Một ví dụ về nơi "" có thể là một giá trị hợp lệ, tách biệt với NULL có thể là tên đệm của một người. Không phải ai cũng có tên đệm, vì vậy bạn cần phân biệt giữa "không có tên đệm" ("" - chuỗi trống) và "Tôi không biết người này có tên đệm hay không" (NULL ). Có thể có nhiều ví dụ khác trong đó một chuỗi rỗng vẫn là một giá trị hợp lệ cho một cột.

84
Dean Harding

Trong khi đồng ý với các ý kiến ​​trên, tôi sẽ thêm đối số này làm động lực chính:

  1. Rõ ràng với bất kỳ lập trình viên nào nhìn vào cơ sở dữ liệu rằng một trường được đánh dấu NULL là một trường Tùy chọn. (tức là bản ghi không yêu cầu dữ liệu cho cột đó)
  2. Nếu bạn đánh dấu một trường KHÔNG NULL, bất kỳ lập trình viên nào nên trực giác cho rằng đó là trường Bắt buộc.
  3. Trong một trường cho phép null, các lập trình viên sẽ mong đợi thấy null hơn là các chuỗi rỗng.

Vì mục đích Tự viết mã hóa trực quan, hãy sử dụng NULL thay vì các chuỗi trống.

41
colinbashbash

Trong ví dụ của bạn nếu đó là giá trị trực tiếp từ trường web - tôi sẽ sử dụng chuỗi rỗng. Nếu người dùng có thể tùy chọn chỉ định rằng anh ta không muốn cung cấp email hoặc có thể xóa nó - thì NULL.

Dưới đây là liên kết với các điểm mà bạn có thể xem xét: https://stackoverflow.com/questions/405909/null-vs-empty-when-deals-with-user-input/405945#405945

--- đã chỉnh sửa (Trả lời bình luận của Thomas) ---

Cơ sở dữ liệu không tồn tại nếu không có các ứng dụng sử dụng chúng. Xác định NULL hoặc '' không có giá trị, nếu ứng dụng không thể sử dụng đúng cách.

Hãy xem xét một ví dụ trong đó người dùng điền vào biểu mẫu LONG và nhấn enter, điều đó sẽ gửi yêu cầu liên tục đến máy chủ. Anh ta có thể ở giữa nhập email của mình. Hầu hết có lẽ bạn muốn lưu trữ bất cứ thứ gì anh ta có trong trường email, để sau này anh ta có thể hoàn thành nó. Nếu anh ta chỉ nhập một ký tự thì sao? Điều gì nếu anh ta nhập một ký tự và sau đó xóa nó? Khi email không bắt buộc, đôi khi người dùng muốn xóa nó: cách dễ nhất để xóa trường. Ngoài ra trong trường hợp khi email không bắt buộc, nó đáng để xác nhận nó trước khi gửi.

Một ví dụ khác: người dùng cung cấp email dưới dạng spamto @ [bigcompany] .com - trong trường hợp đó không cần gửi email, ngay cả như vậy nó vẫn tồn tại và hợp lệ (và thậm chí có thể tồn tại). Gửi một cái như vậy có thể rẻ, nhưng nếu có 10K người dùng có email như vậy để đăng ký hàng ngày, thì việc xác thực như vậy có thể tiết kiệm rất nhiều thời gian.

6
Konstantin Petrukhnov

Sử dụng Null.

Không có điểm nào để lưu trữ giá trị '', khi chỉ cần làm cho trường trong bảng không thể thực hiện được. Nó làm cho các truy vấn rõ ràng hơn quá.

Truy vấn SQL nào rõ ràng và dễ đọc hơn nếu bạn muốn tìm người dùng có địa chỉ email?

  1. SELECT * FROM Users WHERE email_address != ''

  2. SELECT * FROM Users WHERE email_address IS NOT NULL

  3. SELECT * FROM Users WHERE email_address != '' and email_address IS NOT NULL

Tôi sẽ nói 2 là. Mặc dù 3 mạnh hơn trong trường hợp dữ liệu xấu được lưu trữ.

Đối với trường hợp địa chỉ email trên biểu mẫu, là tùy chọn, nó cũng sẽ được phản ánh trong bảng. Trong SQL, đó là một trường không thể, có nghĩa là nó không được biết đến.

Tôi không thể nghĩ ra bất kỳ giá trị kinh doanh hợp lý nào trong việc lưu trữ một chuỗi trống trong một bảng khác với thiết kế đơn giản là xấu. Giống như lưu trữ giá trị chuỗi là 'NULL' hoặc 'BLANK' và có nhà phát triển giả sử rằng nó không có giá trị hoặc một chuỗi rỗng. Đối với tôi, đó là thiết kế tồi. Tại sao lưu trữ khi có NULL ??

Chỉ cần sử dụng NULL, và bạn sẽ khiến mọi người hạnh phúc hơn một chút.

THÔNG TIN THÊM:

SQL sử dụng hệ thống logic ba giá trị: Đúng, Sai và Không xác định.

Để giải thích rõ hơn và chi tiết hơn, tôi khuyên các nhà phát triển nên đọc: Truy vấn SQL - ngoài TRUE và FALSE .

5
spong

Thật không may, Oracle đã nhầm lẫn việc biểu diễn chuỗi VARCHAR có độ dài bằng 0 với đại diện của NULL. Cả hai đều được biểu diễn bên trong bởi một byte đơn có giá trị 0. Điều này làm cho cuộc thảo luận khó khăn hơn nhiều.

Rất nhiều sự nhầm lẫn xung quanh các trung tâm NULL xung quanh logic ba giá trị. Hãy xem xét các mã giả sau đây:

if ZIPCODE = NULL
    print "ZIPCODE is NULL"
else if ZIPCODE <> NULL
    print "ZIPCODE is not NULL"
else print "Something unknown has happened"

Bạn sẽ không mong đợi tin nhắn thứ ba, nhưng đó là những gì bạn sẽ nhận được, theo ba logic có giá trị. Ba logic có giá trị dẫn mọi người tới nhiều lỗi.

Một nguồn gây nhầm lẫn khác là rút ra những suy luận từ việc không có dữ liệu, như vẽ một suy luận từ con chó không sủa trong đêm. Thông thường những suy luận này không phải là những gì nhà văn của NULL dự định cnvey.

Phải nói rằng, có rất nhiều tình huống mà NULL xử lý việc không có dữ liệu tốt và tạo ra kết quả chính xác mà bạn muốn. Một ví dụ là khóa ngoại trong các mối quan hệ tùy chọn. Nếu bạn sử dụng NULL để biểu thị không có mối quan hệ nào trong một hàng nhất định, hàng đó sẽ thoát khỏi liên kết bên trong, giống như bạn mong đợi.

Ngoài ra, hãy lưu ý rằng ngay cả khi bạn tránh NULLS hoàn toàn trong dữ liệu được lưu trữ (dạng bình thường thứ sáu), nếu bạn thực hiện bất kỳ phép nối ngoài nào, bạn vẫn sẽ phải đối phó với NULLS.

5
Walter Mitty

Tôi nghĩ rằng câu trả lời của Dean Hardings thực sự độc đáo. Điều đó nói rằng tôi muốn đề cập rằng khi nói về NULL và chuỗi trống ở cấp DB, bạn nên suy nghĩ về các loại dữ liệu khác của mình. Bạn sẽ lưu trữ ngày tối thiểu khi không có ngày được cung cấp? hoặc -1 khi không có int được cung cấp? Lưu trữ một giá trị khi bạn không có giá trị nghĩa là bạn phải theo dõi toàn bộ phạm vi của các giá trị không. Ít nhất một cho mỗi loại dữ liệu (có thể nhiều hơn khi bạn gặp trường hợp trong đó -1 là một giá trị thực tế, do đó bạn cần phải có một số thay thế, v.v.). Nếu bạn cần/muốn làm một cái gì đó "mập mờ" ở cấp ứng dụng đó là một điều nhưng họ không cần phải làm ô nhiễm dữ liệu của bạn.

5
bendemes

đối với câu hỏi kỹ thuật cụ thể, vấn đề không phải là null so với chuỗi rỗng, đó là một lỗi xác thực. Một chuỗi trống không phải là một địa chỉ email hợp lệ!

đối với câu hỏi triết học, câu trả lời là tương tự: xác nhận đầu vào của bạn. Nếu một chuỗi rỗng là một giá trị hợp lệ cho trường được đề cập, thì hãy mong đợi nó và mã cho nó; nếu không, sử dụng null.

Một chuỗi rỗng sẽ là một đầu vào hợp lệ để trả lời câu hỏi: Mime đã nói gì với hươu cao cổ?

3
Steven A. Lowe

Tôi có thể nghĩ ra một lý do để có NULL và chuỗi trống:

  • Bạn có địa chỉ email hợp lệ: [email protected]
  • Bạn không có ai (và có lẽ nên yêu cầu một): NULL
  • Bạn biết rằng người này không có địa chỉ email: Empty String.

Tuy nhiên tôi sẽ không khuyến nghị điều đó và sử dụng một trường riêng cho việc hỏi xem bạn có biết rằng không có cái nào tồn tại không.

2
Marcel

Câu hỏi theo tôi hiểu là, nên chọn cách giải thích nào về NULL và chuỗi rỗng. Điều này phụ thuộc vào số lượng trạng thái trường particualar có thể nằm trong.

Việc giải thích phụ thuộc vào cách cơ sở dữ liệu đang được truy cập. Nếu có một lớp trong mã tóm tắt hoàn toàn cơ sở dữ liệu, thì việc chọn bất kỳ chính sách nào (bao gồm hai coulmn) hoạt động là hoàn toàn chấp nhận được. (Tuy nhiên, rõ ràng tài liệu chính sách là quan trọng). Tuy nhiên, nếu cơ sở dữ liệu đang được truy cập ở một số nơi, thì bạn nên sử dụng một sơ đồ rất đơn giản, vì mã sẽ khó bảo trì hơn và có thể bị lỗi trong trường hợp này.

1
apoorv020

Về cơ bản, ở mức logic, không có sự khác biệt giữa giá trị "không hợp lệ" và "không có đầu vào của người dùng", hầu hết chúng chỉ là "trường hợp đặc biệt". Trường hợp lỗi.

Có null mất không gian bổ sung: ceil (Cột_with_null/8) tính bằng byte/mỗi hàng.

Ô trống và null đều là cách để đánh dấu một cái gì đó sai/nên được mặc định. Tại sao bạn cần 2 trạng thái "sai"? Tại sao sử dụng NULL nếu chúng chiếm không gian bổ sung và có nghĩa chính xác giống như chuỗi trống? Điều đó sẽ chỉ gây ra sự nhầm lẫn và dư thừa khi bạn có hai ý nghĩa (có thể có nghĩa) giống hệt nhau, thật dễ dàng để quên rằng bạn nên sử dụng NULL thay vì chuỗi rỗng (ví dụ: người dùng sử dụng một số trường).

Và dữ liệu của bạn có thể trở thành một mớ hỗn độn. Trong một thế giới hoàn hảo, bạn sẽ nói "dữ liệu sẽ luôn chính xác và tôi sẽ nhớ" ... nhưng khi mọi người phải làm việc trong một nhóm và không phải ai cũng chính xác ở cấp độ của bạn thì không có gì lạ khi thấy WHERE (aa. xx <> '' VÀ bb.zz IS KHÔNG PHẢI)

Vì vậy, thay vì sửa các thành viên trong nhóm của tôi mỗi ngày, tôi chỉ thực thi quy tắc đơn giản. Không có giá trị null, KHÔNG BAO GIỜ!

Đếm các giá trị NON-NULL nhanh hơn ... câu hỏi đơn giản là bạn cần làm điều đó để làm gì?

1
Slawek

Tôi có xu hướng xem nó không phải từ góc độ DB mà từ góc độ chương trình. Tôi biết rằng câu hỏi này dành cho nhấp chuột SQL nhưng thực sự, có bao nhiêu người dùng truy cập dữ liệu trực tiếp nữa?

Trong một chương trình tôi không thích null/không có gì. Có một vài ngoại lệ nhưng chúng chỉ có vậy. Và những ngoại lệ đó thực sự chỉ là những triển khai tồi.

Vì vậy, nếu người dùng không gửi email, cần có một cái gì đó xác định xem điều này có hợp lệ hay không. Nếu một email trống là tốt thì nó sẽ hiển thị một chuỗi trống. Nếu người dùng không đặt email và vi phạm quy tắc, đối tượng sẽ chỉ ra điều này.

Ý tưởng về null có ý nghĩa là trường học cũ và là thứ mà các lập trình viên hiện đại phải làm việc xung quanh.

Ngay cả trong thiết kế DB, tại sao trường email không cho phép null và có chuỗi có độ dài bằng 0 và có trường khác cho biết người dùng có nhập gì không? Là một bit mà nhiều để hỏi về một DBMS? Theo tôi, DB không nên xử lý logic nghiệp vụ cũng như logic hiển thị. Nó không được chế tạo cho điều đó và do đó làm rất kém công việc xử lý nó.

1
ElGringoGrande