web-dev-qa-db-ja.com

SQL:空の文字列とNULL値

この話題は少し物議を醸していることを知っており、インターネット上にはさまざまな記事や意見が浮かんでいます。残念ながら、ほとんどの人は、その人はNULLと空の文字列の違いが何であるかを知らないと想定しています。そのため、彼らは結合/集計での驚くべき結果についてストーリーを伝え、一般的にはもう少し高度なSQLレッスンを行います。これを行うことで、彼らは全体の要点を完全に逃し、したがって私には役に立たない。したがって、うまくいけば、この質問とすべての回答が少し前に進みます。

個人情報(名前、出生など)を含むテーブルがあり、列の1つがvarcharタイプの電子メールアドレスであるとします。何らかの理由で、電子メールアドレスの提供を望まない場合があると想定しています。そのようなデータ(電子メールなし)をテーブルに挿入する場合、2つの選択肢があります。セルをNULLに設定するか、空の文字列( '')に設定します。あるソリューションを他のソリューションよりも選択することのすべての技術的影響を認識しており、どちらのシナリオでも正しいSQLクエリを作成できると仮定します。問題は、両方の値が技術レベルで異なる場合でも、論理レベルではまったく同じであるということです。 NULLと ''を調べた後、私は1つの結論に達しました。その人の電子メールアドレスがわかりません。また、どんなに頑張っても、NULLまたは空の文字列を使用して電子メールを送信できなかったので、そこにあるほとんどのSMTPサーバーは私のロジックに同意しています。だから私は値がわからない空の文字列を悪いものと見なす場所でNULLを使用する傾向があります。

同僚との激しい議論の後、私は2つの質問をしました。

  1. 不明な値に空の文字列を使用すると、データベースが事実について「嘘をつく」と私は思いますか?より正確に言うと、何が価値で何がそうではないかというSQLの考えを使用すると、結論に達する可能性があります。電子メールアドレスはnullではないことがわかるだけでわかります。しかし、その後、電子メールを送信しようとすると、矛盾する結論に達します。いいえ、電子メールアドレスがないので、@!#$データベースは嘘をついていたに違いありません。

  2. 空の文字列 ''が重要な情報(値と値以外)の優れたキャリアになる可能性がある論理的なシナリオはありますか?空の文字列を実際の値とNULLと共に使用するのが良い場合があると主張する多くの投稿を見てきましたが、これまでのところ、論理的なシナリオ(SQL/DB設計の観点から)は見ていません。

追伸個人的な好みの問題だと答えたくなる人もいます。同意しません。私にとってそれは重要な結果を伴う設計上の決定です。だから私はこれについての意見がいくつかの論理的および/または技術的な理由に裏付けられている答えを見てみたいです。

73
Jacek Prucia

NULLは「メールアドレスなし」の正しい選択だと思います。 多くの「無効な」メールアドレスがあり、「」(空の文字列)は1つだけです。たとえば、「foo」は有効なメールアドレスではなく、「a @ b @ c」は無効です。したがって、「」が有効なメールアドレスではないからといって、それを「メールアドレスなし」の値として使用する理由はありません。

「この列には値がありません」という正しい言い方は「」ではないとあなたは言っているのは正しいと思います。 "" is値。

""が有効な値である例は、NULLとは別に、人のミドルネームである場合があります。すべての人がミドルネームを持っているわけではないので、「ミドルネームなし」(「」-空の文字列)と「この人にミドルネームがあるかどうかわからない」(NULL)を区別する必要があります)。空の文字列がまだ列の有効な値である他の多くの例があります。

84
Dean Harding

上記のコメントに同意しながら、私はこの議論を主な動機として追加します。

  1. NULLとマークされたフィールドがオプションフィールドであることは、データベースを調べているプログラマーには明らかです。 (つまり、レコードはその列のデータを必要としません)
  2. フィールドにNOT NULLのマークを付けた場合、プログラマーはそれを必須フィールドであると直感的に想定する必要があります。
  3. Nullを許可するフィールドでは、プログラマーは空の文字列ではなくnullが表示されることを期待する必要があります。

Self-Documenting Intuitive Codingのために、空の文字列ではなくNULLを使用します。

41
colinbashbash

あなたの例ではそれがウェブフィールドから直接値である場合-私は空の文字列を使用します。ユーザーがメールを提供したくないことを指定するオプションを選択できる場合、またはメールを削除できる場合-NULL。

ここにあなたが考慮できるポイントとのリンクがあります: https://stackoverflow.com/questions/405909/null-vs-empty-when-dealing-with-user-input/405945#405945

---編集(トーマスのコメントへの返信)---

データベースは、それを使用するアプリケーションなしでは機能しません。NULLまたは ''の定義は、アプリケーションが適切に使用できない場合、値がありません。

ユーザーがLONGフォームに入力してEnterキーを押すと、永続的なリクエストがサーバーに送信される例を考えてみます。メールを入力している最中である可能性があります。ほとんどの場合、彼が電子メールフィールドに持っているものをすべて保存したいので、後で彼はそれを完成させることができます。 1文字だけ入力した場合はどうなりますか? 1文字入力してから削除するとどうなりますか?メールが不要な場合、ユーザーはメールを削除したいことがあります。フィールドをクリアする最も簡単な方法です。また、電子メールが不要な場合は、送信前に検証することをお勧めします。

別の例:ユーザーが電子メールをspamto @ [bigcompany] .comとして提供する-その場合、電子メールが存在し、有効である(存在することもある)場合でも、電子メールを送信する必要はありません。そのような1つを送信するのは安上がりかもしれませんが、そのような電子メールを毎日購読する10Kのユーザーがいる場合、そのような検証により多くの時間を節約できます。

Nullを使用します。

''の値を格納しても意味がありません。単にテーブルのフィールドをnullにできるようにするだけで十分です。クエリもわかりやすくなります。

メールアドレスを持つユーザーを見つけたい場合、どのSQLクエリがより明白で読みやすいですか?

  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

2だと思います。不正なデータが保存されている場合は、3の方が堅牢です。

フォーム上のメールアドレスの場合はオプションですが、それも表に反映されている必要があります。 SQLでは、これはNULL可能フィールドです。つまり、不明です。

テーブルに空の文字列を格納することには、単に悪いデザイン以外に、妥当なビジネス上の価値はありません。これは、「NULL」または「空白」の文字列値を格納し、開発者assumeがいるようなものですnullまたは空の文字列です。私には、それは悪いデザインです。 NULLがあるときに、なぜそれを格納するのですか?

NULLを使用するだけで、みんながもう少し幸せになります。

詳細情報:

SQLは、True、False、Unknownの3つの値の論理システムを使用します。

より適切で詳細な説明については、開発者に以下を読むことをお勧めします SQLクエリ– TRUEおよびFALSEを超えて

5
spong

残念ながら、Oracleは長さがゼロのVARCHAR文字列の表現をNULLの表現と混同していました。どちらも内部的には、値がゼロの1バイトで表されます。これは、議論をそれほど難しくします。

NULLを取り巻く多くの混乱は、つの値を持つロジックを中心にしています。次の疑似コードを考えてみます。

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

3番目のメッセージを期待することはできませんが、3つの重要なロジックの下でそれが得られます。 3つの重要なロジックは、多くのバグに人々を導きます。

混乱のもう1つの原因は、データがないことから推論を引き出すことです。たとえば、夜に吠えなかった犬から推論を引き出すことです。多くの場合、これらの推論は、NULLの作成者が意図したものではありませんでした。

そうは言っても、NULLがデータの欠如をうまく処理し、希望する結果を正確に生成する状況はたくさんあります。 1つの例は、オプションの関係の外部キーです。 NULLを使用して特定の行に関係がないことを示す場合、その行は期待どおりに内部結合から削除されます。

また、格納されたデータ(第6正規形)でNULLSを完全に回避したとしても、外部結合を行う場合でも、NULLSに対処する必要があることに注意してください。

5
Walter Mitty

ディーン・ハーディングスの回答はこれを本当にうまくカバーしていると思います。そうは言っても、DBレベルでのNULLと空の文字列について話すときは、他のデータ型について考える必要があることを述べておきたいと思います。日付が指定されていないときに最小日付を保存しますか?または、intが指定されていない場合は-1ですか?値がないときに値を格納するということは、値以外の範囲全体を追跡する必要があるということです。各データ型に少なくとも1つ(おそらく-1が実際の値である場合に取得するため、いくつかの代替が必要になるなど)アプリケーションレベルで「あいまい」なことを行う必要がある場合は、1つのことですが、データを汚染する必要はありません。

5
bendemes

特定の技術的な質問の場合、問題はnullと空の文字列ではなく、検証エラーです。空の文字列は有効なメールアドレスではありません!

哲学的な質問の場合、答えは似ています。入力を検証します。空の文字列が問題のフィールドの有効な値である場合は、それを予期してコード化します。そうでない場合は、nullを使用します。

空の文字列は、質問に答えるための有効な入力になります。キリンに対してMIMEは何と言いましたか?

3
Steven A. Lowe

NULLと空の文字列がある理由を考えることができます。

  • 有効なメールアドレスがあります:[email protected]
  • あなたは何も持っていません(そしておそらく尋ねる必要があります):NULL
  • この人にはメールアドレスがありません:Empty String.

しかし、私はそれをお勧めせず、何も存在しないことを知っているかどうかを尋ねるかどうかを尋ねる別のフィールドを使用します。

2
Marcel

私が理解している質問は、NULLと空の文字列のどちらの解釈を選択すべきかということです。これは、特定のフィールドをいくつstatesに含めることができるかによって異なります。

解釈は、データベースへのアクセス方法によって異なります。コードにデータベースを完全に抽象化するレイヤーがある場合、機能するポリシー(2つの列を含む)を選択することは完全に許容されます。 (ただし、ポリシーを明確に文書化することは重要です)。ただし、データベースが複数の場所でアクセスされている場合は、非常に単純なスキームを使用する必要があります。コードの保守が難しくなり、この場合はエラーになる可能性があるためです。

1
apoorv020

基本的に論理レベルでは、「無効な」値と「ユーザー入力がない」の間に違いはありません。ほとんどの場合、これらはすべて「特殊なケース」にすぎません。エラーケース。

Nullがあると、追加のスペースが必要になります:ceil(columns_with_null/8)(バイト/行)。

空のセルとnullは、何かが間違っていることを示すための両方の方法です/デフォルトにする必要があります。なぜ2つの「間違った」状態が必要なのですか?追加のスペースを取り、空の文字列とまったく同じ意味になるのに、なぜNULLを使用するのですか?これは、2つの意味(つまり、同じ意味)がまったく同じ場合に混乱と冗長性をもたらすだけで、空の文字列ではなくNULLを使用する必要があることを忘れがちです(たとえば、ユーザーが一部のフィールドを省略した場合)。

そして、あなたのデータは混乱する可能性があります。完璧な世界では、「データは常に正しいので、覚えておきます」と言いますが、人々がチームで作業しなければならず、誰もがあなたのレベルに正確にいるわけではない場合、どこにあるかを見るのは珍しいことではありません(aa。 xx <> '' AND bb.zz IS NOT NULL)

ですから、隔日でチームメンバーを修正するのではなく、単純なルールを適用します。 null値はありません。

NON-NULL値のカウントはより高速です...簡単な質問は、何のためにそれを行う必要があるでしょうか?

1
Slawek

私はそれをDBの観点からではなくプログラムの観点から見る傾向があります。この質問はSQLクリックに関するものであることは知っていますが、実際には、直接何人のユーザーがデータに直接アクセスするのでしょうか。

プログラムでは、null/nothingは好きではありません。いくつかの例外がありますが、それだけです。そして、それらの例外は本当に悪い実装です。

したがって、ユーザーが電子メールを入力しなかった場合、これが有効かどうかを判断するものがあるはずです。空白のメールで問題ない場合は、空白の文字列が表示されます。ユーザーが電子メールを入力しておらず、それがルールに違反している場合、オブジェクトはこれを示す必要があります。

Nullに意味があるという考えは古い学校であり、現代のプログラマーが回避しなければならないものです。

DB設計でさえ、なぜ電子メールフィールドはnullを許可せず、長さがゼロの文字列を持ち、ユーザーが何かを入力したかどうかを示す別のフィールドを持つことができないのですか? DBMSに1つ質問することはありますか?私の意見では、DBはビジネスロジックも表示ロジックも処理すべきではありません。それはそのために作られたわけではないので、それを扱うのは非常に貧弱な仕事です。

1
ElGringoGrande