web-dev-qa-db-ja.com

理論上、実際よ​​りも外部キーがよく使用されるのはなぜですか?

もちろん、リレーショナル理論を研究する場合、外部キーは必須です。しかし実際には、私が働いていたすべての場所で、DBMSの外部キーに依存するのではなく、クエリで明示的にキーを指定することによって、テーブルプロダクトと結合が常に行われます。

このようにして、当然のことながら、外部キーではないフィールドで2つのテーブルを結合して、予期しない結果になる可能性があります。

なぜだと思いますか? DBMSは、結合と製品が外部キーによってのみ作成されることを強制するべきではありませんか?

編集:すべての答えをありがとう。 FKの主な理由が参照整合性であることは、今では明らかです。ただし、DBを設計する場合、モデル内のすべての関係(つまり、ERDの矢印)は、少なくとも理論的には、DBMSで定義するかどうかに関係なく、外部キーになりますが、それらは意味的にFKです。 FKではないフィールドでテーブルを結合する必要性は想像できません。 誰かが意味のある例を挙げられますか?

PS:N:Mの関係が外部キーではなく個別のテーブルになるという事実を知っています。単純にするために省略しています。

48
Petruza

外部キー制約が存在する理由は、参照される行が存在することを保証するためです。

「外部キーは、別のテーブルの列または列のセットを参照する1つのテーブルの列または列のセットを識別します。参照する列の1つの行の値は、参照されるテーブルの単一の行に存在する必要があります。

したがって、参照テーブルの行には、参照テーブルに存在しない値を含めることはできません(NULLの可能性はあります)。このようにして、情報をリンクするための参照を行うことができます。これは、データベースの正規化の不可欠な部分です。 "( Wikipedia


RE:あなたの質問:「FKではないフィールドでテーブルを結合する必要性は想像できません」:

外部キー制約を定義する場合、参照するテーブルの列は、参照されるテーブルの主キー、または少なくとも候補キーでなければなりません。

結合を行う場合、主キーまたは候補キーを使用して結合する必要はありません。

以下は、意味のある例です。

CREATE TABLE clients (
    client_id       uniqueidentifier  NOT NULL,
    client_name     nvarchar(250)     NOT NULL,
    client_country  char(2)           NOT NULL
);

CREATE TABLE suppliers (
    supplier_id       uniqueidentifier  NOT NULL,
    supplier_name     nvarchar(250)     NOT NULL,
    supplier_country  char(2)           NOT NULL
);

次に、次のようにクエリします。

SELECT 
    client_name, supplier_name, client_country 
FROM 
    clients 
INNER JOIN
    suppliers ON (clients.client_country = suppliers.supplier_country)
ORDER BY
    client_country;

これらの結合が意味をなすもう1つのケースは、SQL Server 2008やPostGISを備えたPostgresなどの地理空間機能を提供するデータベースです。次のようなクエリを実行できます。

SELECT
    state, electorate 
FROM 
    electorates 
INNER JOIN 
    postcodes on (postcodes.Location.STIntersects(electorates.Location) = 1);

ソース: ConceptDev-SQL Server 2008地域:STIntersects、STArea

Sql 2008 query problem-which LatLong’s present in a geoography polygon ?? 」の投稿に対する承認済み回答で、別の同様の地理空間の例を確認できます。

SELECT 
    G.Name, COUNT(CL.Id)
FROM
    GeoShapes G
INNER JOIN 
    CrimeLocations CL ON G.ShapeFile.STIntersects(CL.LatLong) = 1
GROUP BY 
    G.Name;

これらはすべて、外部キーや候補キーとは関係のない有効なSQL結合であり、実際には依然として役立ちます。

39
Daniel Vassallo

外部キーは、データベースの整合性を維持するよりも、結合とはあまり関係がありません。その証拠は、必ずしも意味をなさない方法でも、好きな方法でテーブルを結合できることです。

34
Otávio Décio

FKではないフィールドでテーブルを結合する必要性は想像できません。誰かが意味のある例を挙げられますか?

FOREIGN KEYsは、ERモデルのエンティティ間の関係がリレーショナルモデルの2つの関係間の等価結合で反映される場合にのみ、参照整合性を適用するために使用できます。

これは常に正しいとは限りません。

少し前に書いた私のブログの記事の例を以下に示します。

このモデルは商品と価格帯を記述します:

そして、これがモデルのリレーショナル実装です:

CREATE TABLE Goods (ID, Name, Price)
CREATE TABLE PriceRange (Price, Bonus)

ご覧のとおり、PriceRangeテーブルには価格関連の属性Priceが1つしかありませんが、モデルにはStartPriceEndPriceの2つの属性があります。

これは、リレーショナルモデルではセットを変換でき、エンティティPriceRangeSQL操作を使用して簡単に再構築できるためです。

Goods
ID  Name               Price
1   Wormy Apple        0.09
2   Bangkok durian     9.99
3   Densuke watermelon 999.99
4   White truffle      99999.99

PriceRange
Price   Bonus
0.01       1%
1.00       3%
100.00    10%
10000.00  30%

各範囲の下限のみを保存します。上限は簡単に推測できます。

次に、各商品のボーナスを見つけるためのクエリを示します。

SELECT  *
FROM    Goods
JOIN    PriceRange
ON      PriceRange.Price =
        (
        SELECT  MAX(Price)
        FROM    PriceRange
        WHERE   PriceRange.Price <= Goods.Price
        )

これらのリレーショナルモデルはERモデルをかなり適切に実装していることがわかりますが、それらをバインドするために使用される操作は等結合ではないため、これらの関係の間で外部キーを宣言できません。

10
Quassnoi

いいえ、強制は不要です。列のオーバーロードの可能性など、いくつかの有用な機能が許可されません。この種の使用は理想的ではありませんが、ISは実際の状況で役立ちます。

外部キー制約の適切な使用法はそのとおりです。参照された行が存在することを保証する、特定の列に追加された値に対する制約。

特定のスキーマに対する外部キー制約の大幅な欠如は悪い「匂い」であり、いくつかの深刻な設計上の問題を示している可能性があることに注意してください。

8
Paul Sonier

任意の式で結合できます。データベースで外部キーを定義するかどうかは重要ではありません。外部キーは、SELECTではなくINSERT/UPDATE/DELETEを制約します。

では、なぜ多くのプロジェクトが外部キーの定義をスキップするのですか?いくつかの理由があります。

  • データモデルは設計が不十分であり、壊れた参照が必要です(例:多態的な関連付け、EAV)。

  • プログラマーは、「外部キーが遅い」と聞いてドロップする可能性があります。実際、外部キーに依存できない場合にデータの一貫性を確保するために実行しなければならない追加作業により、アプリの効率が大幅に低下します。効果を実際に測定せずに時期尚早に最適化することは、よくある問題です。

  • 制約は、一部のデータクリーンアップタスクの邪魔になります。データをリファクタリングするときに、参照を一時的に解除する必要がある場合があります。多くのRDBMSでは制約を無効にすることができますが、プログラマはleaveを無効にする方が簡単であると判断する場合があります。制約を無効にする必要が頻繁にある場合、これはおそらく深刻に壊れたデータベース設計を示しています。

6
Bill Karwin

あなたが説明する方法で使用される外部キーは、それらが使用されることを意図されている方法ではありません。それらは、対応するレコードに論理的に依存するレコードがどこかに存在する場合、その対応するレコードが実際にそこにあることを確認するためのものです。

開発者/ dbasが(A)開発者のテーブルとフィールドに適切な名前を付けるか、(B)広範な外部キー制約を定義する時間があれば、オプション[〜#〜] a [〜#〜]は簡単な選択です。私は両方の状況で働いてきました。秩序を維持し、人々が物事を台無しにしないようにするために広範な制約に依存していた場合、本当に混乱する可能性があります。

開発中にすべての外部キー制約を最新の状態に保つには多くの労力が必要です。時間はほとんどない他の重要なタスクに費やす可能性がある時間です。対照的に、適切な命名規則がある状況では、外部キーはすぐに明確になります。開発者は外部キーを検索したり、クエリを実行して機能するかどうかを確認したりする必要はありません。彼らは関係を見るだけです。

データベースを使用してさまざまなチームの数が増えると、外部キー制約がすぐに役立つと思います。一貫性のある命名を強制することは困難になります。 DBの知識が断片化します。 dbアクションが別のチームに意図しない結果をもたらすことは簡単です。

3
Patrick Karcher

実際には、理論では十分ではないので;)

真剣に、私の経験では主に、理論は現実世界で処理する必要があるすべての可能性を考慮するのに十分な柔軟性がないためです。 DBに格納する必要がある非常に奇妙な1つのケース(または、列のオーバーロードなどのより一般的なケース)でのみ、FKを取得してDALに実装する必要があります。

(たとえば)完全に正規化された方法でアーカイブできるソリューションを開発できるかもしれませんが、多くの場合、必要な作業や最終結果は十分な価値がありません。

私の2セント。

3
j.a.estevan

DBMSは、コアルールに従って機能しながら、さまざまなソリューションを可能にするように構築されています。

定義された外部キーへの結合を制限すると、特にほとんどの開発は専用のDBAやSQL /ストアドプロシージャの確認では発生しないため、機能が大幅に制限されます。

ただし、データアクセス層によっては、機能を使用するために外部キーを構成する必要がある場合があります。たとえば、Linq to SQL。

2
Bravax

DB /リレーショナルタイプの人々はコードの多くを記述したり、テーブルを設計したりしないため、リレーショナル理論が示唆するほど頻繁に外部キーが使用されることはありません。プログラマーはコード/設計テーブルを作成するか、テーブルの設計方法に大きな影響を与えます。

2
ElGringoGrande

どのようなデータベースアプリケーションに取り組んでいますか?よく目にする理論は、データベースをそのまま使用することです。この場合、制約は非常に役立ちます。実際には、データベースは大規模なアプリケーションのバックエンドとしてよく使用されます。多くの場合、これらのアプリケーションはトランザクション自体を検証する必要があり、データベースでそれを繰り返すのは無駄な作業です。

たとえば、販売アプリケーションを考えてみましょう。誰かが注文を入力すると、おそらくデータベースで顧客を検索して、住所やクレジットカード情報を取得します。それが顧客を見つけられないとき、それは合理的な何かをするようにプログラムされます。注文テーブルに行を挿入して顧客がいないことを発見するまで待機した場合、フィードバックが遅くなり、不便になります。

何かがデータベースの整合性を維持する必要がありますが、DBMS自体の中でそれを行うことが常に最良の方法であるとは限りません。

2
David Thornley

外部キーは非常に重要です。特に、手動でクエリを実行するデータベースや、アクティブなソフトウェアを開発しているデータベースでは重要です。データベースで実行されるすべてのテストされていないクエリには、エラーが含まれる可能性があります。外部キーなどの制約は、データに不整合が生じる前にこれらのエラーを強調するのに役立ちます。

これらの制約はスキーマの設計者によって適用され、想定したモデルにデータが残ることを保証します。制約がそこにない場合、遅かれ早かれクエリはいくつかの不整合をもたらします。不整合があると、クエリから予測できない結果が生じ、元に戻すのが非常に困難になります。

1
Paul

リレーショナルデータベースが一般化するずっと前から、私は数十年プログラミングしています。私が最初にPHPを習得したときにMySQLで作業を始めたとき、外部キーオプションを見て、最初に考えたのは「すごい!愚か者だけである理由は、実験室が現実を指示していると信じています。 everが変更されることのないアプリケーションをコーディングしていない限り、アプリケーションをスチールキャストでラップしていることはすぐにわかります。創造的なソリューションで。

この最初の評価は、私が遭遇したすべての実際の運用アプリケーションで生まれました。制約により、すべての変更が大幅に遅くなるだけでなく、ビジネスに必要なアプリケーションの成長がほぼ不可能になります。

テーブルの制約について私が見つけた唯一の理由は、遅延コーダーです。データの整合性をチェックするためのクリーンなコードを書く気はありません。

マイケル

1
Michael

私にとっての一部は、外部キーを追加するためのMSのSQL Server Management StudioのUIがawfulであることです(そして、はい、これは不十分な言い訳です)。

外部キーは「テーブルaの列xの値はテーブルbの列yに表示される必要がある」という制約ですが、SSMSでそれを指定するためのUIは、どのテーブルを操作しているかを明確に示していません。子テーブルである親テーブルなど。

外部キーを作成する必要があるたびに、機能するように見えるまで試行錯誤を繰り返しました。

0
Aric TenEyck

良い質問。 SQLに次のような構文がないのはなぜかといつも疑問に思っていました。

SELECT tbl1.col1, tbl2.col2
  FROM tbl1
  JOIN tbl2 USING(FK_tbl1_tbl2)

fK_tbl1_tbl2は、テーブル間の外部キー制約です。これは、NATURAL JOINまたはOracleのUSING(col1、col2)よりもはるかに便利です。

0
erikkallen

主な理由は、ほとんどのMySQL GUIツール(Navicat、MySQLなど)でクエリなしに設定する方法がないためです。

ばかげて聞こえるかもしれませんが、構文を覚えていないので、私もこれの罪を犯しています:/

0