nullable外部キーの悪い習慣?


114

顧客IDへの外部キーを持つOrdersテーブルがあるとします。ここで、顧客IDなしで注文を追加するとします(それが可能かどうかは別の質問です)、外部キーをNULLにする必要があります...これは悪い習慣ですか、それとも、注文と顧客?関係は1対nですが、リンクテーブルはn対nになります。一方、リンクテーブルでは、これらのNULLはもうありません...

NULLへの外部キーを持つレコードは、注文の顧客が追加されるまでの一時的なものであるため、実際にはデータベースに多くのNULLはありません。

(私の場合、それは注文でも顧客でもありません)。

編集:リンクする割り当てられていない顧客はどうですか?


9
これは、データベーススキーマでNULLを使用できるようにする主な目的の1つです。さらに、それがフィールドをNULLまたはNOT NULLと宣言できる理由です。これにより、スキーマの特定の要件を満たすことができます。
gahooa 2009年

7
私は最初に質問をNullable Primary Keysとして読み、いくつかの強力なアドバイスを求めていました... :-)
Andrzej Doyle

回答:


51

リンクテーブルを持つことで、おそらくより良いオプション。少なくとも、正規化BCNF(Boyce-Codd正規形)に違反していません。しかし、私は実用的であることを望みます。これらのnull値が非常に少なく、それらが一時的なものである場合、スキームを複雑にするだけなので、リンクテーブルをスキップする必要があると思います。

余談ですが; リンクテーブルを使用しても、必ずしもn対nになるわけではありません。リンクテーブルで、注文テーブルを指す外部キーをそのリンクテーブルの主キーとして使用する場合、関係は1..nのままです。そのリンクテーブルには、注文ごとに1つのエントリしか存在できません。


2
source__destination_linkまたはSourceDestination
Svisstack

7
リンクテーブルを使用する方が良い場合の状況について知りたいのですが、プロセスフローが何らかの形で改善されるような状況に遭遇したことはありません。
Reimius 2012

5
私の答えで指摘したように、私はこの特定のケースでは実用的であり、リンクテーブルを使用しません。通常のフォームは、プロセスフローを改善するために発明されたのではなく、一貫性を確保して冗長性を回避するために発明されたと確信しています。それは非常に一般的な議論ですが、ケースバイケースで検討する必要があると思います。
PatrikHägne2012

110

Nullable FKに問題はありません。これは、FKが指すエンティティが(0または1)から(1または多く)の主キー参照テーブルとの関係にある場合に一般的です。

たとえば、アドレステーブルへのFKを使用して、テーブルに物理アドレス属性と郵送アドレス属性(列)の両方がある場合などです。エンティティに私書箱(郵送先住所)しかない場合は物理アドレスをnull処理可能にし、郵送先住所が物理アドレスと同じ(またはない)場合は郵送アドレスをnull処理可能にすることができます。


38

ヌル可能列は1NFから5NFまで可能ですが、私が読んだものによれば6NF内にはありません。

「最初の正規形が実際に何を意味するか」をクリス・デートよりよく知っている場合にのみ。XおよびYは両方ともNULL可能であり、実際にいくつかの行のxおよびyが両方ある場合null、次いでWHERE x=y得られませんtrue。これは、nullが値ではないことの合理的な疑いを超えて証明します(実際の値は常にそれ自体に等しいため)。また、RMは「テーブルのすべてのセルに値が存在する必要がある」と規定しているため、nullが含まれている可能性のあるものは関係のものではないため、1NFの問題は発生しません。

Nullable列は一般的に、最初の正規化を破ると主張していると聞いたことがあります。

その議論の根底にある正当な理由については、上記を参照してください。

しかし、実際には非常に実用的です。

それが世界の残りの地域全体で通常発生する頭痛の影響を受けない場合のみ。そのような頭痛の1つ(他のnull現象と比較して、それは軽微な問題です)は、WHERE x=ySQLでは実際にを意味するという事実ですWHERE x is not null and y is not null and x=yが、ほとんどのプログラマーは単にその事実を認識せず、単に読んでいるだけです。時には害はありませんが、そうでない場合もあります。

実際、null許容列は、最も基本的なデータベース設計ルールの1つに違反しています。1つの列に個別の情報要素を組み合わせないでください。ヌルは、ブール値「このフィールドは実際に存在する/存在しない」と実際の値を組み合わせるため、まさにそれを行います。


17
「WHERE xはnullではなく、yはnullでなく、x = y」の+1。それを知らなかった。
RobM 2011

1
非常にうまくレイアウトされた議論と例。
ペッツ2014年

1
一つの問題。値が「存在しない」(これは実際のシナリオです)場合、およびデータベース属性がnullを許可しない場合、属性内の値はすべてWRONGです。頭痛の種に関しては、KISSはシンプルに保つだけでなく、できるだけシンプルに保つことを意味します。「リレーショナルモデル」が非現実的で愚かな結果を必要とする場合、おそらくルールは、必要な実際のデータを処理するために拡張する必要がありますか?
Charles Bretana、2017年

1
3値のロジックでは4値のロジックが必要になり、5値のロジックなどが必要になることが示されています。2値のロジック十分ですが、データ構造はこれを適用すると、「できるだけ簡単」が「私たちが望むだけ簡単」よりもはるかに単純ではなくなります。
Erwin Smout 2017年

2
Chris Date、Logic&Databases、Chpt 6、「なぜリレーショナルDBMSロジックが多価であってはならないのか」、145ページ。その章への参照のリスト、特にMcGoveranに関連するものも興味深いはずです。
Erwin Smout 2017

13

外部キーでnullとして表されるのは単なるオプションのn-1関係であるため、何も問題はありません。それ以外の場合、リンクテーブルを配置すると、それがnn関係にならないように管理する必要があるため、さらに問題が発生します。


2
実際、これは0-Nの関係であり、オプションの1-Nの関係ではありません。しかし、私はあなたに同意します。
エリックJ.

5
管理しますか?これは、0対1側の単純なUNIQUE制約です。
wqw 2009年

2
はい、それはUNIQUE制約ですが、その制約のために、後でコード内で起こり得る例外にも対処する必要があります...
pedromarce 2009年

4

リレーショナルモデルでは、オプションの関係は間違いなく可能です。

nullを使用して、関係がないことを表すことができます。それらは便利ですが、ヌルが他の場所で引き起こすのと同じ頭痛を引き起こします。問題が発生しない場所の1つに参加があります。外部キーにnullがある行は、参照されるテーブルのどの行とも一致しません。したがって、それらは内部結合から脱落します。外部結合を行う場合、とにかくnullを処理することになります。

ヌル(第6正規形)を本当に避けたい場合は、テーブルを分解できます。2つの分解されたテーブルの1つに2つの外部キー列があります。1つはオプションの外部キーで、もう1つは元のテーブルの主キーを参照する外部キーです。次に、制約を使用して、リレーションシップが多対多になるのを防ぐ必要があります。それを防ぐ必要があります。


2

NULLを使用すると、不完全な注文をクリーンアップできます。

SELECT * FROM `orders`
WHERE `started_time` < (UNIX_TIMESTAMP() + 900) AND `customer_id` IS NULL

上記では、関連するお客様IDなしで15分以上前の注文が表示されます。


1

顧客が定義されるまで、顧客IDなしで一時的に注文を追加するだけの場合、単一のトランザクションで顧客と注文を追加するのは簡単ではありません。これにより、NULL外部キーエントリの必要がなくなり、制約やトリガーを回避できます。違反されて設定しましたか?

通常、この状況は、顧客が誰であるかを定義する前に注文が詳述されるWebアプリケーションで発生します。そして、これらの状況では、注文が完全な注文に必要なすべての状態が提供され、その時点で注文がデータベースに保持されるまで、注文はサーバー状態またはcookieに保持されます。

上記のように、NULL外部キーはアドレスのようなものには問題ありません。ただし、NULL顧客フィールドは注文には意味がなく、制約する必要があります。


注文顧客は一例です。私のアプリでは、住所のようなIDDです。ずっと正しい例をすぐに見つけることができませんでした。どうも。
Lieven Cardoen、

1
これは、データベースがショッピングカートにアイテムを格納するために使用されていて、ショッピングカートが登録ユーザーに属していない場合に有効なシナリオです。
ジョニー・カー2013

1

Id = -1やCustomerName = 'Unknown'などのように、常にCustomerテーブルに人工的な行を追加し、通常、CustomerIdをOrder NULLに設定する場合は、-1に設定します。

これにより、null許容のFKがなくても、データの欠如を適切に表すことができます(そして、NULLの扱い方を知らない下流のユーザーからあなたを救うでしょう)。


これを追加するだけで、NULLは(Oracleの)インデックスに格納されないことに注意してください。これは、リンクテーブルをスキップしてnull可能なFKを取得することが理にかなっていることを意味します。それが依存する可能性のある他のことは、このリンクテーブルに何か他のものを保存する場合、たとえば、WHOがリンクを作成したのはいつですか?リンクは現在非アクティブ/削除されていますか(以前は無効でしたか?)
Worthy7

これは悪い考えです。外部キーが設定されていて、それが指しているデータが後で削除された場合、外部キーの例外は発生せず、データは無意味になります。さらに悪いことに、後で別の何かがそのキーに割り当てられた場合、完全に間違った顧客を指しています
IcedD​​ante


-1

Nullableカラムは一般に正規化の最初の段階を破ると主張していると聞いたことがあります。しかし、実際には非常に実用的です。


3
ヌル可能列は1NFから5NFまで可能ですが、私が読んだものによれば6NF内にはありません。
Walter Mitty、

-1

はい、何か問題があります。null可能であれば、外部キーではありません。コードによるデータベース設計。多分あなたは割り当てられていないへのゼロリンクを作る。または、文字列を使用している場合は「未割り当て」。データの整合性を100%維持します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.