ID列に「Id」という名前を使用しないことを推奨するのはなぜですか?


68

IdテーブルのID列に名前を使用しないように教えられましたが、最近は、データが実際に何であるかについて簡単で、短く、非常に説明的であるため、とにかくそれを使用しています。

Idテーブル名の接頭辞を付けることを提案する人がいますが、これは特にSQLクエリを作成する人(またはEntity FrameworkのようなORMを使用している場合はプログラマー)、特にCustomerProductIdまたはAgencyGroupAssignementId

Ident使用を回避するために、実際にすべてのID列に名前を付けて何かを作成するために雇ったサードパーティベンダーId。最初Idはキーワードだったからだと思っていましたが、調べてみると、IdSQL Server 2005のキーワードではないことがわかりました。

それでは、なぜIdID列に名前を使用しないことを推奨するのでしょうか?

編集:明確にするために、どの命名規則を使用するか、またはある命名規則を他の命名規則よりも使用するための引数を求めていません。IdID列名に使用しないことが推奨される理由を知りたいだけです。

私はDBAではなく、単一のプログラマーです。データベースは、データを保存する場所にすぎません。私は通常小さなアプリを作成し、通常はデータアクセスにORMを使用するため、IDフィールドの共通フィールド名を使用する方がはるかに簡単です。これを行うことで何が欠けているのか、そしてこれを行わない本当に良い理由があるかどうかを知りたいです。


10
すでにここでBFの戦い:Programmers.stackexchange.com/q/114728/5905数人(読んでいる:私)がそれに
夢中

ID列の名前として「id」を使用することに対して実際にそのようなルールはありますか?Ruby on Railsの標準ORMであるActiveRecordは、慣例に従ってまさにそれを行います。 ar.rubyonrails.org
200_success

1
@ 200_successデータベースレベルでは、はい。これはデータベースサイトであり、ORMサイトではありません;)
JNK

2
また、特にSQL Serverについては、dba.stackexchange.com / questions / 124655 / を参照してください。具体的には、connect.microsoft.com / SQLServer / feedback / details / 2178150
アーロンバートランド

回答:


46

テーブル名のプレフィックスには非常に良い理由があります。

考慮してください:

TableA (id int identity, stringdata varchar(max))

TableB (id int identity, stringdata varchar(max))

我々はしたいDELETEからTableA両方のテーブルに存在するレコード。とても簡単ですINNER JOIN

DELETE a
FROM 
  TableA A
INNER JOIN 
  TableB B
    ON b.id = B.id

.... そして、我々はすべてを一掃しましたTableA BのIDを不注意で比較しました。すべてのレコードが一致し、すべてのレコードが削除されました。

フィールドに名前が付けられていてTableAIdTableBIdこれが不可能な場合(Invalid field name TableAid in TableB)。

個人的にはidテーブルで名前を使用しても問題はありませんが、間違ったフィールドと誤って比較して吹き飛ばすことを避けるために、テーブル名(またはTableA人々PeopleIdもうまくいく場合はエンティティ名)を前に付けることは本当に良い習慣です何かアップ。

また、これにより、多数のJOINsを含む長いクエリでフィールドがどこから来たのかが非常に明確になります。


10
それは基本的にエラーから保護するための命名規則ですか?私が使用して思うだろうbegin transactioncommit transaction(IMO)より不快な命名規則を使用するよりも、より良い練習になり
レイチェル

13
@Rachel:それは3.単一のオブジェクトではなく、セットで動作する4困らせるPHPのサルをJOIN..USING許可1.明快2.避け、不要な列の別名のためだ
GBN

4
@Rachelクエリの作成時に間違いに気づかず、実行する直前であれば、コミットする前に気付かないでしょう。このようなことが起こります、なぜそれをより可能にしますか?
アンディ

7
@AndyをSELECT実行する前に常にレコードを見つけるためにa DELETEを実行し、ステートメントを実行したら、コミットする前に行カウントが期待どおりであることを常に確認します。
レイチェル

5
@Rachelあなたに合ったものがあるとうれしいです。みんなにそうさせてもらえますか?
アンディ

36

主に、外部キーが大きな痛みにならないようにすることです。CustomerとCustomerAddressの2つのテーブルがあるとします。両方の主キーはid(id(int)列)という名前の列です。

ここで、CustomerAddressから顧客IDを参照する必要があります。明らかに列IDに名前を付けることはできないため、customer_idを使用します。

これはいくつかの問題につながります。まず、「id」列を呼び出すタイミングと、「customer_id」列を呼び出すタイミングを常に覚えておく必要があります。これを台無しにすると、2番目の問題につながります。12個程度の結合を持つ大きなクエリがあり、それがデータを返さない場合は、Where's Waldoを再生してこのタイプミスを探してみてください。

ON c.id = ca.id

おっと、そうだったはずON c.id = ca.customer_idです。または、さらに良いことに、ID列にわかりやすい名前を付けますON c.customer_id = ca.customer_id。間違ったテーブルエイリアスを誤って使用すると、customer_idはそのテーブルの列にならず、空の結果や後続のコードを細かく表示するのではなく、コンパイルエラーが発生します。

確かに、あるテーブルから別の単一のテーブルへの複数の外部キー関係が必要な場合など、これが役に立たない場合もありますが、すべての主キーに「id」という名前を付けても役に立たない場合があります。


27

以下は、すべての主キーに共通名を使用しないという規則から得られる利点に関するすべての回答の要約です。

  • 識別フィールドに同じ名前が付けられていないため、ミスが少ない

    IDフィールドにまったく同じ名前が付けられることはないため、のB.Id = B.Id代わりに結合するクエリを誤って記述することはできませんA.Id = B.Id

  • より明確な列名。

    という名前の列を見るCustomerIdと、その列にあるデータがすぐにわかります。列名がのような一般的なIdものである場合、列に含まれるデータを知るために、テーブル名も知る必要があります。

  • 不要な列エイリアスを回避します

    あなたは今書くことができますSELECT CustomerId, ProductId結合するクエリからCustomersProductsはなく、SELECT Customer.Id as CustomerId, Products.Id as ProductId

  • JOIN..USING構文を許可します

    Customer JOIN Products USING (CustomerId)代わりに、構文でテーブルを結合できますCustomer JOIN Products ON Customer.Id = Products.Id

  • キーは検索で見つけやすい

    大規模なソリューションで顧客のIDフィールドを探してCustomerIdいる場合、検索は検索よりもはるかに便利です。Id

この命名規則のその他の利点について考えられる場合は、お知らせください。リストに追加します。

IDフィールドに一意の列名を使用するか、同一の列名を使用するかはユーザー次第ですが、選択内容に関係なく、一貫性を保ってください:)


12

リンクされた質問から回答をコピーするには:

すべてのテーブルに「ID」を付けるのが最善のアイデアではない状況がありUSINGます。それがサポートされている場合、キーワードです。MySQLで頻繁に使用します。

たとえば、fooTablewith column fooTableIdおよびbarTableforeign key fooTableIdがある場合、クエリは次のように構築できます。

SELECT fooTableId, fooField1, barField2 FROM fooTable INNER JOIN barTable USING (fooTableId)

入力を節約するだけでなく、他の方法に比べてはるかに読みやすくなっています。

SELECT fooTable.Id, fooField1, barField2 FROM fooTable INNER JOIN barTable ON (fooTable.Id = barTable.foTableId)

9

データベーススキーマを正規化して冗長性を制限した後、テーブルは確立された関係(1対1、1対多、多対多)で小さなテーブルに分割されます。このプロセスでは、元のテーブルの単一のフィールドが複数の正規化されたテーブルに表示される場合があります。

たとえば、ブログのデータベースは、Author_Nicknameに一意の制約があると仮定すると、非正規化形式ではこのようになります。

| Author_Nickname | Author_Email | Post_Title | Post_Body |
+-----------------+--------------+------------+-----------+
| dave            | dave@x.com   | Blah       | Bla bla   |
| dave            | dave@x.com   | Stuff      | I like    |
| sophie          | s@oph.ie     | Lorem      | Ipsum     |

正規化すると、2つのテーブルが生成されます。

著者:

| Author_Nickname | Author_Email |
+-----------------+--------------+
| dave            | dave@x.com   |
| sophie          | s@oph.ie     |

役職

| Author_Nickname | Post_Title | Post_Body |
+-----------------+------------+-----------+
| dave            | Blah       | Bla bla   |
| dave            | Stuff      | I like    |
| sophie          | Lorem      | Ipsum     |

ここで、Author_Nicknameは作成者テーブルの主キーであり、投稿テーブルの外部キーです。Author_Nicknameが2つのテーブルに表示されている場合でも、単一の情報ユニットに対応しています。各列名は単一のフィールドに対応します

多くの場合、元のフィールドに一意の制約を設定することはできないため、代わりに数値の人工フィールドが主キーとして使用されます。これにより、各列名が単一のフィールドを表すという事実は変わりません。従来のデータベース設計では、個々の列名はキーではなくても単一のフィールドに対応しています。(たとえば、part.nameclient.nameではなく、part.partnameclient.clientnameを使用します)。これがINNER JOIN ... USING <key>NATURAL JOIN構文の存在の理由です。

ただし、今日では、多くの言語でORMレイヤーを簡単に使用できるため、データベースはOO言語の永続レイヤーとして設計されることが多く、異なるクラスで同じ役割を持つ変数が同じ(part.nameおよびclient.name、ないpart.partnameclient.clientname)。このようなコンテキストでは、主キーに「ID」を使用する傾向があります。


7

Idの使用を避けるために、実際にすべてのID列にIdentという名前を付けたものを作成するために雇ったサードパーティベンダー。

「Id」の代わりに「Ident」を使用しても、すべてのテーブルで「Ident」が使用された場合、実際には何も解決されません。

Drupalのサイトには、この状況の適切なプラクティスを示すSQLコーディング規約に関する優れた記事があります

名前空間の競合を防ぐために、テーブル名の前にモジュール名を付けることをお勧めします。

この観点から、CustomerProductIdとAgencyGroupAssignmentIdは使用する意味があります。はい、非常に冗長です。あなたはそれを短くすることもできますが、それに関して懸念する最大のポイントは、あなたをフォローしている開発者があなたの意図を理解するかどうかです。冗長なテーブル名で始まるIDは、それらが何であるかについてあいまいさを残すべきではありません。そして(私にとって)それは、いくつかのキーストロークを保存するよりも重要です。


7

IDではなくCustomerIDの列に名前を付けるので、入力するたびに

FROM dbo.Customers AS c JOIN dbo.CustomerOrders AS o

SQLプロンプトはすぐに次を提案します

ON c.CustomerID = o.CustomerID 

それは私にいくつかのキーストロークを節約します。しかし、命名規則は非常に主観的であるため、何らかの方法で強い意見はないと思います。


5

すべてのvarcharフィールドに「UserText」や「UserText1」などの名前を付けない、または「UserDate」や「​​UserDate1」を使用しないのと同じ理由です。

通常、テーブルにIDフィールドがある場合、それは主キーです。両方のテーブルの主キーがidだった場合、親テーブルへの外部キーを持つ子テーブルをどのように構築しますか?

誰もがこの方法論に同意するわけではありませんが、私のデータベースでは、各テーブルに一意の略語を割り当てています。そのテーブルのPKは、PK_ [abbrv] IDという名前になります。それがどこでもFKとして使用される場合、FK_ [abbrv] IDを使用します。今、私はテーブルの関係が何であるかを理解する上でゼロの推測作業をしています。


5

基本的に同じ理由で、通常はパラメーターparameter1、parameter2 ...に名前を付けません。正確ですが、説明的ではありません。TableIdが表示されている場合は、コンテキストに関係なく、Tableのpkを保持するために使用されているとおそらく安全に想定できます。

Identを使用した人に関しては、IdentとId use Idのどちらかを選択すると、彼はその点を見逃します。IdentはIdよりもさらに混乱を招きます。

コンテキスト外では、Idは何らかのテーブルの主キーと見なすことができます(idがguidでない限り、非常に便利ではありません)が、Identはそれを(または少なくとも私には)教えさえしません。私は最終的に、Identがアイデンティティ(いずれにせよ)に不足していることを理解しますが、それを理解するのに費やした時間は無駄になります。


3

natural join/ を実行できるように、主キーと外部キーの両方のコンテキストで同じ名前を使用できるように、プレフィックスを使用しますjoin ... using

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