外部キーをNULLにしたり、重複したりできますか?


325

2つのことを明確にしてください。

  1. 外部キーをNULLにすることはできますか?
  2. 外部キーは複製できますか?

私の知る限り、NULL外部キーでは使用しないでください。ただし、私のアプリケーションでNULLは、OracleとSQL Serverの両方に入力できますが、その理由はわかりません。


1
@エイドリアン:私が知っている限りでは、外部キーをnullにすることはできませんが、SQLサーバーとOracleではnullを取得しています。理由を説明できますか?
ジャム

@Jams-私の答えのリンクを読んでください。
JNK、2011

11
回答と質問が役立つので、これは削除できません。質問を編集して自由に改善してください。
Jeff Atwood

重複についての質問は分割してください。NULLに関する問題のみが以下で回答されています。
reinierpost

回答:


529

短い答え:はい、NULLまたは重複する可能性があります。

外部キーをnullにする必要がある、または一意である必要がある理由を説明したいと思います。まず、外部キーでは、そのフィールドの値が別のテーブル(親テーブル)に最初に存在している必要があるということを覚えておいてください。これがFKの定義です。定義上、ヌルは値ではありません。nullは、値が何であるかがまだわからないことを意味します。

実際の例を挙げましょう。販売提案を格納するデータベースがあるとします。さらに、各プロポーザルには1人の営業担当者と1人のクライアントしか割り当てられていないとします。したがって、プロポーザルテーブルには、クライアントIDと営業担当者IDの2つの外部キーがあります。ただし、レコードが作成された時点では、営業担当者が常に割り当てられているわけではないため(まだ誰も自由に作業できるわけではないため)、クライアントIDは入力されていますが、営業担当者IDはnullである可能性があります。言い換えると、通常、データの入力時にその値がわからない場合でも、入力する必要があるテーブル内の他の値はわかっているときに、FKをnullにする機能が必要です。FKでnullを許可するには、通常、FKを持つフィールドでnullを許可するだけです。null値は、FKであるという考えとは異なります。

一意であるかどうかは、テーブルが親テーブルと1対1または1対多の関係にあるかどうかに関係します。1対1の関係の場合、1つのテーブルにすべてのデータが含まれる可能性がありますが、テーブルが広すぎる場合、またはデータが別のトピックにある場合(従業員-保険の例@tboneたとえば)、FKを使用して個別のテーブルが必要です。次に、このFKをPK(一意性を保証する)にするか、一意の制約を設定することもできます。

ほとんどのFKは1対多の関係のためのものであり、これはフィールドにさらに制約を追加することなくFKから得られるものです。たとえば、注文テーブルと注文詳細テーブルがあります。顧客が一度に10品目を注文すると、FKと同じorderIDを含む1つの注文と10の注文詳細レコードがあります。


13
それで、「Unassigned」という名前の偽の営業担当者よりも良いことを意図しているのですか?
トーマスウェラー

8
コメント。NULLは、SQLが3VLを(誤って)処理する方法を知らない人々によるクエリのエラーのために多くの余地を残します。特定のRテーブルで営業担当者が本当に必要ない場合は、そのレコードを含めないでください。別のテーブルは、「ProposalAssignedTo」などの適切な制約付きのテーブルにすることができます。クエリの作成者は、そのテーブルに参加して、プロポーザルに営業担当者がいない場合に実行したいことに対して独自のロジックを提供できます。NULLは、単に「わからない」という意味ではありません。多くのことに使用できます(そのため、ほとんど常に悪い考えです)
N West

26
@nWest、私は無能な人が私のデータベースにクエリを実行することを許可しません。nullの処理方法を知らない開発者は無能です。特定のフィールドの最初のデータ入力時にデータが不明であるが、そのときに他のフィールドが必要になる場合があります。
HLGEM 2016

28
@ThomasWeller偽の営業担当者(「未割り当て」)を参照すると、問題がさらに悪化します。あなたの営業担当者テーブルには複数の列があると思います...?Unassigned氏の社会保険番号は?彼はどの部門に割り当てられていますか?彼の上司は誰ですか?要点を理解していただければ幸いです。「割り当てられていない」営業担当者を作成するとNULL、1つのテーブルをNULL別のテーブルの複数のに交換したことがすぐにわかります。
ギリ

1
@ThomasWellerインターフェイスをローカライズする必要がある場合、またはその際にも問題が発生します。
tobiv 2017


45

馬の口から:

外部キーは、一致する主キーまたは一意キーがない場合でも、すべてNULLのキー値を許可します

外部キーの制約なし

外部キーに他の制約が定義されていない場合、子テーブルの任意の数の行が同じ親キー値を参照できます。このモデルでは、外部キーにnullを使用できます。...

外部キーのNOT NULL制約

外部キーではnullが許可されていない場合、外部キーではnullが許可されないため、子テーブルの各行は親キーの値を明示的に参照する必要があります。

子テーブルの任意の数の行が同じ親キー値を参照できるため、このモデルは、親キーと外部キーの間に1対多の関係を確立します。ただし、子テーブルの各行には、親キー値への参照が必要です。外部キーに値(null)がないことは許可されていません。前のセクションの同じ例を使用して、そのような関係を説明できます。ただし、この場合、従業員は特定の部門への参照を持っている必要があります。

外部キーに対する一意の制約

UNIQUE制約が外部キーに定義されている場合、子テーブルの1つの行のみが特定の親キー値を参照できます。このモデルでは、外部キーにnullを使用できます。

このモデルは、親キーと外部キーの間に1対1の関係を確立します。これにより、外部キーに不確定値(null)が許可されます。たとえば、従業員テーブルに、会社の保険プランの従業員の会員番号を参照するMEMBERNOという名前の列があるとします。また、INSURANCEという名前のテーブルにはMEMBERNOという名前の主キーがあり、テーブルの他の列には従業員の保険証券に関連するそれぞれの情報が保持されています。従業員表のMEMBERNOは、外部キーと一意キーの両方でなければなりません。

  • EMP_TABテーブルとINSURANCEテーブルの間に参照整合性ルールを適用するには(FOREIGN KEY制約)

  • 各従業員が一意のメンバーシップ番号を持っていることを保証するため(UNIQUEキー制約)

外部キーに対するUNIQUEおよびNOT NULL制約

UNIQUE制約とNOT NULL制約の両方が外部キーに定義されている場合、子テーブルの1行のみが特定の親キー値を参照できます。外部キーではNULL値は許可されないため、子テーブルの各行は明示的に参照する必要があります親キーの値。

これを見てください:

Oracle 11gリンク


16

はい、上層部のプログラマーが言ったように外部キーはnullにすることができます...外部キーをnullにする必要がある別のシナリオを追加します。ビデオ。コメントテーブルでは、2つの外部キーPicturesId、およびVideosIdとプライマリキーCommentIdを指定できます。したがって、動画にコメントする場合は、VideoIdのみが必要であり、pictureIdはnullになります。また、画像にコメントする場合は、PictureIdのみが必要で、VideosIdはnullになります...


1
この問題を解決するより良い方法があると思います。新しい列を作成する代わりに、「id」と「type」の2つの列を作成できます。これらには、外部キーテーブルのIDと名前が含まれます。たとえば、id = 1、type = Pictureはid 1の画像テーブルへのリンクを表します。このソリューションを使用する利点は、コメントを追加のテーブルに追加するときに新しい列を作成する必要がないことです。短所は、データベースレベルの外部キー制約ではなく、制約がアプリレベルである必要があることです。
Agent47DarkSoul

4
@エージェント:この「解決策」は本番環境で使用しました。それをしないでください、それはひどいです。クエリを作成することは、「タイプ1の場合はこのテーブルに結合し、それ以外の場合はこれに結合する」という混乱の原因になります。それは私たちにとって悪夢でした。結局、この答えのとおりにして、結合のタイプごとに新しい列を作成しました。列の作成は安価です。ほとんどの欠点は、多くの列がToadを使いにくくすることですが、それはToadの欠点にすぎません。
user128216

1
@FighterJet Railsは、このソリューションで複雑なクエリを処理する優れたORMフレームワークを提供します。
Agent47DarkSoul

2
@エージェント:できるかもしれませんが...もしあなたがそれを単純にできるなら、なぜそれを複雑にするのですか?そしておそらく「悪夢」を使うのは間違った言葉だった。それは非常に不便だった。データの整合性の問題に悩まされることはほとんどありませんでした。
user128216

7

それはforeign keyあなたの関係でこれが果たす役割に依存します。

  1. これforeign keykey attributeあなたの関係にある場合、それはNULLであってはなりません
  2. これforeign keyが関係の通常の属性である場合、NULLにすることができます。

3

Oracle構文を使用した例を次に示します。
まず、COUNTRYテーブルを作成しましょう

CREATE TABLE TBL_COUNTRY ( COUNTRY_ID VARCHAR2 (50) NOT NULL ) ;
ALTER TABLE TBL_COUNTRY ADD CONSTRAINT COUNTRY_PK PRIMARY KEY ( COUNTRY_ID ) ;

テーブルPROVINCEを作成します。

CREATE TABLE TBL_PROVINCE(
PROVINCE_ID VARCHAR2 (50) NOT NULL ,
COUNTRY_ID  VARCHAR2 (50)
);
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_PK PRIMARY KEY ( PROVINCE_ID ) ;
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_COUNTRY_FK FOREIGN KEY ( COUNTRY_ID ) REFERENCES TBL_COUNTRY ( COUNTRY_ID ) ;

これはOracleで完全に正常に動作します。2番目のテーブルのCOUNTRY_ID外部キーには「NOT NULL」がないことに注意してください。

これで、PROVINCEテーブルに行を挿入するには、PROVINCE_IDを指定するだけで十分です。ただし、COUNTRY_IDも指定することを選択した場合は、COUNTRY_IDがすでにCOUNTRYテーブルに存在している必要があります。


1

デフォルトでは、外部キーに制約はありません。外部キーはnullで重複することができます。

テーブルの作成/テーブルの変更中に、一意性またはnull以外の制約を追加した場合、それだけではnull /重複値は許可されません。


0

簡単に言えば、エンティティ間の「非識別」関係はERモデルの一部であり、ER図を設計するときにMicrosoft Visioで使用できます。これは、タイプが「ゼロ以上」または「ゼロまたは1」のエンティティ間にカーディナリティを適用するために必要です。「1対多」の「1」ではなく、この「ゼロ」のカーディナリティに注意してください。

ここで、カーディナリティが「ゼロ」(非識別)である可能性がある非識別関係の例は、1つのエンティティのレコード/オブジェクトと言う場合です。別のエンティティBの/ s。

エンティティAの1つのレコードが他のエンティティBのレコードに対してそれ自体を識別する可能性があるため、エンティティBには、エンティティBのレコードのID値を持つ列が必要です。エンティティAのレコードがエンティティBのレコード(またはオブジェクト)を識別しない場合、この列は「Null」になる可能性があります。

オブジェクト指向(実世界)パラダイムでは、クラスBのオブジェクトがクラスAのオブジェクトに必ずしも依存しない(強く結合している)場合があります。つまり、クラスBはクラスBと疎結合しています。 Class-AがClass-Aのオブジェクトを "含む"(Containment)ように、Class-Bのオブジェクトの概念とは対照的に、その(クラスのオブジェクト- B)作成。

SQLクエリの観点からは、エンティティBに予約されている外部キーに対して「nullではない」エンティティBのすべてのレコードをクエリできます。これにより、エンティティAの行に対応する特定の値を持つすべてのレコードが取得されます。または、Null値を持つすべてのレコードは、エンティティBのエンティティAにレコードがないレコードになります。


-1

表にある可能性のあるカーディナリティーを検討することをお勧めします。最小カーディナリティをゼロにすることができます。オプションの場合、関連テーブルからのタプルの最小参加はゼロになる可能性があります。ここで、外部キー値をnullにできるようにする必要に直面します。

しかし、答えは、すべてがビジネスに依存するということです。


-3

外部キーの概念は、メインテーブルに既に存在する値を参照するという概念に基づいています。これが、他のテーブルでは外部キーと呼ばれる理由です。この概念は参照整合性と呼ばれます。外部キーがnullフィールドとして宣言されている場合、それは参照整合性の論理そのものに違反します。それは何を指しますか?メインテーブルにあるものだけを参照できます。したがって、外部キーフィールドをnullとして宣言するのは間違っていると思います。


「何も」を参照できない場合や、その値がまだわからない場合でもNULL、参照整合性が言うことは、「何か」を参照する場合、そこに存在する必要があるということです。
ヤクセ

-7

1つのテーブルの外部キーは他のテーブルの主キーでもあると思うので、nullは許可されません。したがって、外部キーにnull値があることには疑問がありません。

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