web-dev-qa-db-ja.com

リレーショナルデータベースのnullは大丈夫ですか?

リレーショナルデータベースではnull値は許可されるべきではないという考え方があります。つまり、テーブルの属性(列)はnull値を許可してはなりません。ソフトウェア開発の背景から来て、私はこれを本当に理解していません。属性のコンテキスト内でnullが有効な場合は、許可する必要があるようです。これは、Javaで非常に一般的です。オブジェクト参照がnullであることがよくあります。データベースに関する広範な経験がないため、ここで何か不足しているのではないかと思います。

68
Steve Kuo

NULLは、データベースの正規化の観点から否定的に見られています。値が何もない場合は、値を持たないアイテムの行を必要としないように、実際にそれを別のスパーステーブルに分割する必要があるという考えです。

これは、すべてのデータが有効で評価されていることを確認するための取り組みです。

ただし、特にパフォーマンス上の理由でさらに別の結合を回避したい場合は、nullフィールドがあると便利な場合があります(ただし、異常な高パフォーマンスシナリオを除いて、データベースエンジンが適切に設定されている場合は問題になりません)。

-アダム

67
Adam Davis

Nullに対する1つの引数は、明確に定義された解釈がないことです。フィールドがnullの場合、それは次のいずれかとして解釈される可能性があります。

  • 値は「なし」または「空のセット」です
  • そのフィールドに意味のある値はありません。
  • 値は不明です。
  • 値はまだ入力されていません。
  • 値は空の文字列です(nullと空の文字列を区別しないデータベースの場合)。
  • いくつかのアプリケーション固有の意味(たとえば、「値がnullの場合、デフォルト値を使用する」)
  • エラーが発生したため、実際には必要ないときにフィールドにnull値が含まれています。

一部のスキーマ設計者は、すべての値とデータ型に明確な解釈が必要であることを要求しているため、nullは不適切です。

38

ヌルマーカーは問題ありません。本当にそうです。

32
Ken Wootton

場合によります。

データベースでNULLsを許可する理由を理解している限り(選択は列ごとに行う必要があります)AND解釈、無視、またはその他の対処方法彼ら、彼らは元気です。

たとえば、NUM_CHILDRENのような列-答えがわからない場合はどうしますか-NULLにする必要があります。私の考えでは、この列のデザインには他に最適なオプションはありません(NUM_CHILDREN列が有効かどうかを判断するフラグがある場合でも、この列に値が必要です)。

一方、NULLsを許可せず、フラグの代わりに、フラグの代わりに特別な予約値がある場合は、-1のように、それが本当に不明な場合の子の数を指定する必要があります。慣習、文書などに関して同様の方法.

したがって、最終的には、問題は規約、ドキュメント、一貫性をもって対処する必要があります。

上記の回答でAdam Davisが明らかに支持しているように、列をスパース(またはNUM_CHILDRENの例またはほとんどのデータに既知の値がある例の場合はそれほどスパースではない)に正規化する別の方法テーブルは、すべてのNULLを削除することはできますが、一般的には実行できません。

属性が不明である多くの場合、より単純な設計でNULLsを許可する可能性があるすべての列について別のテーブルに結合することはほとんど意味がありません。結合のオーバーヘッド、主キーのスペース要件は、現実の世界ではほとんど意味がありません。

これにより、カーディナリティ列を追加することで重複行を排除できる方法が思い浮かびますが、たとえば大規模なデータでは、実際には不可能である一意のキーがないという問題が理論的に解決されます。純粋主義者は、代わりに代理PKをすぐに提案しますが、意味のない代理が関係(テーブル)のタプル(行)の一部を形成できるという考えは、関係理論の観点からは笑えます。

27
Cade Roux

NULLの使用にはいくつかの異論があります。一部の異論はデータベース理論に基づいています。理論的には、理論と実践の間に違いはありません。実際にはあります。

完全に正規化されたデータベースは、NULLSがなくてもうまくいくことは事実です。データ値を除外する必要がある場所は、情報を失うことなく行全体を除外できる場所です。

実際には、この程度までテーブルを分解することは大きな有用な目的にはなりません。また、データベースに対して単純なCRUD操作を実行するために必要なプログラミングは、手間がかかり、エラーが発生しやすくなります。

NULLSを使用すると問題が発生する可能性のある場所があります。基本的に、これらは次の質問に関係しています。 NULLが実際に伝えているのは、特定のフィールドに値が格納されていないことです。しかし、アプリケーションプログラマーが欠落データから引き出す推論は時々不正確であり、それは多くの問題を引き起こします。

さまざまな理由で、場所からデータが欠落している可能性があります。ここにいくつかあります:

  1. データはこのコンテキストでは適用できません。例えば一人の配偶者の名。

  2. データ入力フォームのユーザーがフィールドを空白のままにしたため、アプリケーションでフィールドに入力する必要がありません。

  3. 他のデータベースまたはファイルからデータがデータベースにコピーされ、ソースに欠落データがありました。

  4. 外部キーでエンコードされたオプションの関係があります。

  5. 空の文字列がOracleデータベースに格納されました。

NULLSを回避する必要がある場合のガイドラインを次に示します。

通常の予想されるプログラミングの過程で、クエリライターは、NULLを有効な値に置き換えるために、ISNULL、NV、COALESCE、または同様のコードを大量に記述する必要があります。時々、保存されているものが「現実」であるという条件で、保存時に置換を行う方が良い場合があります。

NULLを含む行がカウントされたためにカウントがオフになる可能性がある場合。多くの場合、これはcount(*)ではなくcount(MyField)を選択するだけで回避できます。

ここでは、NULLSに慣れ、それに応じてプログラミングする1つの場所を示します。LEFTJOINやRIGHT JOINなどの外部結合の使用を開始するときはいつでも。内部結合とは異なる外部結合の背後にある重要な点は、一致するデータが欠落しているときに行を取得することです。欠落しているデータはNULLSとして与えられます。

私の結論:それを理解せずに理論を却下しないでください。しかし、いつ理論から逸脱するべきか、どのようにそれに従うべきかを学んでください。

18
Walter Mitty

データフィールドにNULLを使用しても問題はありません。キーをnullに設定するときは注意が必要です。主キーは決してNULLであってはなりません。外部キーはnullにすることができますが、孤立レコードを作成しないように注意する必要があります。

何かが「存在しない」場合は、空の文字列や他の種類のフラグの代わりにNULLを使用する必要があります。

16
Ken

NULLの問題、およびトライステートとブールロジックなどのすべての問題を記述する代わりに、次の簡潔なアドバイスを提供します。

  1. 欠落または不完全なデータを表す魔法の値を追加するまで、列にNULLを許可しないでください。

  2. この質問をしているので、NULLにどのようにアプローチするかveryは注意する必要があります。自明ではない落とし穴がたくさんあります。疑問がある場合は、NULLを使用しないでください。

11
Mark Brackett

「N/A」または「N/K」または空の文字列を使用する別の方法があります-別のテーブル。

例えば。お客様の電話番号がわかっている場合とわからない場合:

CREATE TABLE Customer (ID int PRIMARY KEY, Name varchar(100) NOT NULL, Address varchar(200) NOT NULL);
CREATE TABLE CustomerPhone (ID int PRIMARY KEY, Phone varchar(20) NOT NULL, CONSTRAINT FK_CustomerPhone_Customer FOREIGN KEY (ID) REFERENCES Customer (ID));

電話番号がわからない場合は、2番目のテーブルに行を追加しません。

9
finnw

Nullsは間違いなく使用されるべきだと私は言うでしょう。データの欠如を表す他の正しい方法はありません。たとえば、空の文字列を使用して行方不明の住所行を表すことは間違っています。また、0を使用して行方不明の年齢データ項目を表すことは間違っています。空の文字列と0の両方がデータだからです。 Nullは、このようなシナリオを表すための最良の方法です。

8
Vaibhav

フィールドをNULL可能にすることで作成する複雑さを過小評価しないでください。たとえば、次のwhere句は、すべての行に一致するように見えます(ビットは1または0のみにできますよね?)

where bitfield in (1,0)

ただし、ビットフィールドがNULL可能である場合、一部が欠落します。または、次のクエリを実行します。

select * from mytable
where id not in (select id from excludetable)

Excludetableにnullと1が含まれている場合、これは次のように変換されます。

select * from mytable
where id <> NULL and id <> 1

しかし、 "id <> NULL"はidのどの値に対しても偽なので、これは行を返しません。これは、経験豊富なデータベース開発者でさえ、驚きによって捕らえます。

ほとんどの人が無防備にNULLに捕らえられる可能性があるので、私はできる限り回避するようにしています。

7
Andomar

NULLは非常に多くのことを意味する可能性があるため、これはワームの巨大な缶です:

  • 人はまだ生きているので、死の日付はありません。
  • それが何であるか、または存在していてもわからないため、携帯電話番号はありません。
  • その人は持っていないことがわかっているため、社会保障番号はありません。

これらの一部は正規化によって回避でき、一部はその列に値が存在することで回避でき( "N/A")、一部はNULLの存在を説明する別の列を設けることで軽減できます(「N/K」、「N/A」など)。

それらを見つけるために必要なSQL構文はnull以外の値の構文と異なり、それらを結合することは困難であり、それらは一般にインデックスエントリに含まれていません。

前者の理由により、ヌルが避けられないケースを見つけることになります。

後者の理由のため、それらの数を最小限に抑えるために最善を尽くす必要があります。

いずれにしても、常にNOT NULL制約を使用して、値が必要なnullを防ぎます。

6
David Aldridge

Nullの主な問題は、比較、集計、結合で予期しない結果を生成する可能性がある特別なセマンティクスがあることです。

  • Nullに等しいものはなく、nullに等しくない、nullより大きい、または小さいものはないため、一括比較を行う場合は、nullをプレースホルダー値に設定する必要があります。

  • これは、結合で使用される可能性のある複合キーの問題でもあります。自然キーにnull値を許可する列が含まれている場合は、合成キーの使用を検討してください。

  • Nullはカウントから外れる可能性があり、これは希望するセマンティクスではない可能性があります。

  • 結合できる列にNULLがあると、内部結合から行が削除されます。一般的に、これはおそらく望ましい動作ですが、報告を行う人々に象の罠を仕掛けることができます。

Nullには他にもいくつかの微妙な点があります。 Joe Celkoの SQL for Smarties については、この章全体を扱っており、良い本であり、とにかく読む価値があります。 nullが適切なソリューションである場所の例は次のとおりです。

  • 結合されたエンティティが存在する場合と存在しない場合のオプションの関係。 NULLは、外部キー列のオプションの関係を表す唯一の方法です。

  • カウントから除外するためにnullにしたい列。

  • 存在する場合と存在しない場合があるオプションの数値(通貨など)の値。数値システム(特にゼロが正当な値である場合)には「記録されない」ための有効なプレースホルダー値がないため、nullが実際にこれを行う唯一の良い方法です。

微妙なバグを引き起こす可能性が高いため、nullの使用を避けたい場所の例。

  • 参照テーブルに対するFKを持つコードフィールドの「記録されていない」値。プレースホルダー値を使用して、データベースに対してクエリを実行するときに、あなた(または追跡しているランダムなビジネスアナリスト)が結果セットから誤って行を削除しないようにします。

  • 何も入力されていない説明フィールド-null文字列('')これで問題なく動作します。これにより、ヌルを特別なケースとして扱う必要がなくなります。

  • レポートシステムまたはデータウェアハウスシステムのオプションの列。この状況では、ディメンションに「Not Recorded」のプレースホルダー行を作成し、それに対して結合します。これにより、クエリが簡素化され、アドホックレポートツールとうまく連携します。

繰り返しますが、セルコの本は主題の良い治療法です。

正規形について知っておくべき最も良いことは、それらがガイドであり、ガイドが忠実に守られるべきではないということです。アカデミアの世界が実際の世界と衝突するとき、あなたはめったに多くのアセデミアの生き残っている戦士を見つけることができません。

この質問に対する答えは、nullを使用しても問題ないということです。状況を評価し、null値と実際の値の比率が高すぎると感じた場合に、それらをテーブルに表示するか、データを別の関連テーブルに集約するかを決定します。

友人が言うのが好きなように、「完璧を善の敵にさせないでください」。ヴォルテールもそうだと思います。 8)

5
ScottCher

厳密な関係代数によれば、ヌルは必要ありません。ただし、実用的なプロジェクトの場合は必要です。

第1に、多くの実世界のデータは不明であるか適用されず、nullはその動作を適切に実装します。次に、ビューと外部結合をより実用的にします。

4
Dour High Arch

ステップバイステップのデータ取得システムでは、質問/データ収集の順序が論理データモデルと一致することが非常にまれであるため、データベースにnullが含まれるのを回避できないことがわかります。

または、値をデフォルトにすることもできます(これらのデフォルト値を処理するためのコードが必要です)。たとえば、モデルでは、すべての文字列がnullではなく空であると想定できます。

または、実際のデータベーステーブルにデータを入力する前にすべてのデータが取得されるまで、データ取得用のステージングデータベーステーブルを用意することもできます。これは多くの追加作業です。

3
JeeBee

データベースにとって、nullは「これの値を持っていない」に変換されます。つまり(興味深いことに)nullを許可するブール列は完全に受け入れ可能であり、多くのデータベーススキーマに表示されます。対照的に、コードにブール値があり、値が「true」、「false」、または「undefined」の場合、遅かれ早かれコードがthedailywtfで終了する可能性があります:)

そのため、フィールドに値がまったくない可能性を考慮する必要がある場合は、列にnullを許可することは完全に許容されます。潜在的な選択肢(空の文字列、ゼロなど)よりもはるかに優れています。

3
Dan

ヌルは扱いにくい場合がありますが、場合によっては意味があります。

日付の値を持つ「PaidDate」列のある請求書テーブルがあるとします。請求書が支払われる前に、その列に何を入れますか(いつ支払われるか事前にわからない場合)。空の文字列にすることはできません。これは有効な日付ではないためです。任意の日付(たとえば、1/1/1900)を指定しても意味がありません。その日付は単に正しくないからです。値がないため、妥当な値はNULLのみです。

データベースでnullを扱うにはいくつかの課題がありますが、データベースはそれらをうまく処理します。実際の問題は、データベースからアプリケーションコードにnullを読み込むときです。それが物事がより困難であることがわかったところです。たとえば、.NETでは、厳密に型指定されたデータセット(DB構造を模倣している)の日付は値型であり、nullにすることはできません。したがって、回避策を構築する必要があります。

可能な場合はnullを避けますが、有効な用途があるため除外しないでください。

3
Jim

上記の答えの多くに同意し、正規化されたスキーマ設計で適切な場合にNULLを使用できると信じています。特に、ある種の「マジックナンバー」やデフォルト値の使用を避けたい場合に、誤解を招く!

しかし結局のところ、上記の回答にリストされている想定の一部、特にNULLが発生する可能性がある箇所を回避するには、nullの使用を(デフォルトではなく)十分に検討する必要があると思います。 想定される 「なし」または「空」、「不明」または「値がまだ入力されていません」.

3
RobS

概念データモデリングと物理データモデリングを混同していると思います。

CDMでは、オブジェクトにオプションのフィールドがある場合は、オブジェクトをサブタイプして、そのフィールドがnullでない場合の新しいオブジェクトを作成する必要があります。それがCDMの理論です

現実の世界では、現実の世界に対してあらゆる種類の妥協を行っています。現実の世界では、NULLは問題ありません。

3
Mark Brady

nullは値がないことを意味し、0はそうではありません。0が表示された場合、意味がわかりません。nullが表示された場合、それは欠損値です。

Nullの方がはるかに明確であると思います。0と ''は、格納されている値の意図を明確に示していないため、混乱しています。

2
SQLMenace

技術的にはNULLはフィールド値としては問題ありませんが、頻繁に無視されます。データベースへのデータの書き込み方法によっては、NULLではなく、フィールドに空の文字列値が表示される可能性があります(一般的です)。そのため、WHERE句の一部としてこのフィールドを持つクエリは、不要なキーストロークである両方のシナリオを処理する必要があります。

2
CNote

当日の問題のある意見-データベースの列でNULLを許可するというデフォルトは、おそらくすべてのRDBMの土地で世界的に受け入れられている最悪の設計決定でした。すべてのベンダーがそれを行っていますが、それは誤りです。 NULLは特定の特定のよく考えられたインスタンスでは問題ありませんが、すべての列でNULLを明示的に禁止する必要があるという考えは、不注意によるNULL可能性を通常よりも一般的にします。

2
mattmc3

技術的には、リレーショナルデータベースの基礎となるリレーショナル数学ではnullは違法です。したがって、純粋に技術的な意味論的リレーショナルモデルの観点からは、いいえ、それらは大丈夫ではありません。

現実の世界では、非正規化とモデルのいくつかの違反は問題ありません。ただし、一般的に、ヌルは設計全体をより注意深く見る必要があることを示す指標です。

私は常にヌルに非常に警戒しており、可能な限りそれらを正規化しようとしています。しかし、それはそれらが時々最良の選択ではないという意味ではありません。ただし、特定のベースでnullを使用する方が良いと本当に確信しているのでない限り、「nullを使用しない」の方がよいでしょう。

2

Oracleデータベースを使用している場合、1つの問題があります。空の文字列をCHAR型の列に保存すると、Oracleは要求せずに値を強制的にNULLにします。したがって、Oracleの文字列列でNULL値を回避することは非常に難しい場合があります。

NULL値を使用している場合は、SQLコマンドCOALESCEを使用する方法を学びます。特に文字列値を使用する場合に注意してください。その後、NULL値がプログラミング言語に伝播するのを防ぐことができます。たとえば、FirstName、MiddleName、FamilyNameを持っている人が、1つのフィールドを返したいとします。

  SELECT FullName = COALESCE(FirstName + ' ', '') + COALESCE(MiddleName+ ' ', '') + COALESCE(FamilyName, '') FROM Person

COALESCEを使用しない場合、any列に[〜#〜] null [〜#〜]値が含まれていると、[〜#〜] null [〜#〜]が返されます。

2
Liam Westley

私の言葉を皮肉にとらないでください。おもちゃのデータベースで作業している場合を除いて、NULLは不可避であり、実際にはNULL値を回避することはできません。

すべての人の名前、ミドルネーム、姓をどのように持つことができるかを言うためだけに。 (ミドルネームと姓はオプションであり、その場合はNULLが表示されます)。また、ブログリストの全員にFAX、会社の電話、オフィスの電話を使用する方法。

NULLは問題なく、取得するときに適切に処理する必要があります。 SQL Server 2008には、NULLのために使用されるスペースも回避できるスパース列の概念があります。

NULLをゼロやその他の値と混同しないでください。人々は、それが正しいと言うことを何でもします。

ありがとうNaveen

2
naveen

NULLロック。場合によっては必要がない場合、SQLはIS NULLおよびIS NOT NULLを特殊なケースの演算子として使用しません。 NULLは概念的なユニバーサルのルートであり、他のすべてはNOT NULLではありません。データ値が欠落していても欠落していない可能性がある場合はいつでも、NULLを自由に使用してください。デフォルト値は、常に完全に正しい場合にのみNULLを補正できます。たとえば、シングルビットフィールド「IsReady」がある場合、このフィールドのデフォルト値がfalseでNULLが許可されていないことは完全に理にかなっているかもしれませんが、これは暗黙的にknowであることをアサートします準備ができていないものは何でも、実際私たちはそのような知識を持っていないかもしれません。可能性としては、ワークフローのシナリオでは、準備ができているかどうかを判断する人がまだ意見を入力する機会がなかったため、デフォルトのfalseは実際には危険であり、彼らが持っていると思われる決定を見落とす可能性があります作成されましたが、実際にはデフォルトのみでした。

余談ですが、ミドル頭文字の例を参照すると、私の父はミドルネームを持っていなかったため、ミドル頭文字がNMI =ミドルイニシャルなし。ばかげたことは?

2
Steven A. Lowe

個人的には、このレコードが他のテーブルの何にもリンクされていないことを象徴するために、フィールドを別のテーブルへの外部キーとして使用しているときにのみnullを使用するべきだと思います。それ以外に、アプリケーションロジックをプログラミングするとき、null値は実際には非常に厄介であることがわかりました。多くのデータ型のほとんどのプログラミング言語では、データベースのnullを直接表すことはできないため、これらのnull値の意味を処理するためのアプリケーションコードが大量に作成されます。 DBがnull整数に遭遇し、たとえば、1の値(別名null + 1)を追加しようとすると、データベースはnullを返します。これがロジックの定義方法です。ただし、プログラミング言語がnullと1を追加しようとすると、通常は例外がスローされます。したがって、コードは、値がnullの場合に何をすべきかをチェックすることになります。これは、数値の場合は0に、テキストの場合は空の文字列に、日付フィールドの場合は一部のnull日付(1900/1/1?)に変換することと同じです。 。

1
Kibbee

問題は、NULLの値を解釈して何を意味するかによると思います。はい、NULL値には多くの解釈がありますが、ここに掲載されているそれらのいくつかは決して使用すべきではありません。 NULLの真の意味は、アプリケーションのコンテキストによって決定され、複数のことを意味することはありません。たとえば、1つの提案は、生年月日フィールドのNULLは、その人がまだ生きていることを示すというものでした。これは危険です。

簡単に言えば、NULLを定義してそれを使用します。 「このフィールドの値は現時点では不明です」という意味で使用しています。それはそれだけを意味します。それが別の意味で適切であることを意味する必要がある場合は、データモデルを再検討する必要があります。

1
Jack

属性のコンテキスト内でnullが有効な場合は、許可する必要があるようです。

しかし、nullはどういう意味ですか?それは摩擦です。それは「値なし」ですが、そこに値がない可能性がある12の異なる理由があり、「null」はこの場合にそれが何を意味するかについての手掛かりを与えません。 (まだ設定されていません、このインスタンスには適用できません、このタイプには適用できません、不明、不明、見つからない、エラー、プログラムのバグ、...)

これは、Javaで非常に一般的です。オブジェクト参照がnullであることがよくあります。

そこにnull参照があるのも悪い と言う考え方の群れがあります。同じ問題:nullの意味

IIRC、Javaには "null"と "uninitialized"の両方があります(後者の構文はありません)。したがって、Goslingはあらゆる種類の "値なし"に "null"を使用する愚かさを理解しました。しかし、なぜ 2つだけ で停止するのですか?

0
Ken

Nullで問題ありません。

0
HAXEN

それはすべて、正規化と使いやすさおよびパフォーマンスの問題の両方に行き着きます。

完全な正規化ルールに固執する場合は、次のようなものを書くことになります。

C.id、c.lastname、.......を顧客cから選択します。左の結合customerphonenumber cpn on c.id = cpn.customerid left join customeraddress ca on c.id = ca.customerid left join customerphonenumber2 cpn2 on c。 id = cpn2.customeridなど、など

0
Kevin