web-dev-qa-db-ja.com

外部キーの何が問題になっていますか?

Joel Spolskypodcast 014 で、彼がほとんど外部キーを使用したことがなかったという話を聞いたことを覚えています(正しく覚えていれば)。しかし、私にとっては、データベース全体での重複とそれに続くデータ整合性の問題を回避するために非常に重要なようです。

(Stack Overflowの原則に沿った議論を避けるために)理由について、いくつかの確かな理由がありますか?

Edit: "まだ外部キーを作成する理由がないので、これは実際に設定する最初の理由。 "

247
ljs

外部キーを使用する理由:

  • あなたは孤児行を取得しません
  • 自動的にテーブルをクリーンアップするニースの「削除カスケード」動作を取得できます
  • データベース内のテーブル間の関係を知ることは、オプティマイザが最も効率的な実行のためにクエリを計画するのに役立ちます。これは、結合カーディナリティのより良い推定値を取得できるためです。
  • FKは、データベースで収集するのに最も重要な統計情報についてかなり大きなヒントを提供します。これにより、パフォーマンスが向上します。
  • すべての種類の自動生成されたサポートを有効にします-ORMは自分自身を生成でき、視覚化ツールは素敵なスキーマレイアウトを作成できます。
  • それ以外の場合は暗黙的な関係が明示的に文書化されるため、プロジェクトの初心者が物事の流れに早く入る

外部キーを使用しない理由:

  • fKの整合性をチェックする必要があるため、すべての CRUD 操作でDBを余分に動作させています。大量の解約がある場合、これは大きなコストになる可能性があります
  • fKは関係を強制することで、物事を追加/削除する順序を指定します。これにより、DBが希望することを拒否することになります。 (そのような場合、あなたがやろうとしているのは、孤立した行を作成することであり、それは通常良いことではありません)。これは、大規模なバッチ更新を実行していて、1つのテーブルを別のテーブルの前にロードし、2番目のテーブルが一貫性のある状態を作成する場合に特に痛みを伴います(ただし、2番目のロードが失敗し、データベースに一貫性がなくなりました?)。
  • データがダーティになることを事前に知っている場合があり、それを受け入れ、DBにそれを受け入れてほしい場合があります。
  • あなたはただ怠けている:-)

ほとんどの確立されたデータベースは、強制されておらず、単なるメタデータである外部キーを指定する方法を提供していると思います(確かではありません!)。 FKを使用しないすべての理由は非強制によって完全に消去されるため、2番目のセクションのいずれかの理由が当てはまる場合は、おそらくそのルートに進む必要があります。

344
SquareCog

これは育成の問題です。あなたの教育的または職業的なキャリアのどこかで、データベースの提供と世話に時間を費やした場合(または、才能のある人々と密接に協力した場合)、エンティティと関係の基本的な教義はあなたの思考プロセスに十分に浸透しています。これらの基本事項には、データベースでキーを指定する方法/時期/理由(プライマリ、外部、およびおそらく代替)があります。それは第二の性質です。

ただし、過去にRDBMS関連の取り組みでこれほど徹底的または積極的な経験がなかった場合、そのような情報にさらされたことはないでしょう。あるいは、あなたの過去には、反抗的なデータベースである環境への没入が含まれる場合があります(たとえば、「これらのDBAはばかです-少数のJava/c#コードスリンガーが日を節約します)」一部のドウィーブの不可解なせせらぎに、FK(およびそれらが暗示する可能性のある制約)を聞くだけで本当に重要であることがわかります。

ほとんどの人は、子供の頃、歯を磨くことが重要だと教えられました。それなしでも大丈夫ですか?確かに、ラインのどこかで、毎食後にブラッシングした場合よりも歯の数が少なくなります。お母さんとお父さんが口腔衛生だけでなくデータベースの設計もカバーするのに十分な責任がある場合、この会話はありません。 :-)

79
Ed Lucas

あなたはそれを逃れることができるアプリケーションがたくさんあると確信していますが、それは最良のアイデアではありません。データベースを適切に管理するためにアプリケーションを常に当てにすることはできません。データベースを率直に管理することは、アプリケーションにとってあまり重要ではありません。

リレーショナルデータベースを使用している場合は、いくつかの関係を定義する必要があるようです。残念ながら、この姿勢(外部キーは必要ありません)は、データの整合性などの愚かなことに煩わされたくない多くのアプリケーション開発者に受け入れられているようです(ただし、会社には専用のデータベース開発者がいないため必要です)。通常、これらのタイプでまとめられたデータベースでは、主キーを持つだけでラッキーです;)

52
AlexCuse

外部キーは、必須リレーショナルデータベースモデルです。

40
Galwegian

私は常にそれらを使用しますが、その後、金融システム用のデータベースを作成します。データベースは、アプリケーションの重要な部分です。金融データベースのデータが完全に正確でない場合、コード/フロントエンドの設計にどれだけの労力を費やしても問題にはなりません。時間を無駄にしているだけです。

また、複数のシステムは通常、データベースと直接インターフェイスする必要があるという事実があります-データを読み取るだけの別のシステム(Crystal Reports)からデータを挿入するシステム(私が設計したAPIを使用する必要はありません。 VBScriptを発見したばかりで、SQLボックスのSAパスワードを持っているくすんだマネージャー。データベースが可能な限り馬鹿にならないなら、さようならデータベース。

データが重要な場合は、はい、外部キーを使用し、データと対話するための一連のストアドプロシージャを作成し、最も厳しいDBを作成します。データが重要でない場合、なぜデータベースを作成するのですか?

29
Ant

Update:今は常に外部キーを使用しています。 「複雑なテスト」という異論に対する私の答えは、「データベースをまったく必要としないように単体テストを作成します。データベースを使用するテストは適切に使用する必要があり、外部キーが含まれます。セットアップを行うための苦痛の少ない方法を見つけてください。」


外部キーは自動テストを複雑にします

外部キーを使用しているとします。 「金融口座を更新すると、取引の記録が保存されるはずです」という自動化されたテストを書いています。このテストでは、accountstransactionsの2つのテーブルのみに関心があります。

ただし、accountsにはcontractsへの外部キーがあり、contractsにはclientsへのfkがあり、clientsにはcitiesへのfkがあります。 citiesにはstatesへのfkがあります。

データベースは、テストに関係のない4つのテーブルにデータを設定しないとテストを実行できません

これには少なくとも2つの視点があります。

  • 「それは良いことです。テストは現実的である必要があり、それらのデータ制約は本番環境に存在します。」
  • 「それは悪いことです。他の部分を使用せずにシステムの一部を単体テストできる必要があります。システム全体の統合テストを追加できます。」

また、テストの実行中に外部キーチェックを一時的にオフにすることもできます。 MySQL、少なくとも これをサポート

19
Nathan Long

「レコードの削除をより面倒にすることができます。外部キーがその制約に違反する他のテーブルにレコードがある「マスター」レコードを削除することはできません。」

SQL標準では、外部キーが削除または更新されたときに実行されるアクションが定義されていることを覚えておくことが重要です。私が知っているものは:

  • ON DELETE RESTRICT-この列にキーがある他のテーブルの行が削除されないようにします。これは、ケンレイが上記で説明したものです。
  • ON DELETE CASCADE-他のテーブルの行が削除された場合、それを参照するこのテーブルの行をすべて削除します。
  • ON DELETE SET DEFAULT-他のテーブルの行が削除された場合、その列を参照する外部キーを列のデフォルトに設定します。
  • ON DELETE SET NULL-他のテーブルの行が削除された場合、このテーブルでそれを参照する外部キーをnullに設定します。
  • ON DELETE NO ACTION-この外部キーは、それが外部キーであることのみをマークします。つまり、ORマッパーで使用します。

これらの同じアクションは、ON UPDATEにも適用されます。

デフォルトは、使用している sql サーバーに依存するようです。

14
Powerlord

@imphasing-これはまさにメンテナンスの悪夢を引き起こすような考え方です。

なぜ、データがguaranteedで少なくとも一貫性があり、せいぜい弱い予防措置であるいわゆる「ソフトウェア強制」を支持して、宣言的参照整合性を無視するのか。

14
Ed Guiness

それらを使用しない正当な理由が1つあります。その役割や使用方法を理解していない場合

間違った状況では、外部キーの制約が事故の滝の複製につながる可能性があります。誰かが間違ったレコードを削除した場合、元に戻すことは巨大なタスクになる可能性があります。

また、逆に、何かを削除する必要がある場合、適切に設計されていないと、制約によってあらゆる種類のロックが発生し、妨げられます。

12
Kent Fredric

good理由notはありません...孤立した行が大した問題でない限り。

11
Matt Rogish

より大きな質問は、目隠しをつけて運転しますか?それは、参照制約なしでシステムを開発する場合の方法です。ビジネス要件の変更、アプリケーション設計の変更、コード変更におけるそれぞれの論理的仮定、ロジック自体のリファクタリングなどが可能であることに留意してください。一般に、データベースの制約は、特定の論理的アサーションと仮定のセットに対して一見正しいと思われる、現代の論理的仮定の下に配置されます。

特に新しい要件が論理的なアプリケーションの変更を推進する場合、アプリケーションのライフサイクルを通じて、参照およびデータチェックはアプリケーションを介したデータ収集を制限します。

このリストの主題に対して-外部キー自体は、リアルタイムトランザクション処理システムの観点から、それ自体では「パフォーマンスの向上」も「パフォーマンスの低下」もしません。ただし、大量の「バッチ」システムでは、制約のチェックに総コストがかかります。リアルタイムトランザクションプロセスとバッチトランザクションプロセスの違いは次のとおりです。バッチ処理-連続的に処理されたバッチの制約チェックによるコストの増加がパフォーマンスに影響を与える場合。

適切に設計されたシステムでは、データの整合性チェックは、バッチ処理の「前」に行われます(ただし、ここでもコストがかかります)。したがって、外部キー制約チェックはロード時に必要ありません。実際、外部キーを含むすべての制約は、バッチが処理されるまで一時的に無効にする必要があります。

QUERY PERFORMANCE-テーブルが外部キーで結合されている場合、外部キー列がインデックス付けされていないという事実を認識します(ただし、それぞれの主キーは定義によりインデックス付けされます)。さらに言えば、外部キーにインデックスを付けることにより、任意のキーにインデックスを付け、インデックス付きのテーブルを結合することで、インデックスなしのキーに外部キー制約を結合するのではなく、パフォーマンスが向上します。

サブジェクトの変更、データベースがウェブサイトの表示/コンテンツのレンダリングなどをサポートし、クリックを記録している場合、すべてのテーブルに完全な制約があるデータベースはそのような目的のために過剰に殺されます。考えてみてください。ほとんどのウェブサイトでは、そのようなデータベースを使用していません。たとえば、データが記録されているだけで参照されていない同様の要件では、制約のないメモリ内データベースを使用します。これは、データモデルがなく、論理モデルがあり、物理データモデルがないという意味ではありません。

4
jasbir L

私の経験から、データベースクリティカルなアプリケーションでFKを使用することは避けた方が良いでしょう。私はここでFKが良い習慣であると言う人には異議を唱えませんが、データベースが巨大で、CRUD操作/秒が膨大な場合は実用的ではありません。名前を付けずに共有できます。最大の投資銀行の1つは、データベースに単一のFKがありません。これらの制約は、DBを含むアプリケーションを作成する際にプログラマーによって処理されます。基本的な理由は、新しいCRUDが実行されるたびに複数のテーブルに影響を与え、挿入/更新ごとに検証する必要があることですが、これは単一の行に影響を与えるクエリでは大きな問題ではありませんが、大手銀行が日常業務として行わなければならないバッチ処理。

FKを避ける方が良いが、そのリスクはプログラマーによって処理されなければならない。

3
Rachit

「レコードを追加する前に、対応するレコードが別のテーブルに存在することを確認する」がビジネスロジックです。

これをデータベースに入れたくない理由は次のとおりです。

  1. ビジネスルールが変更された場合は、データベースを変更する必要があります。多くの場合、データベースはインデックスを再作成する必要があり、これは大きなテーブルでは低速です。 (変更ルールには、ゲストがメッセージを投稿できるようにする、またはユーザーがコメントを投稿したにもかかわらずアカウントを削除できるようにするなど)。

  2. データベースの変更は、本番リポジトリに変更をプッシュしてソフトウェア修正を展開するほど簡単ではありません。データベース構造をできるだけ変更しないようにします。データベースに存在するビジネスロジックが多いほど、データベースの変更(および再インデックスのトリガー)が必要になる可能性が高くなります。

  3. TDD。単体テストでは、データベースをモックに置き換えて機能をテストできます。データベースにビジネスロジックがある場合、完全なテストを行っていないため、データベースでテストするか、テスト目的でビジネスロジックをコードで複製し、ロジックを複製して、ロジックが動作しない可能性を高めます同じ方法。

  4. さまざまなデータソースでロジックを再利用します。データベースにロジックがない場合、アプリケーションはデータベースのレコードからオブジェクトを作成し、Webサービス、jsonファイル、またはその他のソースからオブジェクトを作成できます。データマッパーの実装を交換するだけで、すべてのビジネスロジックを任意のソースで使用できます。データベースにロジックがある場合、これは不可能であり、データマッパーレイヤーまたはビジネスロジックでロジックを実装する必要があります。いずれにしても、コードでこれらのチェックが必要です。データベースにロジックがない場合、異なるデータベースまたはフラットファイル実装を使用して、異なる場所にアプリケーションをデプロイできます。

3
Tom B

外部キーを使用する追加の理由:-データベースの再利用が可能になります

外部キーを使用しない追加の理由:-再利用を減らして、顧客をツールにロックインしようとしています。

3
Dan

データの一貫性を維持するのに役立つという点で、以前の回答に同意します。ただし、数週間前に正規化された一貫性のあるデータの長所と短所について議論した Jeff Atwoodによる興味深い投稿 がありました。

一言で言えば、非正規化されたデータベースは、大量のデータを処理するときに高速になります。また、アプリケーションによっては正確な一貫性を気にかけないかもしれませんが、データを扱うときはDBが気にしないので、もっと注意する必要があります。

2

Clarifyデータベースは、プライマリキーまたは外部キーを持たない商用データベースの例です。

http://www.geekinterview.com/question_details/18869

おもしろいことに、技術文書はテーブルがどのように関連するか、テーブルを結合するためにどの列を使用するかなどを説明するために非常に長くなります。

言い換えれば、couldは明示的な宣言(DRI)でテーブルを結合しましたが、は選択しません

その結果、Clarifyデータベースは不整合で一杯になり、パフォーマンスが低下します。

しかし、削除、追加する前に関連する行をチェックするなどの参照整合性に対処するコードを記述する必要がなく、開発者の仕事が楽になったと思います。

それが、リレーショナルデータベースに外部キー制約がないことの主な利点だと思います。少なくとも悪魔のような気がするという観点からは、開発が容易になります。

2
Ed Guiness

私はOracleデータベースのみを知っており、他のデータベースは知りません。また、データの整合性を維持するには外部キーが不可欠であると言えます。データを挿入する前に、データ構造を作成し、修正する必要があります。それが完了すると、つまりすべての主キーと外部キーが作成されると、作業は完了です!

意味:孤立した行?いいえ。私の人生でそれを見たことはありません。悪いプログラマーが外部キーを忘れた場合、または別のレベルでそれを実装した場合を除きます。両方とも-Oracleのコンテキストでは-データの重複、孤立したデータ、したがってデータ破損につながる大きなミスです。 FKが強制されていないデータベースは想像できません。私には混乱のように見えます。 Unixの許可システムに少し似ています:誰もがルートであることを想像してください。カオスを考えてください。

外部キーは、主キーと同様に不可欠です。主キーを削除するとどうなるでしょうか?まあ、完全な混乱が起こりそうです。それがそうです。主キーまたは外部キーの責任をプログラミングレベルに移行することはできません。データレベルである必要があります。

欠点?そのとおり !挿入時に、さらに多くのチェックが行われるためです。しかし、データの整合性がパフォーマンスよりも重要な場合、それは簡単です。 Oracleのパフォーマンスの問題は、PKおよびFKに付属するインデックスに関連しています。

2
tvCa

それらはレコードの削除をより面倒にすることができます-外部キーがその制約に違反する他のテーブルにレコードがある「マスター」レコードを削除することはできません。トリガーを使用して、カスケード削除を行うことができます。

主キーを不用意に選択した場合、その値の変更はさらに複雑になります。たとえば、「customers」テーブルのPKを人の名前として使用し、そのキーを「orders」テーブルのFKにすると、顧客が自分の名前を変更したい場合、それは大変な痛みです。 。しかし、それは見掛け倒しのデータベース設計です。

Fireignキーを使用する利点は、想定される欠点を上回ると考えています。

1
Ken Ray

ここで2番目に多くのコメントが必要です。外部キーは、整合性のあるデータを確保するために必要なアイテムです。 ON DELETEとON UPDATEの異なるオプションを使用すると、ここで言及されている「ダウンフォール」のいくつかを回避することができます。

すべてのプロジェクトの99%で、データの整合性を強化するためのFKを使用することに気づきましたが、どれほどひどいデータであっても、古いデータを保持しなければならないクライアントがいることはまれです。しかし、とにかく有効なデータを取得するだけのコードを書くのに多くの時間を費やしているので、無意味になります。

1
Mitchel Sellers

私が聞いた議論は、フロントエンドがこれらのビジネスルールを持つべきだということです。外部キーは、そもそも制約を破る挿入を許可するべきではない場合に、「不要なオーバーヘッドを追加します」。これに同意しますか?いいえ、しかしそれは私がいつも聞いたことです。

編集:私の推測では、彼は概念としての外部キーではなく、外部キー制約を参照していました。

1
lordscarlet

外部キー制約の検証にはCPU時間を要するため、外部キーを省略してパフォーマンスを向上させる人もいます。

1
remonedo

基盤となるデータベースシステムが将来変更されないという確信がある場合は、外部キーを使用してデータの整合性を確保します。

ただし、外部キーをまったく使用しないもう1つの非常に良い理由は次のとおりです

さまざまなデータベースシステムをサポートする製品を開発しています。

さまざまなデータベースシステムに接続できるEntity Frameworkを使用している場合は、「オープンソースの無料」サーバーレスデータベースもサポートできます。これらのデータベースのすべてが外部キールール(更新、行の削除...)をサポートしているわけではありません。

これはさまざまな問題につながる可能性があります:

1.)データベース構造が作成または更新されると、エラーが発生する場合があります。外部キーはデータベースシステムによって無視されるため、サイレントエラーのみが発生する可能性があります。

2.)外部キーに依存している場合は、ビジネスロジックでデータ整合性チェックをほとんどまたはまったく行わないことになります。現在、新しいデータベースシステムがこれらの外部キールールをサポートしていない場合、または単に異なる方法で動作する場合は、ビジネスロジックを書き直す必要があります。

あなたは尋ねることができます:異なるデータベースシステムが必要なのは誰ですか?まあ、すべての人が自分のマシンで完全なSQL Serverを購入する余裕がない、または望んでいるわけではありません。これはソフトウェアであり、保守が必要です。他の人はすでに他のDBシステムに時間とお金を投資しています。サーバーレスデータベースは、1台のマシン上の小規模なお客様に最適です。

これらのDBシステムがすべてどのように動作するかは誰にもわかりませんが、整合性チェックを使用したビジネスロジックは常に同じままです。

1
Michael

私はドミトリーの答えをエコーし​​ます-非常によく言えば。

FKが頻繁にもたらすパフォーマンスオーバーヘッドを心配している人にとって、挿入、削除、または更新中の制約検証のコストオーバーヘッドなしで、FK制約のクエリオプティマイザーの利点を得ることができる方法があります。つまり、属性RELY DISABLE NOVALIDATEを使用してFK制約を作成します。つまり、クエリオプティマイザーは、データベースが実際に制約を強制することなく、クエリを作成するときに制約が強制されていると仮定します。このようにFK制約をテーブルに設定する場合、制約に違反するデータがFK列にないことを絶対に確認する場合は、ここで非常に注意する必要があります。このFK制約がオンになっているテーブルを含むクエリから、信頼できない結果が得られる可能性があります。

通常、この戦略はデータマートスキーマの一部のテーブルで使用しますが、統合ステージングスキーマでは使用しません。データをコピーするテーブルに同じ制約が既に適用されているか、ETLルーチンが制約を適用していることを確認します。

1
Mike McAllister

私もこの議論を聞いたことがあります-外部キーにインデックスを付けるのを忘れて、特定の操作が遅いと不平を言った人からです(制約チェックはインデックスを利用できるため)。要約すると、外部キーを使用しない正当な理由はありません。最新のデータベースはすべてカスケード削除をサポートしているため、...

1
Arno

私にとって、 ACID 規格に準拠する場合は、参照整合性を確保するために外部キーを用意することが重要です。

1
CodeRot

ここで答える人の多くは、参照制約によって実装される参照整合性の重要性に夢中になりすぎます。参照整合性を持つ大規模なデータベースでの作業は、うまく機能しません。 Oracleは、カスケード削除で特に悪いようです。私の経験則では、アプリケーションはデータベースを直接更新せず、ストアドプロシージャを介して実行する必要があります。これにより、データベース内にコードベースが保持され、データベースの整合性が維持されます。

多くのアプリケーションがデータベースにアクセスしている場合、参照整合性の制約のために問題が発生しますが、これはコントロール次第です。

アプリケーション開発者は、データベース開発者が必ずしもそれほど慣れていないかもしれない非常に異なる要件を持っている可能性があるという点で、より広い問題もあります。

1
Zak

また、ほとんどのデータベースでは外部キーが必要だと思います。唯一の欠点は、一貫性が強制されることによるパフォーマンスへの影響に加えて、外部キーがあると、機能する外部キーがあると想定するコードを書くことができることです。それは決して許されるべきではありません。

たとえば、参照先のテーブルに挿入し、最初の挿入が成功したことを確認せずに参照元のテーブルに挿入しようとするコードを書く人を見てきました。外部キーが後で削除されると、データベースの一貫性が失われます。

また、更新または削除時に特定の動作を想定するオプションもありません。外部キーが存在するかどうかに関係なく、必要なことを行うためにコードを記述する必要があります。削除がカスケードされていないときにカスケードされると仮定すると、削除は失敗します。参照されている列への更新が参照されている行に反映されていない場合は、更新は失敗します。コードを書くために、これらの機能を持たないこともあります。

これらの機能が有効になっている場合、コードはとにかくそれらをエミュレートし、パフォーマンスが少し低下します。

したがって、要約...一貫性のあるデータベースが必要な場合、外部キーは不可欠です。外部キーは、作成するコード内に存在または機能していると想定してはなりません。

1
Eric

ウォウォウォ...
どこでも答えます。実際、これは私が遭遇した中で最も複雑なトピックです。 FKは必要なときに使用しますが、実稼働環境ではほとんど使用しません。

Fksをほとんど使用しない理由は次のとおりです。

1。ほとんどの場合、パフォーマンスを向上させるために小さなサーバーで巨大なデータを処理していますが、FKを削除する必要があります。 FKがあり、RDBMSを作成、更新、または削除するときに、制約違反がなく、致命的な可能性のある巨大なDBがあるかどうかを最初にチェックするため

2。他の場所からデータをインポートする必要がある場合がありますが、それらがどの程度構造化されているのかわからないため、単にFKをドロップします。

3。複数のDBを処理していて、他のDBに参照キーを持っている場合は、FKを削除するまで(現時点では)うまくいきません(データベース間の関係)
4。また、RDBMSに対応するアプリケーションを作成する場合や、RDBMSシステムでDBをエクスポートおよびインポートする場合もあります。この場合、特定のRDBMSシステムごとにFKを処理する独自の方法があります。 FKの使用をやめる義務がありました。

5。 RDBMSプラットフォーム(ORM)を使用している場合、それらの一部はソリューションと技術の提供に応じて独自のマッピングを提供し、テーブルとそのFKの作成を気にしないことを知っています。

6。最後のポイントの前に、FKがあるDBを扱う知識と、FK 7を必要とせずにすべてのジョブを実行するアプリケーションを作成する知識があります。最後に、知識がそうでない場合、障害。あなたは常にあなたが得ることができる最高の最高を実行したいと思うでしょう!


みんなありがとう!

FKが問題を引き起こす可能性があるのは、キーを使用できなくても、キーを参照する履歴データが(ルックアップテーブルで)ある場合です。
明らかに解決策は前もって物事をより良く設計することですが、私はここで実際の状況を考えています。そこではあなたが常に完全な解決策を制御できるとは限りません。
たとえば:おそらく、さまざまなタイプの顧客をリストするルックアップテーブルcustomer_typeがあります。特定の顧客タイプを削除する必要があると言えますが、(ビジネス上の制約により)できませんクライアントソフトウェアを更新し、ソフトウェアを開発するときにこの状況を誰も調べなかった場合、それが他のテーブルの外部キーであるという事実により、それを参照する履歴データが無関係であっても、行を削除できない場合があります。
これで数回燃やされた後、おそらく関係のdb実施から身を引くでしょう。
(これが良いと言っているわけではありません-FKとdbの一般的な制約を避けることにした理由を示しているだけです)

0
hamishmcn

私が取り組んだプロジェクトでは、多くのテーブルを同じ列で結合できるように、明示的な関係ではなく暗黙的な関係がしばしばありました。

次の表をご覧ください

アドレス

  • AddressId(PK)
  • EntityId
  • EntityType
  • シティ
  • 状態
  • 等..

EntityTypeの可能な値はEmployee、Company、Customerであり、EntityIdは興味のあるテーブルのプライマキーを参照します。

私はこれが物事を行うための最良の方法だとは本当に思いませんが、このプロジェクトではうまくいきました。

0
Curtis

多くのことと同様に、それはトレードオフです。データの整合性を検証する作業をどこで行うかは問題です。

(1)外部キーを使用する(テーブル用に設定する単一ポイント、機能は既に実装、テストされ、動作することが証明されている)

(2)データベースのユーザーに任せます(複数のユーザー/アプリが同じテーブルを更新する可能性があるため、より多くの潜在的な障害点が発生し、テストの複雑さが増します)。

データベースの方が効率的であり(2)、保守が容易で、(1)のリスクが低くなります。

0
Jen A

Dmitriyが言ったことをエコーし​​ますが、ポイントを追加します。

30以上のテーブルに大きな行セットを挿入する必要があるバッチ請求システムに取り組みました。データポンプ(Oracle)を実行できないため、一括挿入を実行する必要がありました。これらのテーブルには外部キーがありましたが、すでに関係を壊していないことを確認していました。

挿入の前に、外部キー制約を無効にして、Oracleが挿入を永久に行わないようにします。挿入が成功したら、制約を再度有効にします。

PS:多くの外部キーと単一レコードの子行データを持つ大規模なデータベースでは、外部キーが不良になることがあり、カスケード削除を禁止する場合があります。課金システムでは、カスケード削除を行うと時間がかかり、データベースに負担がかかりすぎるため、メインドライバー(親)テーブルのフィールドを使用してレコードを不良としてマークします。

0
typicalrunt

DB2では、MQT(マテリアライズドクエリテーブル)が使用される場合、オプティマイザーが特定のクエリに対して適切なプランを選択するには、外部キー制約が必要です。それらにはカーディナリティー情報が含まれているため、オプティマイザーはメタデータを多用してMQTを使用するかどうかを決定します。

0
Senthil

データ構造設計の優れた原則の1つは、テーブルまたはオブジェクトのすべての属性が十分に理解されている制約を受けるようにすることです。あなたまたはあなたのプログラムがデータベース内の有効なデータを頼りにしている場合、不良データが原因でプログラムの欠陥が発生する可能性が低いため、これは重要です。また、エラー状態を処理するコードの作成に費やす時間が少なくなり、エラー処理コードを前もって作成する可能性が高くなります。

多くの場合、これらの制約はコンパイル時に定義できます。その場合、フィルターを記述して、属性が常に範囲内に収まるようにするか、属性の保存に失敗するようにできます。

ただし、多くの場合、これらの制約は実行時に変更できます。たとえば、最初に「赤」、「緑」、「青」などの値をとる属性として「色」を持つ「車」テーブルがあるとします。プログラムの実行中にその初期リストに有効な色を追加することが可能であり、追加された新しい「車」は最新の色リストの任意の色をとることができます。さらに、通常、この更新された色のリストは、プログラムの再起動後も維持されます。

あなたの質問に答えるために、実行時に変更できるデータ制約の要件があり、それらの変更がプログラムの再起動に耐えなければならない場合、外部キーが問題に対する最も簡単で簡潔な解決策であることがわかります。開発コストは1つのテーブルの追加(「色」、「cars」テーブルへの外部キー制約、インデックス)であり、実行時コストは最新の色の追加のテーブル検索です。データを検証します。このランタイムコストは通常​​、インデックス付けとキャッシュによって軽減されます。

これらの要件に外部キーを使用しない場合、リストを管理するソフトウェアを作成し、有効なエントリを探し、ディスクに保存し、リストが大きい場合はデータを効率的に構造化し、リストへの更新が行われないようにする必要がありますリストファイルを破損し、複数のリーダーやライターが存在する場合にリストへのシリアルアクセスを提供します。つまり、多くのRDBMS機能を実装する必要があります。

0
Jay Godse

それらを使わないのは怠け者だといつも思っていました。私はそれが常に行われるべきであると教えられました。しかし、その後、私はジョエルの議論に耳を傾けませんでした。彼には十分な理由があるのか​​もしれない、私には分からない。

0
Kilhoffer

Qかなり頻繁にエラーを受け取りますFK制約子行を追加または更新できません:外部キー制約が失敗します2つのテーブルinventory_sourceとcontract_linesがあり、 inventory_source_id in contract_lines from inventory_sourceを参照しており、inventory_sourceからレコードを削除し、そのレコードがすでにcontract_linesに存在するか、ベーステーブルからPK列を削除すると、FK制約のエラーが発生します。以下の手順を使用して回避できます。

CREATE TABLE inventory_source (
inventory_source_id int(11) NOT NULL AUTO_INCREMENT,
display_name varchar(40) NOT NULL,
state_id int(11) NOT NULL,
PRIMARY KEY (inventory_source_id),
KEY state_id (state_id),
CONSTRAINT ba_inventory_source_state_fk FOREIGN KEY (state_id) REFERENCES   ba_state (state_id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

CREATE TABLE contract_lines(
contract_line_id int(11) NOT NULL AUTO_INCREMENT,
inventory_source_id int(11) NULL ,
PRIMARY KEY (contract_line_id),
UNIQUE KEY contract_line_id (contract_line_id),
KEY AI_contract_line_id (contract_line_id),
KEY contract_lines_inventory_source_fk (inventory_source_id),
CONSTRAINT contract_lines_inventory_source_fk FOREIGN KEY       (inventory_source_id) REFERENCES ba_inventory_source (inventory_source_id)
) ENGINE=InnoDB AUTO_INCREMENT=135 DEFAULT CHARSET=utf8 ;

次の手順を使用してそれを克服できます。

  1. Inventory_sourceから行を削除または更新すると、contract_linesテーブル内の一致する行が自動的に削除または更新されます。これは、カスケード削除または更新と呼ばれます。
  2. それを行う別の方法は、contract_linesテーブルの列(inventory_source_id)をNULLに設定することです。これに対応するレコードがinventory_sourceテーブルで削除されます。
  3. 削除または更新の親テーブルを制限できます。つまり、inventory_sourceテーブルの削除または更新操作を拒否できます。
  4. 参照されるテーブルに関連する外部キー値がある場合、主キー値を削除または更新しようとしても続行できません。
0
Vikas Kukreti