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


210

私のt-sqlの先生は、PKカラムに「Id」という名前を付けることは、それ以上の説明なしに悪い習慣と見なされると教えてくれました。

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


27
まあ、それは実際の説明ではなく、Idは非常に自明な「アイデンティティ」を意味します。それが私の意見です。
ジャンフィリップルクレール

49
IdをPK名として使用しているお店はたくさんあると思います。私は個人的にTableIdを命名規則として使用していますが、その唯一の真の方法を誰にも伝えません。先生は自分の意見を広く受け入れられているベストプラクティスとして提示しようとしているようです。

22
間違いなく、それほど悪くないタイプの悪い習慣です。ポイントは一貫性を保つことです。idを使用する場合は、どこでも使用するか、使用しないでください。
deadalnix

57
テーブルがあります... Peopleと呼ばれ、Idと呼ばれる列があります。Idはどう思いますか?車?ボート?...いいえ、それはPeople Idです、それだけです。それは悪い習慣ではないとは思いませんし、PK列にId以外の名前を付ける必要はありません。
ジム

38
それで、先生はクラスの前に来て、これが単一の理由なしで悪い習慣であるとあなたに言うか?それは教師にとって悪い習慣です。
-JeffO

回答:


247

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

チャドが指摘したように)次のクエリのようにエラーをマスクできるという引数を作成できます。

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。(適切な場合:誰が実際にテーブル名carsを略語で省略しcarますか?それはどのような目的を果たしますか?)

ポイントは、一貫性を保つことです。会社でIdを使用していて、上記のエラーをよくする場合は、完全なテーブル名を使用する習慣を身に付けてください。会社がId列を禁止している場合は、それを一気に取り、好きな命名規則を使用してください。

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


編集者への注意:このクエリのエラーは意図的なものであり、指摘するために使用されています。編集する前に完全な回答をお読みください。


1
@Chad、それは意味がない場合でも、その特定のクエリでテーブル名のエイリアスに3文字を使用したという事実への参照でした(cars-> car。ありがとうございます-あなたは私の指を救った)。深く読みすぎないでください。
リウォーク

3
私のエイリアス名よりも悪いのは、複数carsとの混合でしたmanufacturer。1つは複数ですが、もう1つはそうではありません。人々がデータベースを選択したい場合、それは選択すべき悪い習慣です。
CaffGeek

3
悪い習慣だと思います。明らかに、悪い慣行に関する限り、それはひどいことではありません。しかし、回避するのはとても簡単です。今、私は同意します、イントロクラスのために、これは焦点を合わせることですか?おそらくそうではない
...-user606723

2
@ user606723、実際には、イントロクラスでは重要なことだと思います。ベストプラクティスを教えることが基本である必要があります。結果とトレードオフを理解し、ベストプラクティスから逸脱する必要があるのは、経験を積んで初めてです。
CaffGeek

5
@Chad、そう思わない。なぜそれらがベストプラクティスであるのかを理解させることなく、学生に「ベストプラクティス」を教えようとすることは無駄な努力です。そして、すべてを網羅することはできないので、この点を「やるべきではない、後でそれを理解する」と強調することは、教授の観点からはかなり正気の選択です。好奇心students盛な学生はここに投稿するか、うまくいけばこの質問がすでに答えられているのを見つけることができます。(またはクラスの後に尋ねる)
-user606723

123

外部キーを持つテーブルがある場合、その外部キーに「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

正確な名前でこれは問題ではありません


174
これが私にとって十分な説明であるかどうかはわかりません。と言うことに何の問題もありませんSELECT * FROM cars c JOIN manufacturer m ON manufacturer.Id = c.ManufacturerId。私はid何年も使ってきましたが、あなたが説明したものが本当の問題であるとは発見しませんでした。
リウォーク

61
ここでの悪い習慣は、mfgやmodのような名前でテーブルをエイリアスすることです。manufacturer.id = cars.manufacturer_idは非常に読みやすく、エラーも発生します。
-deadalnix

5
@Chad>ダム変数名に問題があります。何度も。繰り返しになりますが、ここで私が私のチームでこれを行う開発者に言うことは«製造は製造者を意味するのではなく、製造者を入力するのが面倒なことを意味します»。
-deadalnix

9
@ Stargazer712:2つのテーブルからSELECT *を実行すると、2つのID列が得られます。IDがあいまいになりました。序数または名前で参照していますか?SELECT *もお勧めしません。不十分な議論。壊れやすいコード。チャドは正しい:基本的に防御的なコーディング
-gbn

6
@gbn、繰り返しますが、単純にすればすべての曖昧さがなくなりますSELECT manufacturer.id FROM ...。から生じるすべての困難idは非常に簡単に克服でき、単に好みの問題になります。
リウォーク

67

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


30
+1「読みにくい」-命名規則は、ずさんなコードのバンドエイドと考えるべきではなく、読みやすさを第一の関心事として改善すべきです。
オコド

12
IDの読み取りははるかに面倒です
HLGEM

5
@HLGEM:列名をテーブル名でいつでも修飾できます。
ケビンクライン

2
読むのが面倒なことを除いては同意します。実際には、より説明的な列名を読み、その列が実際に何のためにあるのかを理解するのに費やす時間を少なくすることを好みます。
デビンディクソン

2
+ 1、Posts.postID、Posts.postNameのような列を持つテーブルを見るのが嫌いで、単純にpost.idとpost.nameを使用する方がはるかにきれいです。
ダグ

40

「Name」や「Id」などの共通またはキー列名には、TableNameをプレフィックスとして付ける必要があります。

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

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


57
あなたがこれを行う場合、私は私が余分なタイピングを行うようにあなたを憎む!!!! テーブルの名前はPersonです。IDはどうなると思いますか?車?いいえ、それは人です。
ジム

16
@jim、あなたのことは知りませんが、6文字の余分な文字を入力すると、約0.5秒かかります。そして、私が1つのテーブルから選択することはめったにないため、「Id」という名前の2つの列になり、とにかくテーブル/エイリアス名を含める必要があることを考慮すると、入力する文字数が節約されません。
CaffGeek

21
@Chad私はそれが不必要だと思う。結合を行っている場合、c.id = m.manufactureridは大丈夫です。これらの列は通常、何らかの方法でクラスに「マッピング」され、Person.PersonIdを持つクラスを作成すると、吐き出したいと思うようになります...はい、問題があることを完全に認識しています。
ジム

20
私もこれに同意しません。なぜで停止nameしてid?すべての列にそのテーブル名をプレフィックスとして付けないのはなぜですか?接頭辞を義務付けるためにこれらの2つの名前を選択するのはarbitrary意的なようです。概念的には、とにかく列のコンテキストを持つためにテーブルが必要です。なぜクエリを明確にするためにそのテーブル名を使用しないのですか:Person.Name、Animal.Name、Part.Name、...
Thomas

11
@Bill Leeper、DRYはデータベース開発において常に適切であるとは限りません。データベースで重要なのはパフォーマンスであり、データベースにDRYの原則を満たすための追加作業を行わせます(スカラ関数またはビューを呼び出すビューやクエリを使用して、列を返す数が多すぎたり、カーソルを使用して1000000レコードを追加して既存のprocを使用するなど)しばしば禁忌です。オブジェクト指向の世界で何かが良いからといって、それがデータベース設計に適しているとは考えないでください。あなたの下票は不適切でした。IDの使用は、既知のSQLアンチパターンです。
HLGEM

31

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

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

正直に言うと、コンピュータープログラミングを教えるほとんどの人々の問題は、もしあったとしても何年にもわたって生産コードの行を書いていないことであり、働くソフトウェアエンジニアが実際に何をするのかわからないことです。作業を開始するまで待ってから、自分の考えが良いアイデアかどうかを自分で決めます。


2
主キーがいずれも複合キーではない場合のみです。これは、残念ながら非常に頻繁に行われます。実際には、特定の状況でのみ代理キーを使用する必要があります。
nicodemus13

6
IDを使用すると、開発者が考えているすべてのテーブルに主キーIDを追加することを考えずに済むという状況になります。リレーショナルデータベースの基盤の1つは、意味のある主キーの使用であり、IDの使用は役に立ちません。
ピーターB

この答えは、あなたが意見を述べた議論で「私はIDを好む」と言っているようです。あなたの議論は、Idと呼ばれるキーを見つけることで、どのキーが主キーであるかを即座に確認できることです。まあ、それはtableIdでもまったく同じです。どのキーが主キーでも混乱しないことを保証できます。IDの前にテーブル名があるものを探します。それだけでなく、最初の列が主キーではない場所でどのような異教徒のテーブルを使用していますか?この答えのあなたの議論はすべて、純粋に優先的なものであり、「tableIdが私にとって間違っていると感じる」に似ていると思います。
ダリン

@dallinのすべての回答には意見があります。そうでなければ、誰かが公式の標準にリンクするだけで、それはありません。
ジェームズ

@James StackExchangeサイトの目標は、意見を述べる回答を減らすことだと思います。だからこそ、質問があまりにも熱心であるとして閉じられます。確かに、それがこの質問が閉じられた理由の一種だと思います-それは意見のある答えを引き出すからです。私の意見では、それが私が好きな理由だけでIDを使用する必要があります」。それは価値のある答えではありません。
ダリン

24

悪い習慣だとは思いません。通常通り、一貫性が重要です。

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

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

同様に、「Foo」というJavaクラスのプロパティには「Foo」というプレフィックスが付いていません。テーブルIDにテーブル名をプレフィックスする義務はありません。通常、コンテキストでは、参照されているIDが明確です。


5
リレーショナルデータベーステーブルはクラスではありません
アダムロビンソン

1
ただし、これらはデータ構造であり、PODOクラスに類似しています。同じ命名の問題が適用されます。
オコド

4
@Slomojo:いいえ、それらは単純なオブジェクトに類似していません。オブジェクト指向設計とデータベース設計は同じではなく、関連さえありません。場合によっては、同様の(または同じ)設計が得られることもありますが、それはそれらが関連していることを示すものではありません。たとえば、m:mリレーションシップはクラスでは簡単ですが、3番目の関連付けテーブルなしでは2つのテーブル間で持つことは不可能です。
アダムロビンソン

1
これがネーミング戦略にどのように関係しているか、私にはわかりません。私の類推は(明らかに?)その範囲に限定されています。
オコド

2
私の暗黙の意味があまり明確ではなかったのが残念です。「この意味では、クラスに類似している」と言っておくべきでした。いずれにせよ、これについて過度にover慢になることは特に建設的だとは思わない。命名に関しては、テーブルとクラスはかなりの類似点を共有しています。袋小路で展開するベストプラクティスは、修正のための公正なゲームであるか、少なくとも議論の余地があります。このQ&Aにはこれを効果的に説明するものがたくさんありますが、他に注目すべき点はありません。
オコド

24

data.stackexchange.comから

投稿のID

BOOM、質問に答えました。
さて、先生に、データベースの設計が悪いことを実践してください。


8
名前に基づいFKSで私の推測で、:PostTypeId -> PostTypes.Id; AcceptedAnswerId -> Answers.Id; OwnerUserId -> Users.Id。なぜそんなに簡単なプラクティスを「悪い」と見なすべきなのでしょうか?
シェード

3
これは、ベストプラクティスについてどのように正確に証明されていますか?
-GBa

5
スタックで何かを使用するかどうかは、それが良いか悪いかを証明しません。
ピーターB

2
それが証明しているのは、この方法がアプリケーションのスケーラビリティと有用性を決して妨げないということです。
サイファー

1
実際、SOプラクティスは完璧ではありません。私はこの命名を使用します:PostType-> PostType.Id; AcceptedAnswer-> Answer.Id; OwnerUser-> User.Id
alpav

17

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

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.idselect * from dudes inner join cars where dudes.carid = cars.id


アプリケーション開発者として最後にストアドプロシージャを記述する場合を除き、実際に完全にフォーマットされたSQLセレクターを記述しましたか?最近の言語にはすべて、この関係を管理する何らかのORM機能が含まれています。列名は、クリーンな手動SQLを作成できるよりもはるかに重要です。
ビルリーパー

4
@Bill私は常に、1日に何度も、開発している言語よりもコードベースに依存しています。また、診断のために、適切で深いリレーションを行いたい場合は、それらの自然な結合をつなぎ合わせて、フィールドIDの検索を完全に回避できます。そして、セントジェロームが有名に言ったように、「SQLの無知はデータベースの無知」です。
ピーターターナー

自然結合は普遍的にサポートされていないという事実を除いて、IMO、自然結合は読みにくいです。関係に2つの列がありますか、それとも1つだけですか?明示的であり、自然な結合を避ける方がはるかに優れています。
トーマス

1
@Thomas、私もコードに自然結合を入れませんが、診断のために、データベースが実際に機能するようにモデル化されている場合、それらが非常に有用であることがわかりました。
ピーターターナー

16

すべてのテーブルに「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)

これは、私にとって最も突出した答えです。USINGキーワードはPostgresの/ mysqlの/ SQLiteデータベースでサポートされ、使用する理由として、他の回答リストのいくつかの少ないタイピングを意味しid、そして最終的には私の主観的な意見では、より読みやすいです。
マイケルバートン

11

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

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

列名は意味的に重要である必要があります。IDジェネリックです。


8
何に対して汎用的すぎる?テーブルのID?
ジム

3
どのテーブルの@Jim?id特に別のテーブルへの外部キーのコンテキストでは、それだけでは何の意味もありません。これは、classes基本的な優れたリレーショナルデータベースの設計とは何の関係もありません。

10
少し太っているのは、それが属するテーブルです。フィールドtable.idを参照する完全に受け入れられる方法ですid。フィールド名の前にテーブル名を付けることは冗長です。
オコド

2
@Slomojは、列に名前を含めることだけで入力することはなく、テーブル名をモンスター結合の1文字または2文字の略語にエイリアスする場合はより明示的です。

6
あなたはどんな悪夢について言及していますか?マネージャーを表す列を持つ従業員の自己参照構造があるとします。外部キーとは何ですか?おそらくあなたのPKであるため、EmployeeIdと呼ぶことはできません。FKの名前はPKと一致する必要はありません。それが含まれるエンティティに対して何を表すかという名前を付ける必要があります。
トーマス

7

IDは、次の理由で不良です。

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

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

結合をコピーして複雑なクエリを作成する場合、エイリアスを必要なものに変更して、誤った結合を取得するのを忘れがちです。各idが含まれているテーブルにちなんで名前が付けられている場合、通常は構文エラーが発生します。また、pPK名とFK名が一致する場合、複雑なクエリの結合が正しくない場合、見つけやすくなります。


+1:これらは私の意見では説得力のある理由ですが、反対する他の答えIDは私をまったく納得させません。
phoog

再:「結合をコピーして複雑なクエリを作成する場合」-あなたの問題はコピー&ペーストです。コピーと貼り付けを停止すると、car.idの命名がいかに便利かがわかります。FKに参加するには、car.mfg = mfg.id、car.color = color.id、car.model = model.idを使用します-非常にシンプルで、LINQで記述する内容と一致します。
alpav

30の結合で何かを書いてみてください。なぜアンチパターンなのかがわかります。
HLGEM

エイリアシングは何よりも重要な理由です。大きな複雑なレポートを作成するとき、これは頭痛の種です。自然結合は単なるおまけです。他の回答がこの点を無視するのは驚くべきことです。いくつかの例を追加すると、ポイントがより明確になり、この答えが本来あるべき場所にジャンプします。
ルル

5

テーブルの主キーの列名として「id」を使用しない最も重要な理由と考えられるものにアプローチする回答がいくつかあります。つまり、一貫性とあいまいさの軽減です。

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

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

はい、これの多くは「id」を持ち、常に「tableNameID」として使用することを知っているという標準によって達成できますが、それは慣習が整っていることを知っていることと、より少ない直感的な標準プラクティス。

長い列名を書き出すには追加のキーストロークが必要であると指摘する人もいますが、コードを書くことはプログラムのアクティブライフのほんの一部にすぎないと思います。開発者のキーストロークを保存することが目標だった場合、コメントを書くべきではありません。

何百ものテーブルを持つ大規模なプロジェクトの保守に長年費やしてきた誰かとして、私はテーブル間でキーの一貫した名前を強く望みます。


仮定Companiesの表は、2〜外部キーを持つPersonsテーブル。1つは会社の社長を表します。もう1つは会社の財務担当者を表します。あなたは本当に列PersonID1を呼び出しますPersonID2か?それらを呼び出すとはるかに記述的にPresidentIDなりTreasurerIDます。inner join Person AS Presidents ON Company.PresidentID = Presidents.IDinner join Person AS Person1 ON Company.PersonID1 = Person1.PersonID
-phoog

1
いいえ、あなたの例では、私はおそらく持っているでしょうCompanyOfficerCompanyPerson間で多対多の関係ができ、テーブルCompanyPerson関係の性質に関する追加情報とを。Companyテーブル内に実装する場合、列名PresidentPersonIDを使用しTreasurerPersonID、追加の記述子を追加するときに名前の* PersonID部分を保持します。 inner join Person as Presidents on Company.PresidentPersonID = Presidents.PersonID
マラキ

5

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

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

次の表を考慮してください。

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

このテーブルの問題は、ユーザーが別の行を追加できることです:United States、countrycode840。これは関係の整合性を破っただけです。もちろん、個々の列に一意性を適用することも、すでに利用可能な主キーを使用することもできます。

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

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


1
異なるシステム間でデータベースを移行する必要がある場合、またはデータベースを一緒にマージする喜びがあったときに、人々がすべてのテーブルに汎用キー列を追加する理由を理解できます。
サイファー

1
これはときどき起こりますが、私の経験では、素敵な一意の不変キーを持つことはめったにありません。しかし、あなたの例でも、国を識別するための意味のない一意の番号があり、データベースではなくISOによって割り当てられた番号のみです。
CodesInChaos

そして今、国名が変更されたら、データベース全体で国名を更新して修正する必要があります。単にサロゲートキー(... "id"など)を使用した場合、更新は簡単になります。自然キーは素晴らしい-それらが完全に不変であり、決して変わらないとき。実際、これが当てはまるケースはほとんどありません。
ジェラート

@Gerrat:国名が変更されても、ISO 3166-1数値コードは変わりません。ISO3166-1 alpha-2およびalpha-3コードのみが変更されます。これは、たとえばビルマ/ミャンマーで起こりました。同様に、国の領土を変更しても名前を保持する場合、ISO 3166-1数値コードは変更されますが、ISO 3166-1 alpha-2およびalpha-3コードは残ります。これは、南スーダンがスーダンから分離し、エリトリアがエチオピアから分離したときに起こりました。東ドイツと西ドイツが再会したとき、彼らは西ドイツのアルファ2およびアルファ3コードを保持していましたが、新しい数値コードを取得しました。国は、完全に溶解または考える(...変換すると
イェルクWミッターク

…90年代のバルカン戦争の結果)、新しい数値とアルファ2およびアルファ3の両方のコードを取得します。
イェルクWミッターク

4

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

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


2

それが適切に使用されている場合、それは悪い習慣だとは思わない。「ID」という名前の自動インクリメントIDフィールドを使用するのが一般的です。このフィールドは、触れる必要はなく、アプリケーションに使いやすい識別子を使用します。次のようなコードを書くのは少し面倒かもしれませんfrom tableA a inner join tableB b on a.id = b.a_idが、そのコードは隠れてしまいます。

個人的な好みとして、エンティティの名前をIDの前に付ける傾向がありIdますが、データベースで完全に処理される場合に使用するだけでは実際の問題は見られません。


それぞれの主キー、特に自動インクリメントIDによって2つのテーブルを結合することはありません。上記のサンプルは、a.id = b.table_a_idのtableA a内部結合tableB bからのものです。
ビルリーパー

ええ、それが私が意味したことです。ほぼ昼休みでエネルギーが必要です。
ウェインモリナ

2

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

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

CREATE TABLE CAR (ID);

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


1
これは、正式なリレーショナル理論の知識が重要である理由を示しています。テーブル名は、単一の行が何であるかを表します。表はをCar表し、TableそれぞれがをRow表しCarます。を呼び出すとCars意味が変わり、形式的な関係理論の基本原則の完全な理解不足が示されます。Railsは危険なことを十分に知っいた人の代表的な例です。

2

この質問は何度も繰り返されてきましたが、私も自分の意見を追加すると思いました。

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

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

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

  4. idも短くて甘い

  5. 追加の規則-すべてのテーブル名と列名に小文字を使用するため、大文字と小文字の問題は検出されません


1

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

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


しかし、それはサードパーティのツールのせいです。列の命名規則は、ツールが内省する必要がある実際の外部キーに代わるものではありません。
ジェラート

1

私はここの人々がほぼすべての側面をカバーしていることを発見しましたが、「id」は「識別子」として読まれるべきではなく、「インデックス」のように読まれるべきではなく、確かに行のアイデンティティを述べたり説明したりしないことを付け加えます。(ここで間違った表現を使用した可能性があります。修正した場合は修正してください)

それは多かれ少なかれ、人々がテーブルデータをどのように読み、どのようにコードを書くかです。個人的には、これが最も頻繁に見られる最も一般的な方法である可能性が最も高いのは、コーダーtable.idがユニオンや結合を行う必要がない場合でも、完全な参照をとして記述することです。例えば:

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

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

したがって、私が追加したいことをまとめると、それは好みの問題であり、記述されたSQLの読み取り方法が最も一般的です。

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

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