web-dev-qa-db-ja.com

テーブルの主キー列に「Id」という名前を付けることが悪い習慣と見なされるのはなぜですか?

私のt-sqlの先生は、私たちのPK列に "Id"という名前を付けることは、それ以上の説明なしに悪い習慣であると考えられると私たちに言いました。

テーブルのPK列に「Id」という名前を付けることが悪い習慣と見なされるのはなぜですか?

215

私は出てきてそれを言うつもりです:それは本当に悪い習慣ではありません(そしてそれがたとえそうであったとしても、それはそれではない悪い)。

次のクエリのようにエラーをマスクできる引数( Chad が指摘されている)を作成できます。

SELECT * 
    FROM cars car
    JOIN manufacturer mfg
        ON mfg.Id = car.ManufacturerId
    JOIN models mod
        ON mod.Id = car.ModelId
    JOIN colors col
        ON mfg.Id = car.ColorId

しかし、これはテーブル名に小さなエイリアスを使用しないことで簡単に軽減できます。

SELECT * 
    FROM cars
    JOIN manufacturer
        ON manufacturer.Id = cars.ManufacturerId
    JOIN models
        ON models.Id = cars.ModelId
    JOIN colors
        ON manufacturer.Id = cars.ColorId

常に3文字の略語を使用する習慣は、列名idを使用するよりもずっと悪いようです。 (適切な例:実際​​にテーブル名carscarに短縮するのは誰ですか?何が目的ですか?)

重要なのは、一貫していることです。会社でIdを使用していて、一般的に上記のエラーが発生する場合は、完全なテーブル名を使用する習慣をつけてください。会社がId列を禁止している場合は、それを一歩踏み込んで、好きな命名規則を使用してください。

このような問題を検討するのではなく、実際に悪い習慣(複数のネストされた相関サブクエリなど)を学ぶことに集中してください。列に「ID」という名前を付けることの問題は、悪い習慣よりも好みの問題に近いものです。


編集者への注記:このクエリのエラーは意図的であり、ポイントを作成するために使用されています。編集する前に回答全体をお読みください。

250
riwalk

外部キーを持つテーブルがある場合、その外部キーに「Id」という名前を付けることはできないためです。 TableIdというテーブル名があります

そして、あなたの結合は次のようになります

SELECT * FROM cars c JOIN manufacturer m ON m.Id = c.ManufacturerId

そして理想的には、条件は両側で同じフィールド名を持つ必要があります

SELECT * FROM cars c JOIN manufacturer m ON m.ManufacturerId = c.ManufacturerId

したがって、IdをManufacturerIdと名付けるのは冗長に見えますが、間違いが明らかになると、結合条件にエラーが発生する可能性が低くなります。

これは簡単に見えますが、いくつかのテーブルを結合すると、間違いを犯す可能性が高くなります。以下のテーブルを見つけてください...

SELECT * 
    FROM cars car 
    JOIN manufacturer mfg
        ON mfg.Id = car.ManufacturerId
    JOIN models mod
        ON mod.Id = car.ModelId
    JOIN colors col
        ON mfg.Id = car.ColorId

一方、適切な名前を付けると、エラーが発生します...

SELECT * 
    FROM cars car 
    JOIN manufacturer mfg
        ON mfg.ManufacturerId = car.ManufacturerId
    JOIN models mod
        ON mod.ModelId = car.ModelId
    JOIN colors col
        ON mfg.ManufacturerId = car.ColorId

Idに名前を付けるもう1つの理由は、複数のテーブルから情報を照会するときに、Id列の名前を変更して区別できるようにする必要があるためです。

SELECT   manufacturer.Id as 'ManufacturerId'
        ,cars.Id as 'CarId'
        --etc
    FROM cars 
    JOIN manufacturer
        ON manufacturer.Id = cars.Id

名前が正確であれば、これはそれほど問題ではありません

125
CaffGeek

RubyのActiveRecordライブラリとGroovyのGORMは、デフォルトで代理キーに「id」を使用します。私はこの練習が好きです。各列名にテーブル名を複製することは冗長であり、書き込みが面倒で、読み取りが面倒です。

68
kevin cline

「名前」や「Id」などの共通またはキー列名の前には、TableNameを付ける必要があります。

あいまいさをなくし、検索が容易になり、両方の「Id」値が必要な場合に列のエイリアスがはるかに少なくなります。

使用頻度が低いか、監査列または非キー(LastUpdatedDateTimeなど)は関係ありません

40
gbn

このスレッドは無効ですが、Idを使用するIMOではなくを追加することは悪い習慣です。 Id列は特別です。 the主キーです。どのテーブルにも任意の数の外部キーを含めることができますが、プライマリキーとなることができるキーは1つだけです。すべての主キーがIdと呼ばれるデータベースでは、テーブルを見るとすぐに、どの列が主キーであるかが正確にわかります。

私を信じてください。今月、私は毎日たくさんの大きなデータベース(Salesforce)で作業していて、スキーマについて言えることはすべてのテーブルにIdという主キーがあるということです。 PKはIdと呼ばれているため、主キーを外部キーに結合することについて混乱することは絶対にありません。人々が言及していないもう1つのことは、テーブルがTable_ThatDoesGood_stuff__cのようなばかげた長い名前を持つ可能性があることです。アーキテクトがそのテーブルを考えた朝に二日酔いがあったので、その名前は十分に悪いですが、主キーTable_ThatDoesGood_stuff__cIdを呼び出さないのは悪い習慣だと教えています(SQL列名が含まれていないことを思い出してください)一般的な大文字と小文字が区別されます)。

正直なところ、コンピュータプログラミングを教えるほとんどの人の問題は、彼らが何年もプロダクションコードのラインを書いておらず、実際に働いているソフトウェアエンジニアが実際に何をしているのかわからないことです。仕事を始めるまで待ってから、自分が良いアイデアだと思うかどうかを決めてください。

32
user23157

から data.stackexchange.com

Id in Posts

ブーム、質問は答えました。
さて、先生に言ってくださいSO悪いデータベース設計を実践してください。

25
Cyril Gandon

私はそれを悪い習慣とは考えていません。いつものように、一貫性は王様です。

私はそれはすべて文脈についてだと思います。テーブル自体のコンテキストでは、「id」はまさに期待するものを意味します。それ以外の場合は同一(または表示)である可能性のある他のものに対して一意に識別するのに役立つラベルです。

結合のコンテキストでは、自分とチームが読みやすいように結合を作成するのはユーザーの責任です。言い回しやネーミングが悪いと物事を難しく見せるのと同じように、エイリアスやコメントを効果的に使用して、意味のあるクエリを作成することも同様に可能です。

同様に、Java「Foo」と呼ばれるクラスには、「Foo」という接頭辞のプロパティがありません。テーブルIDにテーブル名の接頭辞を付ける必要はありません。通常は、 コンテキスト内参照されているIDは何ですか。

24
lotsoffreetime

テーブルで自然な結合を実行するのは難しく(そして混乱します)、そのため、ええ、それは非常に悪いことではありません。

Natural Joinは、SQL Lore(つまり、リレーショナル代数)の古代のアーティファクトであり、次のいずれかを見たことがあるかもしれません。つまり、Natrual Joinは、DBMSがそれを実装するのに永遠にかかるように思われたとしても、新しい手間のかかるSQLアイデアではありません。今日ではその存在。

まあ、すべての主キーのIDに名前を付けると、自然な結合の容易さと単純さが失われます。 select * from dudes natural join cars書く必要がありますselect * from dudes inner join cars where cars.dudeid = dudes.idまたはselect * from dudes inner join cars where dudes.carid = cars.id。自然な結合を行うことができれば、関係が実際に何であるかを無視することができます。これはかなり素晴らしいと思います。

17
Peter Turner

すべてのテーブルに「ID」を付けるのが最善の方法ではない場合があります。サポートされている場合は、USINGキーワードです。 MySQLでよく使用されます。

たとえば、fooTableに列fooTableIdがあり、barTableに外部キー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)
16
Izkata

先生に聞いてみませんか?

これについて考えてください。すべてのテーブルのPK列にIDという名前が付いていると、それらを外部キーとして使用することが悪夢になります。

列名は意味的に重要である必要があります。 IDは総称です。

11
user7519

IDは次の理由で不良です:

多くのレポートクエリを実行する場合、両方を表示するには、常に列にエイリアスを設定する必要があります。したがって、最初に適切に名前を付けることができると、時間の無駄になります。これらの複雑なクエリは、不必要な作業を行うという追加の負担がなければ、非常に困難です(何百行ものクエリを作成します)。

コードエラーが発生する可能性があります。自然結合の使用を許可するデータベースを使用する場合(これを使用する必要があるとは思わないが、機能が利用可能な場合は誰かがそれらを使用する)、それを使用する開発者を取得すると、間違ったものに参加することになります。

結合をコピーして複雑なクエリを作成する場合、エイリアスを必要なものに変更することを忘れがちで、不正な結合が発生します。各IDがそれが含まれているテーブルに基づいて名前が付けられている場合、通常は構文エラーが発生します。また、pPK名とFK名が一致する場合は、複雑なクエリでの結合が正しくない場合も簡単に見つけることができます。

7
HLGEM

Idを主キーフィールドとして使用する方法は、IDがすべてのテーブルに追加される方法につながります。多くのテーブルには、レコードを一意に識別する一意の情報が既に含まれています。すべてのテーブルに追加するidフィールドではなく、THATを主キーとして使用します。これは、リレーショナルデータベースの基盤の1つです。

そして、それがidの使用が悪い習慣である理由です:idはしばしば単なる自動増加の情報ではありません。

次の表を検討してください。

PK id | Countryid   | Countryname
    1 |         840 | United States
    2 |         528 | the Netherlands

このテーブルの何が問題なのは、ユーザーが別の行を追加できることです:国コード840の米国。これは、リレーショナル整合性を壊しました。もちろん、個々の列に一意性を適用することも、すでに利用可能な主キーを使用することもできます。

PK Countryid   | Countryname
           840 | United States
           528 | the Netherlands

こうすることで、すでに持っている情報を主キーとして使用できます。これは、リレーショナルデータベース設計の中心です。

5
Pieter B

テーブルの主キーの列名として "id"を使用しないことの最も重要な理由、つまり一貫性とあいまいさの低減について、いくつかの回答があります。

しかし、私にとって重要な利点は、メンテナンスプログラマ、特に元の開発に関与していなかったプログラマによって実現されました。 PersonテーブルのIDに「PersonID」という名前を使用し、その名前を一貫して外部キーとして使用した場合、スキーマに対してクエリを記述して、「PersonID」を推測する必要なしに、PersonIDがあるテーブルを見つけることは簡単です。外部キーの場合に使用される名前です。正しいか間違っているかにかかわらず、すべてのプロジェクトで外部キーの関係が常に適用されるわけではありません。

1つのテーブルが同じテーブルへの2つの外部キーを必要とするEdgeケースがありますが、そのような場合は、元のキー名を列のサフィックス名として置くため、ワイルドカード一致%PersonIDで簡単に見つけることができますそれらのインスタンスも同様です。

はい、これの多くは、「id」を持ち、それを常に「tableNameID」として使用することを知っているという標準によって達成できますが、そのためには、プラクティスが実施されていることを知っていることと、元の開発者に依存してless直感的な標準的な練習。

長い列名を書き出すには追加のキーストロークが必要だと指摘する人もいますが、コードの記述はプログラムのアクティブライフのごく一部にすぎないと私は推測します。開発者のキーストロークを保存することが目的の場合は、コメントを記述しないでください。

何百ものテーブルを持つ大規模なプロジェクトを何年も維持してきた人として、テーブル全体でキーの名前に一貫性を持たせることを強くお勧めします。

5
Malachi

私は常に使用するフレームワーク(Ruby on Rails、CakePHP)の規則であるため、すべてのテーブルのプライマリ列名として「id」を常に使用しているため、常にオーバーライドする必要はありません。

それは私にとって学問的な理由に勝るものではありません。

4
Sfynx

IDは十分に一般的で、誰も混乱させることはないと思います。あなたはいつもテーブルを知りたいと思うでしょう。テーブル/エイリアスを含めずにフィールド名を製品コードに入れることは悪い習慣です。アドホッククエリをすばやく入力できるかどうかについて過度に心配している場合は、自分で判断してください。

IDが予約語であるSQLデータベースを開発する人がいないことを願っています。

CREATE TABLE CAR (ID);

フィールド名、主キー、および1から始まる自動インクリメントをすべて1つのニースの小さな2文字パッケージで処理します。ああ、私はそれをCARSと呼んでいたでしょうが、キーストロークを節約するつもりで、CARというテーブルには1つしかないと思う人がいるとしたらどうでしょう。

2
JeffO

この質問は何度も打たれましたが、私も私の意見を付け加えたいと思いました。

  1. Idを使用して、それが各テーブルの識別子であることを意味します。そのため、テーブルに結合して主キーが必要になると、自動的に主キーに結合します。

  2. Idフィールドは、署名なしの自動インクリメントです(つまり、値を設定する必要がなく、負にすることはできません)。

  3. 外部キーの場合、tablenameidを使用します(これもスタイルの問題です)。ただし、結合する主キーはテーブルのidフィールドであるため、一貫性があるため、常に簡単にクエリをチェックできます

  4. iDも短くて甘い

  5. 追加の規則-すべてのテーブル名と列名に小文字を使用するので、大文字小文字による問題は見つかりません

私はここの人々がほぼすべての側面をカバーしていることを見つけましたが、「ID」は「識別子」としてではなく、「識別子」として読むべきではないことを追加したいと思います。 (ここでは間違った表現を使用している可能性があります。もし間違っていた場合は修正してください)

それは、多かれ少なかれ、人々がテーブルデータを読み取る方法と、コードを記述する方法です。私個人としては、これが最も頻繁に見られる最も一般的な方法であり、プログラマーが完全なリファレンスをtable.id、ユニオンまたは結合を行う必要がない場合でも。例えば:

SELECT cars.color, cars.model FROM cars WHERE cars.id = <some_var>

そうすれば、「番号が付けられた車の色とモデルを教えて」と英語に翻訳できます。 「番号で識別されるその車の色とモデルを教えて」ではありません。 IDは自動車を表すものではなく、自動車のインデックス、シリアル番号のみです。配列から3番目の要素を取得する場合と同様です。

つまり、私が追加したかったことを要約すると、それは好みの問題であり、SQLの記述された読み取り方法が最も人気があるということです。

ただし、IDが実際に説明する文字列である場合(はるかにまれな例)など、これが使用されない場合もあります。例えば ​​id = "RedFordMustang1970"または同様のもの。少なくともこのアイデアを理解するために、これについて説明できたらと思います。

1

考慮すべきもう1つの点は、主キー名が外部キー名と異なる場合、特定のサードパーティツールを使用できないことです。

たとえば、スキーマをVisioなどのツールにロードして、正確なERDを生成させることはできません。

1
1earldog