主キー/外部キーの命名規則[終了]


95

私たちの開発グループでは、主キーと外部キーの命名規則に関して激しい議論があります。私たちのグループには、基本的に2つの考え方があります。

1:

Primary Table (Employee)   
Primary Key is called ID

Foreign table (Event)  
Foreign key is called EmployeeID

または

2:

Primary Table (Employee)  
Primary Key is called EmployeeID

Foreign table (Event)  
Foreign key is called EmployeeID

私は、どの列でもテーブルの名前を複製しないことを好みます(したがって、上記のオプション1を好みます)。概念的には、プロパティ名にオブジェクトの名前を使用しない他の言語で推奨されている多くの慣習と一致しています。私は、外部キーに名前を付けるとEmployeeID(またはそれEmployee_IDよりも良いかもしれません)、それが表のID列であることを読者に伝えると思いますEmployee

列名がデータベース全体で同じになるように、テーブル名を前に付けた主キーに名前を付けるオプション2を好む人もいます。その点はわかりましたが、主キーと外部キーを視覚的に区別することはできなくなりました。

また、私はそれはあなたがエンティティとそのエンティティのプロパティまたは属性として列としてテーブルを考えるならば、あなたはのID属性と考えるので、列名にテーブル名を持つように冗長だと思うEmployee、ありませんEmployeeID従業員の属性。私は同僚に何を言っているのPersonAgeか尋ねませんPersonGender。私は彼に彼の年齢は何であるか尋ねます。

だから私が言ったように、それは激しい議論であり、私たちはそれについて何度も何度も繰り返します。私はいくつかの新しい視点を得ることに興味があります。



1
私は10の以上の同様の質問を読んで、最終的にここにトップ3の回答が良好であるが見つかりました:stackoverflow.com/a/465146/781695
ユーザー

余談ですが、選択肢2では「自然な結合」が可能になります。一体、 'Employee.IDをEmployeeID'として追加して、選択肢1でまだそれを行わないのはなぜですか。しかし、より良い実践方法は、「ON Employee.ID = Event.EmployeeID」を使用して「結合」することです。
レオ

どちらの場合も、1つ以上のクエリでエイリアス(または 'table_name.column_name')を使用する必要があります。これは、どちらの場合も列名を繰り返すためです。
Please_Dont_Bully_Me_SO_Lords '11 / 11/18

回答:


52

それは本当に重要ではありません。選択肢1と選択肢2に実際の違いがあるシステムに出くわしたことはありません。

ジェフ・アトウッドはこのトピックについてしばらく前に素晴らしい記事を書いてくれました。基本的に人々は、彼らが間違っていると証明できないこれらのトピックについて最も激しく議論し、議論します。または別の角度から見ると、フィリバスタースタイルの持久力に基づく最後の常人の議論によってのみ獲得できるトピック。

1つを選択して、実際にコードに影響を与える問題に集中するように伝えます。

編集:楽しみたい場合は、その方法が再帰的なテーブル参照に優れている理由を詳細に指定してもらいます。


26
+1、常識のため...議論するべきより重要な事柄があります..だから、私のやり方で行ってください(選択肢2)
Charles Bretana

5
また、自己参照DRIの場合、同じPKを自己参照する複数のFKがある場合、2つのFK列に同じ名前を付けることはできないため、両方の「標準」に違反する必要があります...例:EmployeeTable EmployeeId PK、SupervisorId FK、MentorId Fk、PartnerId FKなどを含む...
Charles Bretana、2009

75

2つの列が両方のテーブルで同じ名前である場合(慣例#2)、SQLのUSING構文を使用して、入力とボイラープレートノイズを節約できます。

SELECT name, address, amount
  FROM employees JOIN payroll USING (employee_id)

規約#2を支持するもう1つの議論は、これがリレーショナルモデルの設計方法だということです。

各列の重要性は、対応するドメインの名前でラベル付けすることによって部分的に伝えられます。


4
SQLの構文とセマンティクスは、実際にSQLの使用方法についてかなり良い手がかりを与えます。たとえば、USING構文は同じドメインの列が同じ名前であることを意味し、NULL = NULL-> NULLはNULLが「該当なし」ではなく「不明」であることを意味し、ON UPDATE CASCADEはキーが一意であり、不変ではないことを意味します。
Steven Huwig

6
さらに良いことに、これにより次のことが可能になりますSELECT name, address, amount FROM employees NATURAL JOIN payroll
1

5
デプロイされたコードでは自然結合を使用しません。これは、スキーマの追加の場合、脆弱であるためです。しかし、インタラクティブなクエリについては、それは素晴らしいことです。
Steven Huwig、2012

3
+1しかし、常に例外があります。たとえば、給与に2つの列があり、どちらも従業員に対する外部キーである場合(1つは支払われる人への参照、2つ目は予算権限を持つマネージャーへの参照など)。ただし、両方の外部キーに名前を付けることはできませんemployee_id
Bill Karwin 2013

1
「using」キーワードはMySql固有です。残念ながらT-SQLでは機能しません。
バーダス2017

12

アプリケーションの組み立て方次第だと思います。ORMを使用するか、オブジェクトを表すためにテーブルを設計する場合、オプション1が適しています。

データベースを独自のレイヤーとしてコーディングするのが好きです。私はすべてを制御し、アプリはストアドプロシージャを呼び出すだけです。特に結合されたテーブルが多く、返された列が多い場合は、結果セットに完全な列名を付けると便利です。このタイプのアプリケーションでは、オプション2が好きです。結合で列名が一致するのを確認したいのです。私は古いシステムで作業しましたが、それらが一致せず、悪夢でした。


4
+1、一致しない列名との結合を理解する必要がある
Raj More

4
「古いシステム」では、8文字の長い名前のハンディキャップは、これよりもはるかに傷つきます。私はすぐに出かけて、IDという名前のPKを持つことが、あなたが扱っていた古いシステムの悪夢の主な原因ではなかったと推測しています。また、「古いシステムに吸い込まれた」という表現は、ソフトウェア開発、特にデータベースで頻繁に使用されています。私は、10年以上前にリリースされたDBシステムでの経験に基づいて、特定のプラクティスAを正当化する人々を日常的に見ています。
ラッセルスティーン

2
今日の最先端のアプリケーションは、数年後には古くなってしまいます。インターフェイスを書き換えたり、別のプラットフォームでデータを使用したりすることもできますが、データ(列名を含む)は時の試練に耐える必要があります。
和基。

2
それで、20文字前の人々は、8文字しかなかったにもかかわらず、どういうわけか今日では意味のある列名を使用するべきでしたか?データストレージのフォーマットは過去20年間で大幅に変化し、今後20年間で再び変化します。あなたの好みがリストされている他の方法よりも時間のテストに耐えられることを証明する方法はありません。データの保存と操作の能力が向上するにつれて、人々が20年以内にこの議論をするまでには、「列名」自体が「古臭い」である可能性があります。テーブルは不完全データの関係を表している人間の構文です...
ラッセル・スティーン

1
十分な根拠のある知的応答に感謝します。
ラッセルスティーン、

3

どちらの規約もすべてのケースで機能するわけではないので、なぜ1つしかないのでしょうか。常識を使う...

たとえば、自己参照テーブルの場合、同じテーブルのPKを自己参照する複数のFK列がある場合、2つのFK列に同じ名前を付けることはできないため、両方の「標準」に違反する必要があります...例えば、EmployeeId PK、SupervisorId FK、MentorId Fk、PartnerId FKなどのEmployeeTable ...


1
+1は実際の技術目標の回答
DVK

適切で適切な答えですが、デムスの答えに対する議論は要点を逃しています。
JYelton 2010

3

それらの間で選択することはほとんどないことに同意します。どちらの標準についても私にとってはるかに重要なことは、「標準」の部分です。

人々が「自分でやること」を始めるなら、彼らは彼らの地獄に縛られているはずです。私見では :)


3
一貫性が「正しい」よりも重要であることを認識するための+1(この場合)
Russell Steen

「愚かな一貫性」を適用しようとする場合は-1。古い中国のことわざは「愚かな一貫性は単純な心のホブゴブリンです」と言います。
Charles Bretana、2010年

@charles:さまざまな人々がお互いのコードを管理している世界では、多くの場合、ライターが去り、ドキュメントが古くなっているか存在しない場合、これは愚かな一貫性ではありません。私はあなたと一緒に仕事をしないのでとてもうれしいです...
MatBailie 2010年

@Dems、意図的な攻撃はありませんが、これは2つの理由で愚かです。1)いずれかの標準に違反する必要がある、よく理解された一般的なシナリオがあります。(例と2については私の回答を参照してください)この問題に関しては、少なくとも、標準は、標準が好きな人がより快適に感じることを除いて、ほとんど価値がありません...
Charles Bretana 2010年

1
「ID」はより一貫していると主張できます。「cars」テーブルまたは「car」テーブルに英語の「carID」を導入するとすぐに?「sheep」テーブルの「sheepID」または「sheeps」-物事が矛盾​​し始めます。「ID」と単数のテーブル名に固執する場合-これは一貫性があるだけでなく、多くのORMでうまく機能します/構成も少なくてすみます(例:Dapper Contrib)
niico

3

次のことを検討しましたか?

Primary Table (Employee)   
Primary Key is PK_Employee

Foreign table (Event)  
Foreign key is called FK_Employee

3
人々が反対票を投じたとき、私は我慢できず、理由を述べません。これは完全に有効な回答です。一部の人にとって口当たりが良いかどうかは別の質問ですが、これは主観的であり、反対票を投じる必要はありません。
ジェレミー

1
これを指摘してくれてありがとう。このフォーマットを使用しない理由にも興味があります。そして、私には十分な理由があると確信しています...
Wouter

これは、あなたが使用する必要はありませんようにして最良の方法ですtable_name.column_name...クエリでは、繰り返しの名前を持っていない場合は、列名のエイリアスを使用する必要はありません
Please_Dont_Bully_Me_SO_Lords

1
これはハンガリーの表記法の一種と考えることができます。したがって、賛成と反対の議論を検討してください。
フレッド

2

私が使用する規則は、Aにかなり似ていますが、複数形(つまり、「従業員」)でテーブルに名前を付け、テーブル名と列名の間にアンダースコアを使用している点が異なります。この列の利点は、列へのアクセス方法に応じて、「employees _ id」または「employees.id」のいずれかになることです。列の取得元のテーブルを指定する必要がある場合、 "employees.employees _ id"は間違いなく冗長です。


複数形のテーブル名が好きかどうかは決めていません。単数形を使用することにより、クエリは読みやすくなります( "employees.name"ではなく "employee.name")。結合の場合でも、単一のレコードを別のテーブルに結合しているため、読みやすくなります。ただし、複数のテーブル名は、クエリではなくテーブルについて考えるとより正確に見えます。それが私たちが使用するものなので、私は単数形に固執しますが、それはまた進むべき正しい方法だと思います(ただし、多くの人が同意しません)
MatBailie

うん。個人的な好みや、あなたが見慣れているもののどちらかだと思います。
ジャレットミラード

2

データベースクエリだけでなく、アプリケーションコードも見てみると、いくつかのことがはっきりとわかります。

  1. テーブル定義は通常、1つのオブジェクトを記述するクラスに直接マップされるため、それらは単数である必要があります。オブジェクトのコレクションを説明するために、通常、単数形の名前に「配列」、「リスト」、または「コレクション」を追加します。複数形を使用するよりも、それがコレクションであることだけでなく、どのようなコレクションであるかを明確に示すためですそうです。そのビューでは、テーブル名はコレクションの名前ではなく、それがコレクションであるオブジェクトのタイプの名前として表示されます。アプリケーションコードを記述しないDBAは、この点を見落とす可能性があります。

  2. 私が扱うデータでは、非キー識別の目的で「ID」を使用することがよくあります。キー "ID"と非キー "ID"の混同を避けるために、主キーの名前には、テーブル名またはその省略形を前に付けた "Key"(つまり、そうですね)を使用します。テーブル名。この接頭辞(および私はこれを主キーに対してのみ予約します)はキー名を一意にします。これは、データベースの列名と同じ変数名を使用し、ほとんどのクラスには、親キー。これは、「Key」だけのように、予約済みキーワードではないことを確認するためにも必要です。キー変数名の一貫性を維持し、自然結合を行うプログラムを提供するには、外部キーは、それらが主キーである表で使用されているものと同じ名前です。自然結合を使用してこの方法ではるかにうまく機能するプログラムに一度以上遭遇しました。この最後の点で、私が使用した自己参照テーブルの問題を認めます。この場合、外部キーの命名規則に例外を設けます。たとえば、ManagerキーをEmployeeテーブルの外部キーとして使用して、そのテーブルの別のレコードをポイントします。


Entity Frameworkなどの多くのオブジェクトリレーショナルマッパー(ORM)では、テーブルを別の名前のクラスにマップできます。これにより、「User」という名前のクラスと「Users」という名前のテーブルを持つことができます。
フレッド

2

私はコンベンション#2が好きです。このトピックを調査し、自分の質問を投稿する前にこの質問を見つけると、次の問題に遭遇しました。

多数の列を持つテーブルから*を選択し、それを同様に多数の列を持つ2番目のテーブルに結合しています。どちらのテーブルにも主キーとして「id」列があります。つまり、結果でこれらの2つの値を一意にするために、(私の知る限り)すべての列を具体的に選択する必要があります。

SELECT table1.id AS parent_id, table2.id AS child_id

規則#2を使用すると、同じ名前の列が結果に含まれることになりますが、必要なID(親または子)を指定できるようになり、Steven Huwigが示唆したように、USINGステートメントによってさらに単純化されます。


2
SELECT *とにかく、(ほとんどの)プロダクションクエリはノーノーなので、命名基準を選択する理由はそれほどありません。
Pダディ

1
反対しない:これがそうである理由へのリンクを提供できますか?クエリで80列の名前を維持する必要があるという考えは好きではありません。
JYelton 2010

現時点ではリンクが見つかりません(「*」ではグーグル検索が難しい)が、基本的なポイントを概説します:(1)テーブルへの変更はアプリケーションに悪影響を与える可能性があります、(2)それは可能性があります(3)実際に必要なデータを明示的に指定すると、コードが理解しやすくなります。これらの点は拡大する可能性があり、例外もあります(私がほのめかしたように)が、ここでは適切ではありません。これを新しい質問として投稿した場合、私(および他の人)はさらに詳しく説明してくれると思います。
Pダディ

2
私はそうするかもしれません。パフォーマンスのメリットは実感できますが、コードを編集する際には時間の投資を考慮する必要があります。アプリとデータベース間の相互作用を改善する方法を常に探しています。ありがとう。
JYelton 2010

1
私はSELECT *ほとんどのプロダクションクエリに対してノーノーであるかどうかを確信していません。開発速度が大幅に向上し、コードがより簡潔で読みやすくなる場合-より重要な事項に集中できるようになります-なぜSELECT *ですか?それは各状況の状況に大きく依存し、多くの要因間のトレードオフです。1つのルールがすべてに当てはまることはめったにありません。
niico

2

私は常に1つのテーブルのPKとしてuserIdを使用し、別のテーブルのuserIdをFKとして使用してきました。userIdPKuserIdFKを名前として使用して、お互いを識別することを真剣に考えています。テーブルを見るときにPKとFKをすばやく特定するのに役立ちます。また、PHP / SQLを使用してデータにアクセスすると、コードがわかりやすくなり、理解しやすくなります。特に誰かが私のコードを見るとき。


1

規約#2を使用します。現在、レガシーデータモデルで作業していますが、指定されたテーブルの意味がわかりません。冗長であることの害はどこにありますか?


1

外部キーに名前を付けるのはどうですか

role_id

ここで、roleは、参照されるエンティティが手元のテーブルに関連する役割です。これにより、同じテーブルへの再帰参照と複数のfkの問題が解決されます。

多くの場合、参照されるテーブル名と同じになります。この場合、それは提案の1つとまったく同じになります。

いずれにせよ、長い議論は悪い考えです


0

「 "employee INNER JOIN order ON order.employee_id = employee.id"のどこに追加の資格が必要ですか?」

私が話した資格はすでにそこにあるので、追加の資格は必要ありません。

「ビジネスユーザーが注文IDまたは従業員IDを参照する理由は、コンテキストを提供するためですが、データベースを参照しているため、データベースレベルではすでにコンテキストがあります。」

列が 'ID'という名前の場合、私が言ったようにID列へのこの参照を正確に修飾しない限り、「テーブルへの[sic]の参照」はどのように行われますか?

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