主キー/外部キーの一致が結合に使用されないのはなぜですか?


48

多くのDBMS(mysql、postgres、mssqlなど)を見つけることができる限り、fkとpkの組み合わせはデータへの変更を制限するためだけに使用されますが、それらはネイティブで結合する列を自動的に選択するために使用されることはほとんどありません(名前での自然な結合のように)。何故ですか?pk / fkを使用して2つのテーブル間のリレーションシップを既に定義している場合、データベースでそれらのテーブルを結合するとpk / fk列で結合したいことがわかりません。

編集:これを少し明確にするために:

table1とtable2があるとします。table1の列aには外部キーがあり、これはtable2の主キーbを参照します。これらのテーブルを結合する場合、次のようにする必要があります。

SELECT * FROM table1
JOIN table2 ON table1.a = table2.b

ただし、table1.aがtable2.bを参照するキーを使用してすでに定義しているので、DBMSシステムがtable1.aとtable2.bを結合列として自動的に使用することを難しくするべきではないようです。次のように単純に使用できます:

SELECT * FROM table1
AUTO JOIN table2

ただし、多くのDBMSはこのようなものを実装していないようです。

回答:


32

多くの場合、2つのテーブルを結合する方法は複数あります。多くの例については、他の回答を参照してください。もちろん、そのような場合に「自動結合」を使用するとエラーになると言えます。それから、それが使用できる簡単なケースのほんの一握りが残されるでしょう。

ただし、重大な欠点があります!今日正しいクエリは、同じテーブルに2番目のFKを追加するだけで明日エラーになる可能性があります。

繰り返しますが、列を追加すると、それらの列を使用しないクエリが「正しい」から「エラー」に変わる可能性があります。

それは保守的な悪夢であり、正気のスタイルガイドはこの機能の使用を禁止します。select *同じ理由でほとんどはすでに禁止されています!

パフォーマンスが向上する場合、これはすべて受け入れられます。ただし、そうではありません。

要約すると、この機能は限られた一連の単純なケースでのみ使用でき、パフォーマンスは向上せず、ほとんどのスタイルガイドでは使用が禁止されます。

そのため、ほとんどのデータベースベンダーがより重要なことに時間を費やすことを選択するのは当然のことです。


1
結合列を特定するのではなく把握する必要があるため、実際には小さなパフォーマンスヒットが発生する可能性があります。
HLGEM

1
@HLGEM、これはキャッシュされる可能性があり、大規模なクエリには関係ありません。利点は、何らかの人為的ミスによってキーが失われないことを確認できることです。
Pacerier

列の追加と変更も壊れる可能性がありますNATURAL JOIN(これが通常それらを避ける理由です)が、dbmsが外部キーに基づいてテーブルを自動的に結合する方法を実装できないことを意味するとは思わない。
ジェイK

2
多くの場合?数千のテーブルDBでは、2つのテーブル間に1を超えるリレーションのケースがいくつかあります。とにかく、それは問題ではなく、のような関係名を追加するだけで十分AUTO JOIN mytable THROUGH myrelationでしょう。
ティージェイ

それは、我々は特注.NET SQLビルダーで仕事だインテリセンスと、のようなInnerJoin(SRC_TABLE.rDEST_TABLE.REL_NAME_F01)
Teejay

27

外部キーは、データを制約するためのものです。すなわち、参照整合性を強制します。それでおしまい。他に何もありません。

  1. 同じテーブルに対して複数の外部キーを持つことができます。出荷に開始点と終了点がある場合、以下を考慮してください。

    table: USA_States
    StateID
    StateName
    
    table: Shipment
    ShipmentID
    PickupStateID Foreign key
    DeliveryStateID Foreign key
    

    ピックアップの状態に基づいて参加することもできます。たぶん、あなたは配達状態に参加したいです。たぶん、あなたは両方のために2つの結合を実行したいです!SQLエンジンには、何が欲しいかを知る方法がありません。

  2. 多くの場合、スカラー値を交差結合します。スカラーは通常、中間計算の結果ですが、場合によっては、正確に1つのレコードを持つ特別な目的のテーブルがあります。エンジンが結合の外部キーを検出しようとした場合...クロス結合は列と一致しないため、意味がありません。

  3. 特別な場合には、どちらも一意ではない列で結合します。したがって、これらの列にPK / FKが存在することは不可能です。

  4. あなたは、あなたの質問があったときについてですので、ポイント2と3は、上記関連していないと思うかもしれISテーブル間の単一PK / FKの関係。ただし、テーブル間に単一のPK / FKが存在するからといって、PK / FKに加えて他のフィールドを結合することはできません。SQLエンジンは、どのフィールドに参加したいかを知りません。

  5. 「USA_States」というテーブルと、州へのFKを持つ他の5つのテーブルがあるとします。「5つの」テーブルには、相互にいくつかの外部キーもあります。SQLエンジンは自動的に「5つの」テーブルと「USA_States」を結合する必要がありますか?または、「5」を互いに結合する必要がありますか?両方?関係を設定して、SQLエンジンがものを結合しようとする無限ループに入るようにすることができます。この状況では、SQLエンジンが必要なものを推測することは不可能です。

要約すると、 PK / FKはテーブル結合とは関係ありません。それらは独立した無関係なものです。PK / FKコラムに頻繁に参加するのは、単なる偶然です。

SQLエンジンに、それが完全結合、左結合、右結合、内部結合のいずれであるかを推測させますか?そうは思いません。おそらく、結合する列を推測するよりも罪は少ないでしょう。


7
外部キーと正規化は、テーブル結合に非常に関連があると考えています。

3
通常のJOINキーワードが常にそれに一致しようとするときに引数が保持されます(この例では間違っていたので、修正します)。ただし、多くの結合は結合のみから直接派生できるため、結合するための明示的な構文がない理由はわかりません。多くのDBMSには自然結合があります。これは基本的に同じことを行いますが、列名(= bad)を使用します。AUTO JOIN操作を指定するなど、このタイプの結合でも同じことができます。

5
「PK / FKコラムによく参加するのは自然の偶然です」-私は確信していません!
いつか

2
「正規化?」ここでの考えは、1NF relvarで開始してから6NF relvarに分解した場合、可能性はa)実装に外部キーがあり、b)クエリに頻繁に参加することだと思います。
いつか

4
「PK / FKはテーブル結合とは関係ありません」
ypercubeᵀᴹ

11

「結合性」の概念。リレーションr1r2は、同じ名前の属性が同じタイプである場合にのみ結合可能です。この概念は、結合だけでなく、他のさまざまな操作(ユニオンなど)にも適用されます。

SQLおよびリレーショナル理論:CJ日付ごとに正確なSQLコードを記述する方法

標準SQLには、として知られるそのような機能が既にありNATURAL JOIN、mySQLに実装されています。

あなたの提案はそれほど価値がありませんが、合理的なもののようです。SQL Server(のサポートがないNATURAL JOIN)では、Management StudioでSQLプロンプトを使用しますINNER JOIN。InteliSenseを作成するときONに、共通の属性名と外部キーの両方に基づいて句を提案し、非常に便利です。ただし、このために新しい(標準の)SQL結合タイプを見たいとは思いません。


1
共通の列での自然な結合と結合は、FK-PKでの結合の概念とは異なります。(私の答えを参照してください。)
philipxy

@philipxy:同意しました。そうでないことを意味するつもりはありませんでした。(あなたの答えは素晴らしい答えです!)
onedaywhen

9

SQLが最初に登場しました!

外部キーと外部キーの制約は後で登場し、本質的には「トランザクション」スタイルのアプリケーションの最適化です。

リレーショナルデータベースは、元々、リレーショナル代数を使用して数学的に証明可能な方法でデータセットに複雑なクエリを適用する方法として考えられていました。特定のデータセットと特定のクエリのIEには、常に1つの正解があります。

それ以来、リレーショナルデータベースは大きな進歩を遂げており、トランザクションシステムの永続化レイヤーとしての主な用途はCODDなどではありませんでした。想定されるすべて。

ただし、ANSIのすべての矛盾する目標とベンダーの方針に関する標準化団体は、SQLの「数学的に証明可能な」特性を維持するよう常に努力しています。

データベースが「隠された」外部キーデータから結合プロパティを推測できるようにした場合、このプロパティは失われます(複数の外部キーセットが定義されている場合のあいまいさを考慮してください)。

また、SQLを読んでいるプログラマーは、2つのテーブルに対して現在どの外部キーが定義されているかを必ずしも知る必要がなく、データベーススキーマを調べてクエリが何をしていたかを調べる必要があります。


3
おかげで、これは私には理にかなっています!しかし、自然な結合にも同じ問題はありませんか?自然結合にはさらに大きな問題がありますが、多くのDBMSはそれらをサポートしています。IMO pk / fkに基づく結合は、自然に正しく行われます。

1
ほとんどのデータベースエンジンが、自然な結合と明示的な "JOIN ... ON"の間で関係している限り、違いはありません。エンジンはクエリを分析し、さまざまな述語に基づいてできる限り最善の方法で結合を実行します。明示的な結合を使用しても、特定のインデックスまたはアクセスパスの使用は強制されません。主に、「欠落」行を挿入するタイミングを知るために明示的な結合述語を知る必要がある「LEFT、OUTER、INNER」結合構文をサポートします。

6
SQLが最初に来たわけではありません!リレーショナルモデル(もちろん、外部キーの概念を含む)は、1969年にEFCoddによって最初に概説されました。その後のSEQUELは、1974年頃まで日の目を見ませんでした。その発明者は、 SEQUEL / SQLは、既存のリレーショナルモデルに基づくことを目的としていましたが、SQLは真のリレーショナル言語ではありませんでした。
nvogel

@sqlvogel-true!「最初にSQLが実装された」と表現すべきでした。
ジェームズアンダーソン

「データベースシステムの概要」(p276)のCJ Dateは、Coddが外部キーの概念を発明したと述べています。いつ言うかはわかりませんが、最初のSQL実装の前だと思います。
いつか

7

外部キー関係を定義しましたが、それはすべてのクエリでテーブルを結合する方法ではありません。テーブルを結合する最も可能性の高い方法ですが、正しくない場合があります。

  • 何らかの目的で、2つのテーブルのデカルト積またはその一部を使用できます。
  • 別の目的で参加できる他のフィールドがある場合があります。
  • 3つ以上のテーブルを結合する場合、1つのテーブルが2つ以上のテーブルに関連している可能性があります。この場合、通常、可能なFKリレーションシップの1つだけがクエリで適切である可能性があります。

7

誤った仮定で操作している可能性があります。 あなたは「あなたが知る限り」と言いますが、経験的または証拠的な証拠を与えません。pkまたはfkがクエリに最適なインデックスである場合、それが使用されます。なぜあなたはこれを見ているのか分かりませんが、私の推測では、不適切な形式のクエリです。


質問が完全に書き直されたので、今編集してください。あなたが説明しているケースは、非常に小さなクエリのセットのためだけです。結合されたテーブルが12個ある場合はどうなりますか?FKがない場合はどうなりますか...デフォルトの結合があったとしても、読みやすさのために常に結合を指定します。(データを見てから、何に結合されているかを把握する必要はありません)

一部のクエリツールは、実際に自動結合を実行してから、結合を削除または編集できます。MS Accessのクエリビルダーがこれを行うと思います。

最後に、ANSII標準では、結合を指定する必要があると規定されています。それが許可しない理由です。


3
申し訳ありませんが、おそらく十分に明確ではありませんでした。インデックスのことではなく、結合のことです。table1とtable2があり、table1.aのfkがtable2.bを指しているとします。これらのテーブルを結合する場合、列aとbで結合することを明示的に指定する必要があります(例: 'SELECT * FROM table1 JOIN table2 ON table1.a = table2.b ')これら2つが関連するスキーム。問題は、「SELECT * FROM table1 JOIN table2」を実行できず、fk / pkに基づいてDBMSが結合列を自動的に選択できない理由です。

3
特に読みやすさは私にとって理にかなっています!しかし、標準がそう言っていることは、IMOとしては本当に良い議論ではありません。以前は、多くの標準が間違った選択をしていました(たとえばHTML)。

3

外部キーを追加/削除すると、アプリケーションのソースコード内のクエリを含む事前に作成されたクエリの意味が変わるなど、データベースがこれを安全に行えない多くの理由があります。また、ほとんどのデータベースには、実行する可能性のあるすべての結合をカバーする外部キーの良いセットがありません。また、より良いまたは価値があるために、外部キーはシステムを高速化するために削除されることが多く、ファイルから「間違った」順序でロードされたテーブルでは使用できません。

ただし、クエリデザインツールまたはテキストエディターが列名のインテリセンスを提供するのと同じ方法で、外部キーの助けを借りて結合を自動完了できない理由はありません。ツールで問題が発生した場合はクエリを編集し、完全に定義されたクエリを保存できます。このようなツールは、「親」テーブル名と親/子テーブルなどの両方で同じ名前の列によって外部キー列に名前を付けるという慣習を有効に利用することもできます。

(私の妻はまだManagement StudioとSql Serverの違いを理解できず、彼女が管理スタジオを起動したときのsqlサーバーの起動について話します!)


3

自然が参加する「自動的に」共通の列の平等に参加するが、それはあなたが何場合のみ、それを書くべきたいテーブルの意味とあなたのdesied結果に基づきます。2つのテーブルがどのように「結合」されるべきか、または他の方法でクエリに「存在」されるべきかを「自動的に」知ることはできません。クエリするための制約を知る必要はありません。それらの存在は、入力が制限される可能性があることを意味し、その結果、出力も制限される可能性があります。宣言された制約ごとに「自動的に」結合する、ある種のjoin_on_fk_to_pk演算子を定義できます。ただし、テーブルの意味ではなく制約のみが変更された場合にクエリの意味を同じままにしたい場合は、新しい宣言された制約を使用しないようにそのクエリを変更する必要があります。制約の変更にもかかわらず、すでに同じ意味を残しています

保持される制約(PK、FK、UNIQUEおよびCHECKを含む)は、テーブルの意味に影響しません。もちろん、テーブルの意味が変わると、制約が変わる可能性があります。ただし、制約が変更されても、クエリが変更される必要があるという意味ではありません。

クエリするための制約を知る必要はありません。制約について知ることは、制約を保持しなければ同じ答えを返さない式をさらに使用できることを意味します。たとえば、UNIQUEを介してテーブルに1つの行があることを期待しているので、それをスカラーとして使用できます。制約が仮定されているが宣言されていない場合、これらのクエリは破損する可能性があります。しかし、クエリが想定していなかった制約を宣言しても、それを破ることはできません。

人間が読める記述からSQLクエリを構築するための経験則はありますか?


2

その理由は、言語があり、その下に基本的なプリンシパルがあるからです。この言語はまばらで、汎用言語で見られる多くの機能が欠けています。これは単に言語に追加されていない素晴らしい機能であり、おそらく追加されないでしょう。それは死んだ言語ではないので、いくつかの希望がありますが、私は楽観的ではありません。

他の人が指摘したように、一部の実装では、結合(列)が共通の列名に基づいて2つのテーブルを結合する拡張機能を使用します。しかし、それは広く普及していません。この拡張機能はSELECT * FROM employee NATURAL JOIN department;、使用する列を指定する方法を含まない構文とは異なることに注意してください。どちらもテーブル間の関係に依存しないため、テーブルは信頼できなくなります(拡張よりも自然な結合構文)。

PKFKが「2つのテーブル間で定義された外部キー関係」を意味するキーワードである場合、「PKFKの内部結合テーブル」に根本的な障害はありません。問題は、言語を設計する人々が、a)良いアイデアであり、b)他の言語の変更よりも作業をする方が良いと考えるかどうかです...


3
これは、彼らがすでに行っているべきであるというのは良い考えだと仮定しています。また、彼らはすでにこれを考慮しており、それを行わないことにした可能性があります。おそらく、実際には非常に悪い考えです。Sjoerdは、クエリが新しい列とFKの関係を追加するだけで中断する可能性がある例を挙げました。また、Tydus alsoは、テーブルの結合方法を決定することとは異なる責任を持つ外部キーについても説明しています。

1
@JonathanHobbs:私の答えは一般的に中立であることを意味していましたが、中立性を放棄しました。Sjoerdのロジックには欠陥があります。これにより、実際には、テーブルの関係が維持されている限り、列の変更を安全に行うことができますが、これはある程度まであなたを隔離します。 PK上にあるか、Pkを含みます。マルチfkを処理するには、列名を使用します。
jmoreno

1

ON句を省略すると、参照整合性に基づいてフィールドに従うと想定される場合、デカルト積はどのようになりますか?

編集:AUTOを使用 するこれの利点は、入力が少し少なくなることと、結合方法を知ったり、複雑な結合を覚えたりする必要がないことです。リレーションシップが変更された場合、自動的に処理されますが、開発の初期段階を除いてほとんど発生しません。

あなたが今しなければならないことは、あなたの選択ステートメントの意図に一致するように関係の変更中にすべてのAUTO結合が保持されるかどうかを決定することです。


@JeffO:主な利点は、非常に明確な宣言方法で意図をより正確に表現することです。列名の結合は、列の内容の一部が別の列の内容と似ている(ただし、同じタイプではない可能性がある)こと以外は何もわかりません。そこにいることを示しています、FK REFに参加している FK refは、列のリストは、テーブル間の唯一の1 FKがあったわけないだろう、あるいは逆1+があることが(何が起こるか以上1 REFと複数列のキーを検討します列c1 = fk1_c1とc2 = fk2_c2)を混合します。平均してさらに入力しても、これは良いことです。
jmoreno

ONなしで(INNER)JOINを使用することは標準SQLではありません。カンマ、CROSS JOIN&(INNERまたはOUTER)JOIN ON 0 = 0は、デカルト積を返します。
philipxy

-1

これらのテーブルを結合する場合、pk / fkカラムで結合したいことをデータベースが理解できないのはなぜですか?

理由の一部は次のとおりです。

1-理論的には、2つのテーブルの任意の列でテーブルを結合できます。これは一般的な方法ではありませんが、有効です。SQLはプログラミング言語のようなものであり、SQLにとって当然のことながら、名前が列の内部にある情報を理解していないことに注意してください。

2-さまざまな種類の結合(左、右、内部)があります-内部結合はそのうちの1つのみです。

3-SQL標準は、高レベルの方言がそれを使用してインテリジェンスを形成できるようにする低レベル言語であるという原則によって導かれる場合があります。第4世代の言語と第3世代の言語を考えると、比較はいくらか明確になります。実際、私が使用したツールの1つであるIEFにより、次のような記述が可能になりました。

ReadEach Customer 
Where Customer Places Orders and That Customer LivesIn "California" 
and OrderValue > 100.00

要約すると、提案は興味深いものであり、標準の一部として、またはストアドプロシージャとして実装できます(既定では内部結合になります)。


-10

Tiddo、あなたは完全に正しいと信じています、そのトピックのSQLは非常に愚かであり、10年前にSQLを学習している間に外部キーについて同じことを考えたことを覚えています。

OK、それを考えると、私は最終的にその試験に合格しなければなりませんでした。合格するには、手放す必要がありました。SQLは誰もが認める可能性のあるものよりも多くの難問であり、その標準化パスは完全な災害であり、一部の実装は恐ろしく完全なものです。それでも、一般的には非常に便利です。(私はK / Vラディットではありません)

外部キー、それでは...それほど便利ではありません。彼らは重要な中に概念リレーショナルモデル、[OK]を、しかし、同じ名前のSQL機能が十分に比較されません。

まっすぐに教える:と呼ばれるそのSQL機能を使用していないForeign Keyすべてのを、あなたはパフォーマンスの問題といくつかの大きなシステムを打つまで。明示的にエンジン伝えるフィールドは外部キーとされていないですのみインデックス付けのために使用され、それがDBユーザーには見えないのですが。

誤解を招くものですか?
はい。

30年間の人々が誤解された後、彼らは今、それをより強力にするつもりですか?
チャンスじゃない。

必要になるまで外部キーを完全に無視します... 私のためにSQLを修正しましたか?
はい!

そして、なぜこれらすべてがそもそも起こったのでしょうか?
さて、外部キーと呼ばれる機能は、後でSQLに追加されました。SQLは、時間の経過とともにボトムアップで進化した標準です。ベンダーは滑luな機能を実装しましたが、標準的なボディは顔をしかめました。

前述の外部キー。インデックス作成のみを目的としており、JOINコンストラクトはありません。(で行わどこ加入SELECTクエリ、JOINクエリはかなり最近であり、唯一の別名に意味SELECT機能)がインデックスフラグを呼び出すことを彼らはおそらくかかわらずFOREIGN KEY、だった巧妙な命名-ハックリレーショナルDB理論の概念の上に。


13
外部キーに関しては、MySQLのMyISAMエンジンに触れたことがありますか?「その小さな暴言を無視しても、この答えのすべてが間違っています。

Fkはインデックス付けには使用されません。実際、fk列にパフォーマンスの劇的な影響を与える可能性のあるインデックスがないことが一般的な問題です。
jmoreno
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.