SQL:空の文字列とNULL値


72

私はこの主題が少し物議を醸すことを知っています、そして、インターネットの周りに浮かんでいる多くの様々な記事/意見があります。残念ながら、それらのほとんどは、その人がNULLと空の文字列の違いを知らないことを前提としています。そのため、結合/集計を使用した驚くべき結果についてのストーリーを伝え、一般にもう少し高度なSQLレッスンを行います。これを行うことで、彼らは絶対に全体のポイントを見逃し、したがって私にとって役に立たない。したがって、この質問とすべての回答が主題を少し前進させることを願っています。

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

同僚との激しい議論の後、2つの質問がありました。

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

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

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


11
Oracleでは、空の文字列 NULL であることを知っていますか?
user281377

8
@ammoQ:長さゼロの文字列のOracleの扱いは非標準です。また、''Oracleでも、とは異なりますNULL。たとえば、CHAR(1)列に値''を割り当てると、' 'ではなく(スペース)になりNULLます。さらに、JacekがOracleを使用している場合、この質問はおそらく出てこないでしょう:
Dean Harding

2
Dean:char(1)の例については正しいですが、PL / SQLで'' IS NULL評価されるので、これは別のWTF trueです。
user281377

「未知の値に空の文字列を使用すると、データベースが事実について「嘘をつく」ことになりますか?」あなたのビジネスユーザーが未知か空かを気にしないなら、嘘さえ重要ですか?
アンディ

文字列を使用するルートに行く必要がある場合は、空であることを確認してください。すべての開発者のために、スペースを含む文字列に未知の値を表させないでください。お願いです。
Airn5475

回答:


83

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

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

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


5
完全に同意する。NULLには理由があります。電子メールがどこにあるのかを選択してください(NOT NOT)NULLはそれを行う方法であり、遅くなる傾向のある文字列比較ではありません(空の文字列であっても、これはわかりません:)。
LudoMC

5
私が考えるNULL何のメールアドレスがないことを意味するものではありません、私はそれが電子メールアドレスが現在存在することが知られていない、知られている、または他の理由で埋めることは不可能であるされていないことを意味だと思います。幸いなことに、本当にメールアドレスを持っていない人やメールアドレスを持っているつもりのない人に関する情報をデータベースに保持したい状況はおそらくないでしょう。
アレクセイ

9
@Alexey-NULLは値がないことを意味します。他の人が指摘したように、空の文字列は値です。
ラムハウンド

3
@Ramhound、空の文字列は値であり、NULLは漠然と「値がない」ことを意味することに同意します。「価値がない」という解釈を説明しました。私の意見では、それは「その人がメールアカウントを開設していない」と同じではありません。むしろ「その人のメールアドレスは記録されていません」。
アレクセイ

5
@Ramhound NULLは、値がないことを意味します。ミドルネームのない人には価値がありません。そのため、中間の初期列にもNULLを使用する必要があります...これは、この回答に示されている引数とは正反対です。
イズカタ

41

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

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

Self-Documenting Intuitive Codingのために、空の文字列の代わりにNULLを使用します。


4
+1これは、空の文字列に対する開発者に関する「最小限の驚き」の議論です。後に来る開発者は、空の文字列が「電子メールアドレスなし」を表すために使用されることを期待しません。
トーマス

6

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

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

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

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

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

別の例:ユーザーが電子メールをspamto @ [bigcompany] .comとして提供する-その場合、電子メールが存在していて有効である場合でも(存在する場合もあります)、電子メールを送信する必要はありません。そのような安価なものを送信することもできますが、毎日のサブスクリプションでそのような電子メールを使用する1万人のユーザーがいる場合、そのような検証により多くの時間を節約できます。


7
-1。データベースがWebサイトを駆動しているかどうかは関係ありません。データベースの設計は、Webデザインとは異なる世界です。データベースは、書き込みに使用されるインターフェイスに関係なく、ビジネスドメインに関する事実を取得するように設計する必要があります。ロジックでは、偶然に最初のアプリケーションが実行可能ファイルである場合、nullを使用する必要がありますか?最初のアプリがWebアプリケーションで、次のアプリケーションがモバイルアプリの場合はどうなりますか?データベースを設計して、正規化ルールを使用してファクトをキャプチャし、それに書き込むWebサイトを設計します。
トーマス

このサイトの書き方とコメントの仕方を学んだことを嬉しく思います:) DBはそれを使用するアプリケーションをサポートするべきだとまだ信じています。編集した回答を確認してください。
コンスタンチンペトルフノフ

4
データベースは、データベースを使用するアプリケーションなしでは存続しません。私の経験では、これは単に真実ではなく、近視眼的ではありません。ほとんどの場合、データベースは、設計されたアプリケーションの外部で使用されます。一般に、データベースは、構築されたアプリケーションよりも長く存続します。データベースは、ビジネスに関する事実を収集するように設計する必要があり、UIは、他の方法ではなく、データベースを読み書きするように構築する必要があります。リレーショナル設計は、アプリケーション設計とはまったく異なる考え方です。
トーマス

2
データベースが元のアプリケーションだけで使用れない例:レポート、他のシステムとの統合。
トーマス

1
Thomasが示したように、DBは複数のアプリケーションで使用されることが多く、多くの場合、DBデータをクリーンに保つという考え方に重みを加えます。アプリケーションでNULLを使いたくない/処理できない場合は、データアクセスレイヤーで単純に「マジック値」(素敵な説明Thomas)に置き換えることができます。このようにして、DBにアクセスしたい将来のアプリケーションは、元のアプリケーションのマジック値について知る必要がありません。
ベンデム

5

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


2
+1-これは私が「マジックバリューソリューション」と呼んでいるものです。値が存在しないことを表すために、各データ型のマジック値を作成する必要があります。さらに、一部の列では、共通のマジック値が正当な値であるか、または正当な値になるため、新しいマジック値が必要です。
トーマス

5

残念ながら、Oracleは長さゼロのVARCHAR文字列の表現とNULLの表現を混同していました。これらは両方とも、値ゼロの単一バイトによって内部的に表されます。これにより、議論が非常に難しくなります。

NULLを取り巻く混乱の多くは、3値のロジックに集中しています。次の擬似コードを検討してください。

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つの原因は、夜間にdidnえなかった犬から推論を描くなど、データがないことから推論を引き出すことです。多くの場合、これらの推測は、NULLの作成者が意図したものではありませんでした。

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

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


4

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」または「BLANK」の文字列値を保存し、開発者にそれがヌルまたは空の文字列であると想定させるようなものです。私にとって、それは悪い設計です。NULLがあるときにそれを保存するのはなぜですか?

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

詳細:

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

より詳細で詳細な説明については、開発者に以下をお勧めします。SQLクエリ-TRUEおよびFALSEを超えて


3

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

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

空の文字列は、質問に答えるための有効な入力になります。MIMEはキリンに何を言ったでしょうか?


世界で最高の意図があったとしても、検証ではこの問題を解決できない場合があります。すべての列に何らかの値を提供する必要がある行を処理する方法を使用する必要がある場合があります。その場合、質問は残ります-値がないときにどの値を使用するのですか?もちろん、答えは次のとおりです。値がないことを示す値。DBでは、これは通常NULLです。
-jmoreno

2

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

  • 有効なメールアドレスがあります: me@example.com
  • あなたは何も持っていません(おそらく1つを尋ねるべきです): NULL
  • この人にはメールアドレスがないことを知っています: Empty String.

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


1

私が理解している質問は、NULLと空の文字列のどの解釈を選択すべきかということです。これは、特定のフィールドがいくつの状態にあるかに依存します。

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


1

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

nullを追加するには、追加のスペースが必要です。ceil(columns_with_null / 8)バイト/行ごと。

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

また、データが混乱する可能性があります。完璧な世界では、「データは常に正しいものであり、覚えている」と言うでしょう...しかし、人々がチームで作業する必要があり、全員があなたのレベルに正確にいるわけではない場合、WHERE(aa。 xx <> '' AND bb.zzはNOT NULL)

したがって、チームメンバーを1日おきに修正するのではなく、単純なルールを実施します。null値はありません、絶対に!

NULL以外の値をカウントする方が高速です...簡単な質問は何のためにそれをする必要があるでしょうか?


NULLを使用すると、実際にはデータベースのコスト(計算とストレージの両方)になることをどこかで読んだことを漠然と思い出します。そのフォーミュラを持ち出すことの良い点。
ヤチェクプルシア

VARCHAR列がゼロであっても、文字列の長さを格納するために少なくとも1バイトかかることを忘れないでください。
dan04

空のセルとnullはどちらも、何かが間違っていることを示す方法です。違います。nullは、値がないことを示す方法です。ほとんどのRDBMSは、各行にビット配列を使用して、どの列がヌルであるかを示しているに違いありません。したがって、追加のスペースは非常に小さいため、無関係です。追加の処理を心配するのは時期尚早の最適化であり、意図的に空の文字列を使用していることを「発見」するために他の開発者向けに作成されたスピードバンプと比較しても何もありません。
トーマス

3
null値はありません。これがダチョウのアプローチです。「私たちは頭を砂の中に入れて、存在しない値は存在しないと宣言します」。これは通常、値が存在しないことを表すために各データ型のマジック値を作成する必要があるマジック値ソリューションにつながります。
トーマス

1

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

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

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

nullが意味を持つという考えは古いものであり、現代のプログラマーが回避しなければならないものです。

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


電子メールフィールドがヌルを許可せず、長さゼロの文字列を持つことができない理由 -簡単に言うと、データベースについて何かを知っている開発者は魔法の意味を持つ空の文字列を期待しないからです。あなたは、すべてのデータベースに基本的にすでに存在するもの、つまり値の欠如を表す概念を表すために、独自の魔法の値を作成しようとしています。なぜ車輪を再発明するのですか?また、NULLSの考え方は、オールドスクールとはかけ離れています。Nullは、リレーショナルデータベースの設計を理解するための重要なポイントです。
トーマス

笑。プログラマーの観点から言ったように、nullはほとんど常に痛みであり、ビジネスロジックにはほとんど必要ありません。私は個人的に、開発者として、リレーショナルデザインをあまり気にしません。私がやった場合、私はDBの男になります。DBからnullを取得する場合、ほとんど常に空の文字列のような合理的なものに変換し、それから私の素晴らしいOOPデザインに魔法をかけます。フレームワークは、DBAが世界に押し付ける愚かなヌルを処理します。DBの男はそれに対処しなければならないことを知っています。しかし、プログラマーとして私はする必要はありません。より良い解決策があります。
エルグリンゴグランデ

ヌルを処理する必要はありません。したがって、あなたが説明するのは、ダチョウのソリューションと魔法の値のソリューションを組み合わせたものです。「存在しない値が存在するという事実を無視し、すべてのヌル整数を-1に変換します」。-1が実際の値になる日が来るまで。MSが.NETにジェネリックを追加した理由の1つは、データベースとアプリケーションコード間の大きなインピーダンスミスマッチに対処するためであり、主に中間層コードでnullを表現することを中心としたことに注意する必要があります。これらの「愚かなヌル」は、ビジネスロジックにも存在します。
トーマス

dbに整数が存在しない(またはnullである)という事実は、-1で表すか、nullable(int)を表す必要があるという意味ではありません。それがヌルを処理する唯一の方法だと思うなら、あなたはプログラミングをあまりよく理解していません。nullは何もないことと同じではないことに注意してください。あなたが言ったように、nullはある種のデータ構造体に存在しない値のプレースホルダーを表します。それは何かを意味します。ビジネスロジックは、データではなく動作に関するものであるため、めったに(決して同じではない)この概念を必要としません。そして、それがnullになるとき、これを表現する最良の方法はめったにありません。
エルグリンゴグランデ

ビジネスロジックでさえ、存在しない値を考慮(表現する)する必要があり、これは過去20年間に見たり構築したほとんどすべてのシステムで私の経験に当てはまります。データベースは、キャプチャおよび保存するビジネスファクトをモデリングしています。ビジネスロジックがデータベースとやり取りできるようにするには、nullの処理方法を知っている必要があります。それがカスタム構造体であるか、マジック値であるか、ジェネリックであるかは関係ありません。ビジネスロジックには、データベースからの不在値の受信を処理する機能と、データベースに不在として値をマークする機能が必要です。
トーマス

-1

私はそれはそれほど重要ではないと思いますが、NULLが存在する方が良いと思います。

テーブルに表示されるデータ(SQL Server Management Studioなど)を表示するときに、NULLと表示され、背景の色が異なる場合、欠損値をより適切に区別できます。

空白が表示された場合、それが本当に空なのか、空白または目に見えない文字がいくつかあるのかといつも思っています。NULLを使用すると、最初は空であることが保証されます。

ここに画像の説明を入力してください

通常、アプリケーション内の値を区別しません。NULLと空の文字列が何か異なることを意味するのは予想外で奇妙なことです。そしてほとんどの場合、私は防御的なアプローチを取り、両方の州に対処します。しかし、人間としての私にとっては、データを見るときにNULLを処理する方が簡単です。


これは、以前の12の回答
-gnat

@gnat:私は同意しません、回答の誰もデータを見る人間の側面についてまだ言及していません。NULL値は1つだけですが、空の文字列のように見える値がたくさんある場合があります(空白だけでなく、奇妙な振る舞いのUnicode文字もたくさんあります)。問題のこの側面について言及している他の回答は見当たりません。
トムパジョレック

限り私はこれを言うことができるようにかなりよくでレイアウトされた第2の上部の答え「それは...データベースを見て任意のプログラマには明白である」など:5年前に投稿されました
ブヨ

@gnat:あなたの主張はわかりますが、著者は同じことを意味しているとは思いません。NULLはオプションのフィールドを意味するが、必須フィールドにも空の文字列を使用できるため、欠損値の場合はNULLの方が論理的だと彼は考えている。私は彼に同意します。しかし、私の答えは、空の文字列は実際には空の文字列ではないが、一見すると空の文字列のように見えるため、空の文字列はNULL値ほど明確ではないという事実を示しています。
トムパジョレック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.