質問
データベース テーブルの ID 列の命名についての人々の意見が気になりました。
ID 列の主キーを持つ Invoices というテーブルがある場合、他のテーブルと競合せず、それが何であるかが明らかになるように、その列を InvoiceID と呼びます。
私が現在働いているところでは、すべての ID 列が ID と呼ばれています。
そこで彼らは次のことを行うでしょう。
Select
i.ID
, il.ID
From
Invoices i
Left Join InvoiceLines il
on i.ID = il.InvoiceID
さて、ここでいくつかの問題がわかります。
1.選択時に列にエイリアスを付ける必要があります
2.ID = InvoiceID が頭に収まりません
3.テーブルに別名を付けずに InvoiceID を参照した場合、それがどのテーブルにあるのかは明らかですか?
このトピックについて他の人はどう思いますか?
解決
IDはSQLアンチパターンです。 http://をご覧ください。 www.amazon.com/s/ref=nb_sb_ss_i_1_5?url=search-alias%3Dstripbooks&field-keywords=sql+antipatterns&sprefix=sql+a
IDがIDであるテーブルが多数ある場合、レポートはさらに難しくなります。意味があいまいになり、複雑なクエリが読みにくくなり、レポート自体を区別するためにエイリアスを使用する必要があります。
さらに、誰かが利用可能なデータベースで自然結合を使用するほど愚かな場合、間違ったレコードに結合します。
一部のデータベースで許可されているUSING構文を使用する場合、IDを使用することはできません。
IDを使用すると、結合構文をコピーした場合に誤った結合に陥る可能性があり(誰もこれを実行しないと言わないでください!)、結合条件のエイリアスを変更し忘れることがあります。
だからあなたは今
select t1.field1, t2.field2, t3.field3
from table1 t1
join table2 t2 on t1.id = t2.table1id
join table3 t3 on t1.id = t3.table2id
意図したとき
select t1.field1, t2.field2, t3.field3
from table1 t1
join table2 t2 on t1.id = t2.table1id
join table3 t3 on t2.id = t3.table2id
idフィールドとしてtablenameIDを使用すると、この種の偶発的な間違いは発生する可能性がはるかに低くなり、見つけやすくなります。
他のヒント
TableName + idカラムのID、そしてTableName +外部キーのIDよりも常にIDを好みました。この方法では、すべてのテーブルのidフィールドに同じ名前が付けられ、冗長な説明はありません。すべてのテーブルが同じプライマリキーフィールド名を持っているので、これは私には簡単に思えます。
テーブルを結合し、どのIdフィールドがどのテーブルに属するかわからない限り、私の意見では、この状況を処理するためにクエリを記述する必要があります。私が働いている場所では、テーブル/テーブルのエイリアスを使用してステートメントで使用するフィールドを常に優先しています。
最近、私の会社でこのことについてオタクの戦いがありました。 LINQの出現により、冗長な tablename + ID パターンが私の目にはさらに明らかに愚かになりました。最も合理的な人々は、 FK を区別するためにテーブル名を指定する必要があるような方法でSQLを手書きする場合、タイピングの節約になるだけでなく、どのIDが PK と FK であるかを明確に確認できるという点で、IDのみを使用するようにSQLを明確にします。
E.g。
従業員eから LEFT JOIN顧客c ON e.ID = c.EmployeeID
2つがリンクされていることだけでなく、どちらが PK であり、どちらが FK 。一方、古いスタイルでは、見た目または名前が適切であることを期待する必要があります。
ID
ではなく、 InvoiceID
を使用します。クエリを読みやすくします- ID
だけが表示されている場合、特にテーブルを i
にエイリアスしている場合は、何でも意味があります。
表のPKは単純にIdであり、外部キーはOtherTable + Idをリストする必要があるという点で、Kevenと他の数人の人々に同意します。
ただし、最近、この主張に重みを付けた理由を1つ追加します。
現在の立場では、POCO生成を使用したエンティティフレームワークを採用しています。 Idの標準の命名規則を使用すると、PKは、一連の共通列名を共有するテーブルの検証などで基本pocoクラスを継承できます。これらの各テーブルのPKとしてTablename + Idを使用すると、これらのベースクラスを使用する機能が破壊されます。
考えてみてください。
それほど重要ではありません。すべての命名規則で同様の問題が発生する可能性があります。
ただし、クエリを作成するたびにテーブル定義を確認する必要がないように、一貫性を保つことが重要です。
私の好みは、主キーのIDおよび外部キーのTableNameIDです。また、列「名前」も持っています。エントリのユーザーが読み取り可能な識別子(つまり、名前:-))を保持するほとんどのテーブルで。この構造はアプリケーション自体に大きな柔軟性を提供し、同じ方法でテーブルをまとめて処理できます。これは非常に強力なことです。通常、OOソフトウェアはデータベースの上に構築されますが、db自体で許可されていないため、OOツールセットは適用できません。列のIDと名前を保持することはまだあまり良くありませんが、それは一歩です。
選択
i.ID、il.IDから 請求書i InvoiceLines ilの左結合 on i.ID = il.InvoiceID
なぜこれができないのですか?
Select
Invoices.ID
, InvoiceLines.ID
From
Invoices
Left Join InvoiceLines
on Invoices.ID = InvoiceLines.InvoiceID
私の意見では、これは非常に読みやすく簡単です。変数をiおよびilとして命名することは、一般的に適切な選択ではありません。
「ID」のみを使用する場所で作業を始めました。 (外部キーのTableNameIDによって参照されるコアテーブル)、およびそれによって直接引き起こされる2つの運用上の問題を既に発見しています。
クエリでは、" ... where ID in(SELECT ID FROM OtherTable ..."ではなく" ... where ID in(SELECT TransID FROM OtherTable ...&quot ;.) p>
間違ったステートメントが" ... where TransID in(SELECT OtherTableID from OtherTable ..."そうは思いません。
他の問題は、コードのリファクタリング時に発生します。以前はクエリがコアテーブルから外れていたのに対して一時テーブルを使用する場合、古いコードは" ... dbo.MyFunction(t.ID)..."を読み取ります。そして、それが変更されていないが、「t」がコアテーブルではなく一時テーブルを参照するようになりました。エラーは発生しません。結果が間違っています。
不必要なエラーを生成することが目標である場合(十分な作業を行わない人もいるかもしれません)、この種の命名規則は素晴らしいです。それ以外の場合は、一貫した命名が進むべき方法です。
簡単にするために、ほとんどの人はテーブルIDの列に名前を付けます。別のテーブルに外部キー参照がある場合、結合の場合に(例を使用するために)明示的にInvoiceIDと呼びます。とにかくテーブルをエイリアスしているため、明示的なinv.IDはinv.InvoiceIDよりも単純です
正式なデータディクショナリの観点からこれを考えると、データ要素に invoice_ID
という名前を付けます。一般に、データ要素名はデータディクショナリ内で一意であり、理想的には全体にわたって同じ名前を持ちますが、コンテキストに基づいて追加の修飾用語が必要になる場合があります。 employee_ID
という名前のデータ要素は組織図で2回使用でき、それぞれ supervisor_employee_ID
および subordinate_employee_ID
として修飾できます。
明らかに、命名規則は主観的であり、スタイルの問題です。 ISO / IEC 11179のガイドラインが有用な出発点であることがわかりました。
DBMSの場合、テーブルはエンティティのコレクションとして表示されます(cofigテーブル、定数のテーブルなど、1行のみを含むものを除く)。 employee_ID
がキーであるテーブルの名前は Personnel
です。したがって、すぐに TableNameID
の規則は機能しません。
大規模なデータモデルで使用される TableName.ID = PK TableNameID = FK
スタイルを見てきましたが、やや紛らわしいと言わざるを得ません。出現するテーブルに基づいて名前を変更することはありません。注目すべき点は、 everyに IDENTITY
(auto-increment)列を追加するショップで前述のスタイルが使用されているように思われることです。 テーブル。外部キーの自然キーと複合キーを排除します。これらのショップには、正式なデータ辞書がなく、データモデルから構築されない傾向があります。繰り返しますが、これは単にスタイルの問題であり、私が個人的に購読するものではありません。だから最終的に、それは私のためではありません。
とはいえ、テーブルの名前がそうするためのコンテキストを提供するとき、列名から修飾子を時々ドロップする場合があります。 employee_last_name
という名前の要素は、 Personnel
テーブルの last_name
になります。ここでの理論的根拠は、ドメインが「人々の姓」であり、 last_name
の列と UNION
されている可能性が高いことです。別のテーブルの 外部キーとして使用されますが、もう一度...私はただ考えを変えるかもしれません、時にはあなたは決して知ることができません。それが問題です。データモデリングは芸術であり、科学です。
私は個人的に(上記のとおり) PK および TableID Table.ID を好みます> FK の場合。でも(私を撃たないでください)Microsoft Accessはこれを推奨します。
ただし、一部の生成ツールは、 INCLUDING ID!という単語に 'ID' を含むすべての列名をリンクする傾向があるため、PKのTableIDを好むという事実も知っています! !!
クエリデザイナーでもMicrosoft SQL Serverでこれを行います(作成するクエリごとに、列IDのすべてのテーブルで新しく作成された不要な関係をすべて取り除いてしまいます)
THUS内部のOCDが嫌いなのと同じように、私は TableID の慣習に従います。 Data BASE と呼ばれることを覚えておいてください。これは、多くの多くのアプリケーションのベースになることを願っています。そして、すべてのテクノロジーは、明確な記述スキーマで十分に正規化されていることの恩恵を受けるはずです。
言うまでもなく、人々がTableNameやTableDescriptionなどを使い始めたときに線を引きます。私の意見では、コンベンションは次のことを行うべきです:
- テーブル名:複数形。例従業員
-
テーブルエイリアス:完全なテーブル名、単数形。例:
SELECT Employee.*, eMail.Address FROM Employees AS Employee LEFT JOIN eMails as eMail on Employee.eMailID = eMail.eMailID -- I would sure like it to just have the eMail.ID here.... but oh well
[更新]
また、このスレッドには、「関係の種類」による重複した列に関するいくつかの有効な投稿があります。または役割。たとえば、ストアに EmployeeID がある場合、スクワットがわかります。だから私は時々 Store.EmployeeID_Manager のようなことをします。確かにそれは少し大きくなりますが、少なくとも、 table ManagerID や EmployeeID が何をしているのかを見つけようとする人は夢中になりません。クエリがWHEREの場合、次のように単純化します。 EmployeeID_ManagerをManagerID FROM Storeとして選択します
「ID」は一貫していれば何でも良いと思います。テーブル名を含めることが重要です。Erwin などのモデリング ツールを使用して命名規則と標準を強制し、クエリを作成するときにテーブル間に存在する可能性のある関係を簡単に理解できるようにすることをお勧めします。
最初のステートメントが言いたいのは、ID の代わりに「recno」などの別のものを使用できるということです。したがって、このテーブルには invoice_recno などの PK が含まれることになります。
乾杯、ベン
私の投票は、テーブルIDのInvoiceIDに対するものです。外部キーとして使用する場合も同じ命名規則を使用し、クエリでインテリジェントなエイリアス名を使用します。
Select Invoice.InvoiceID, Lines.InvoiceLine, Customer.OrgName
From Invoices Invoice
Join InvoiceLines Lines on Lines.InvoiceID = Invoice.InvoiceID
Join Customers Customer on Customer.CustomerID = Invoice.CustomerID
もちろん、他のいくつかの例よりも長いです。しかし、笑顔。これは後世のためであり、いつか、貧しいジュニアコーダーがあなたの傑作を変えなければならないでしょう。この例ではあいまいさはなく、追加のテーブルがクエリに追加されるので、冗長性に感謝します。
データベースの列名には、「InvoiceID」を使用します。
LINQを使用してフィールドを名前のない構造体にコピーすると、「ID」という名前を付けることができます。構造内の唯一のIDである場合。
列が外部キーで使用されないため、編集編集または削除のために行を一意に識別するためにのみ使用される場合は、「PK」という名前を付けます。
各キーに一意の名前を付けると、たとえば" invoices.invoice_id" " invoices.id"の代わりに、" natural join"を使用できます。および「使用」心配のないオペレーター。例:
SELECT * FROM invoices NATURAL JOIN invoice_lines
SELECT * FROM invoices JOIN invoice_lines USING (invoice_id)
の代わりに
SELECT * from invoices JOIN invoice_lines
ON invoices.id = invoice_lines.invoice_id
SQLはより冗長にすることなく十分に冗長です。
自分で物事の一貫性を保つために(テーブルにIDとして使用される単一列のプライマリキーがある場合)、テーブルのプライマリキーに Table_pk
という名前を付けます。そのテーブルの主キーを指す外部キーがある場所では、 PrimaryKeyTable_fk
列を呼び出します。そうすれば、Customerテーブルに Customer_pk
があり、Orderテーブルに Customer_fk
がある場合、OrderテーブルがCustomerのエントリを参照していることがわかります。テーブル。
これは、読みやすいと思う結合の場合に特に意味があります。
SELECT *
FROM Customer AS c
INNER JOIN Order AS c ON c.Customer_pk = o.Customer_fk
FWIW、新しい標準(新しいプロジェクトごとに「進化する」という意味に変わります):
- 小文字のデータベースフィールド名
- 大文字のテーブル名
- アンダースコアを使用してフィールド名の単語を区切ります-コードでこれらをPascalの大文字に変換します。
-
pk _
プレフィックスは主キーを意味します -
_id
接尾辞は、整数の自動インクリメントIDを意味します -
fk _
プレフィックスは外部キーを意味します(サフィックスは不要です)
ビューの -
_VW
サフィックス
ブール値の -
is _
プレフィックス
したがって、NAMESという名前のテーブルには、フィールド pk_name_id、first_name、last_name、is_alive、
および fk_company
と、 LIVING_CUSTOMERS_VW
というビューがあります。次のように定義されます:
SELECT first_name, last_name FROM CONTACT.NAMES WHERE (is_alive = 'True')
しかし、他の人が言ったように、一貫性があり、あなたの意味を不必要に難読化しない限り、ほぼすべてのスキームが機能します。
あなたが指定した理由から、IDフィールド名にテーブル名を含めることに間違いなく同意します。通常、これはテーブル名を含める唯一のフィールドです。
プレーンID名は嫌いです。常にinvoice_idまたはそのバリアントを使用することを強くお勧めします。必要なときにどのテーブルがIDの信頼できるテーブルであるかを常に知っていますが、これは私を混乱させます
SELECT * from Invoice inv, InvoiceLine inv_l where
inv_l.InvoiceID = inv.ID
SELECT * from Invoice inv, InvoiceLine inv_l where
inv_l.ID = inv.InvoiceLineID
SELECT * from Invoice inv, InvoiceLine inv_l where
inv_l.ID = inv.InvoiceID
SELECT * from Invoice inv, InvoiceLine inv_l where
inv_l.InvoiceLineID = inv.ID
何よりも最悪なのは、あなたが言及したミックスであり、完全に混乱させます。最もよく使用されるIDの1つを除き、ほぼ常にfoo_idであるデータベースを使用する必要がありました。それはまったく地獄だった。
DomainNameが好きです|| 「ID」。 (つまり、DomainName + ID)
DomainNameは、常にではありませんが、多くの場合TableNameと同じです。
ID自体の問題は、それ自体がスケールアップしないことです。それぞれがIDという名前の最初の列を持つ約200のテーブルを作成すると、データはすべて同じように見え始めます。常にテーブル名でIDを修飾する場合、それは少し役立ちますが、それほどではありません。
ドメイン名& IDを使用して、外部キーとプライマリキーの名前を付けることができます。 foriegnキーが参照する列にちなんで名前が付けられている場合、ニーモニックの助けになることがあります。正式には、参照整合性制約によって参照が確立されるため、外部キーの名前を参照するキーに関連付ける必要はありません。しかし、クエリや更新の読み取りに関しては非常に便利です。
時々、DomainName || 「ID」は使用できません。同じテーブルに同じ名前の2つの列があるためです。例:Employees.EmployeeIDおよびEmployees.SupervisorID。これらの場合、RoleNameを使用します||例のように「ID」。
最後になりましたが、可能であれば、合成キーではなく自然キーを使用します。自然キーが利用できない、または信頼できない状況もありますが、自然キーが正しい選択である状況はたくさんあります。そのような場合、自然なキーに自然な名前を付けます。多くの場合、この名前には「ID」という文字さえありません。例:OrderNo(Noは" Number"の略)。
各テーブルに対して、ツリー文字の短縮形を選択します(例:Employees => Emp)
このようにして、数値の自動番号主キーが nkEmp になります。
これは短く、データベース全体で一意であり、そのプロパティが一目で正確にわかります。
SQLと使用するすべての言語(主にC#、Javascript、VB6)で同じ名前を使用しています。
Interaktサイトの命名規則よく考えられたテーブルと列の命名システム。このメソッドは、各テーブルのサフィックス(製品テーブルの場合は _prd
、カテゴリテーブルの場合は _ctg
)を使用し、特定のテーブルの各列に追加します。したがって、productsテーブルのID列は id_prd
になり、データベース内で一意になります。
外部キーの理解を支援するためにさらに一歩進みます:カテゴリテーブルを参照する製品テーブルの外部キーは idctg_prd
であるため、どのテーブルに属しているかが明らかです( _prd
サフィックス)およびそれが参照するテーブル(カテゴリ)。
利点は、異なるテーブルのID列にあいまいさがないこと、およびクエリが列名で参照している列を一目で確認できることです。
次の命名規則を使用できます。欠点はありますが、特定の問題を解決します。
- 表名には短い(3-4文字)ニックネームを使用します。つまり、Invoice-
inv
、InvoiceLines-invl
- これらのニックネームを使用してテーブルの列に名前を付けます。つまり、
inv_id
、invl_id
- 参照列では、名前に
invl_inv_id
を使用します。
このように言うことができます
SELECT * FROM Invoice LEFT JOIN InvoiceLines ON inv_id = invl_inv_id