私のt-sqlの先生は、PKカラムに「Id」という名前を付けることは、それ以上の説明なしに悪い習慣と見なされると教えてくれました。
テーブルのPK列に「Id」という名前を付けるのは悪い習慣と見なされるのはなぜですか?
私のt-sqlの先生は、PKカラムに「Id」という名前を付けることは、それ以上の説明なしに悪い習慣と見なされると教えてくれました。
テーブルのPK列に「Id」という名前を付けるのは悪い習慣と見なされるのはなぜですか?
回答:
それは本当に悪い習慣はありません(と、それであっても、そのない:私は出てくるし、それを言うつもりだという悪いです)。
(チャドが指摘したように)次のクエリのようにエラーをマスクできるという引数を作成できます。
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」という名前を付けるという問題は、悪い習慣であるというよりも好みの問題に近いです。
編集者への注意:このクエリのエラーは意図的なものであり、指摘するために使用されています。編集する前に完全な回答をお読みください。
cars
-> car
。ありがとうございます-あなたは私の指を救った)。深く読みすぎないでください。
cars
との混合でしたmanufacturer
。1つは複数ですが、もう1つはそうではありません。人々がデータベースを選択したい場合、それは選択すべき悪い習慣です。
外部キーを持つテーブルがある場合、その外部キーに「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
正確な名前でこれは問題ではありません
SELECT * FROM cars c JOIN manufacturer m ON manufacturer.Id = c.ManufacturerId
。私はid
何年も使ってきましたが、あなたが説明したものが本当の問題であるとは発見しませんでした。
SELECT manufacturer.id FROM ...
。から生じるすべての困難id
は非常に簡単に克服でき、単に好みの問題になります。
RubyのActiveRecordライブラリとGroovyのGORMは、デフォルトでサロゲートキーに「id」を使用します。私はこの練習が好きです。各列名にテーブル名を複製するのは冗長で、書くのが面倒で、読むのが面倒です。
「Name」や「Id」などの共通またはキー列名には、TableNameをプレフィックスとして付ける必要があります。
これにより、あいまいさがなくなり、検索が容易になり、両方の「Id」値が必要な場合の列エイリアスがはるかに少なくなります。
使用頻度の低い列または監査列または非キー(LastUpdatedDateTimeなど)は関係ありません
name
してid
?すべての列にそのテーブル名をプレフィックスとして付けないのはなぜですか?接頭辞を義務付けるためにこれらの2つの名前を選択するのはarbitrary意的なようです。概念的には、とにかく列のコンテキストを持つためにテーブルが必要です。なぜクエリを明確にするためにそのテーブル名を使用しないのですか:Person.Name、Animal.Name、Part.Name、...
このスレッドは死んでいますが、IMO を使用しないのId
は悪い習慣です。このId
列は特別です。それは主キー。任意のテーブルに任意の数の外部キーを含めることができますが、プライマリキーは1つだけ持つことができます。すべての主キーが呼び出されるデータベースでは、テーブルを見るとすぐに、どの列が主キーであるかが正確にわかります。Id
私を信じて、今では何日も毎日たくさんの大きなデータベース(Salesforce)で仕事をしてきました。スキーマについて言えることは、すべてのテーブルにと呼ばれる主キーがあることId
です。PKが呼び出されるため、主キーを外部キーに結合することについて絶対に混乱しないことを保証できますId
。人々が言及していないもう一つのことは、テーブルのように長い愚かな名前を持つことができるということTable_ThatDoesGood_stuff__c
です。アーキテクトが朝に二日酔いしてそのテーブルを考えたため、その名前は十分に悪いですが、今では主キーを呼び出さないことは悪い習慣であると言っていますTable_ThatDoesGood_stuff__cId
(SQL列名は一般的に大文字と小文字を区別しないことに注意してください)。
正直に言うと、コンピュータープログラミングを教えるほとんどの人々の問題は、もしあったとしても何年にもわたって生産コードの行を書いていないことであり、働くソフトウェアエンジニアが実際に何をするのかわからないことです。作業を開始するまで待ってから、自分の考えが良いアイデアかどうかを自分で決めます。
悪い習慣だとは思いません。通常通り、一貫性が重要です。
コンテキストがすべてだと思います。テーブル自体のコンテキストでは、「id」はまさにあなたが期待するものを意味し、他の方法で同一である(または表示される)可能性のあるものに対して一意に識別するのに役立つラベルです。
結合のコンテキストでは、あなたとあなたのチームが読めるように結合を構築するのはあなたの責任です。言い回しやネーミングが不十分で物事を難しくすることができるのと同じように、エイリアスやコメントを効果的に使用して意味のあるクエリを作成することも同様に可能です。
同様に、「Foo」というJavaクラスのプロパティには「Foo」というプレフィックスが付いていません。テーブルIDにテーブル名をプレフィックスする義務はありません。通常、コンテキストでは、参照されているIDが明確です。
BOOM、質問に答えました。
さて、先生に、データベースの設計が悪いことを実践してください。
PostTypeId -> PostTypes.Id
; AcceptedAnswerId -> Answers.Id
; OwnerUserId -> Users.Id
。なぜそんなに簡単なプラクティスを「悪い」と見なすべきなのでしょうか?
テーブルで自然な結合を実行することは難しく(そして混乱させます)、そのため、非常に悪くないとしても悪いことです。
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
すべてのテーブルに「ID」を付けるのが最善のアイデアではない状況がありUSING
ます。それがサポートされている場合、キーワードです。MySQLで頻繁に使用します。
たとえば、fooTable
with column fooTableId
およびbarTable
foreign 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
、そして最終的には私の主観的な意見では、より読みやすいです。
先生に聞いてみませんか?
これを考えてください。すべてのテーブルPK列に名前が付けられるID
と、外部キーとして使用するのは悪夢になります。
列名は意味的に重要である必要があります。ID
ジェネリックです。
id
特に別のテーブルへの外部キーのコンテキストでは、それだけでは何の意味もありません。これは、classes
基本的な優れたリレーショナルデータベースの設計とは何の関係もありません。
table.id
を参照する完全に受け入れられる方法ですid
。フィールド名の前にテーブル名を付けることは冗長です。
IDは、次の理由で不良です。
多数のレポートクエリを実行する場合、両方を表示する場合は常に列のエイリアスを作成する必要があります。したがって、最初から適切な名前を付けることができれば、時間の無駄になります。これらの複雑なクエリは、不必要な作業を行う追加の負担なしで、十分に困難です(数百行の長さのクエリを作成します)。
コードエラーが発生する可能性があります。自然な結合の使用を許可するデータベースを使用する場合(それを使用する必要はないと思いますが、機能が使用可能になったときに誰かがそれらを使用します)、それを使用する開発者を取得すると、間違ったことに参加します。
結合をコピーして複雑なクエリを作成する場合、エイリアスを必要なものに変更して、誤った結合を取得するのを忘れがちです。各idが含まれているテーブルにちなんで名前が付けられている場合、通常は構文エラーが発生します。また、pPK名とFK名が一致する場合、複雑なクエリの結合が正しくない場合、見つけやすくなります。
ID
は私をまったく納得させません。
テーブルの主キーの列名として「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.ID
inner join Person AS Person1 ON Company.PersonID1 = Person1.PersonID
CompanyOfficer
かCompanyPerson
間で多対多の関係ができ、テーブルCompany
とPerson
関係の性質に関する追加情報とを。Company
テーブル内に実装する場合、列名PresidentPersonID
を使用しTreasurerPersonID
、追加の記述子を追加するときに名前の* PersonID部分を保持します。 inner join Person as Presidents on Company.PresidentPersonID = Presidents.PersonID
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
そのようにして、既存の情報を主キーとして使用します。これは、リレーショナルデータベース設計の中心です。
それが適切に使用されている場合、それは悪い習慣だとは思わない。「ID」という名前の自動インクリメントIDフィールドを使用するのが一般的です。このフィールドは、触れる必要はなく、アプリケーションに使いやすい識別子を使用します。次のようなコードを書くのは少し面倒かもしれませんfrom tableA a inner join tableB b on a.id = b.a_id
が、そのコードは隠れてしまいます。
個人的な好みとして、エンティティの名前をIDの前に付ける傾向がありId
ますが、データベースで完全に処理される場合に使用するだけでは実際の問題は見られません。
IDは十分に一般的であるため、誰も混乱させることはないと思います。あなたはいつもテーブルを知りたいでしょう。テーブル/エイリアスを含めずに実動コードにフィールド名を入れるのは悪い習慣です。アドホッククエリをすばやく入力できるかどうかを過度に心配している場合は、自分で作成してください。
IDが予約語であるsqlデータベースを誰も開発しないことを願っています。
CREATE TABLE CAR (ID);
フィールド名、主キー、および1で始まる1ずつの自動インクリメントを、1つのすてきな2文字のパッケージですべて処理します。ああ、私はそれをCARSと呼んでいましたが、キーストロークを節約し、CARというテーブルには1つしかないと思う人は誰ですか?
この質問は何度も繰り返されてきましたが、私も自分の意見を追加すると思いました。
idを使用して、それが各テーブルの識別子であることを意味します。したがって、テーブルに結合し、主キーが必要な場合、自動的に主キーに結合します。
idフィールドは、符号なしの自動インクリメントです(つまり、値を設定する必要はなく、負の値にすることはできません)
外部キーの場合、tablenameidを使用します(スタイルの問題)が、結合する主キーはテーブルのidフィールドであるため、一貫性があるため、クエリを常に簡単に確認できます
idも短くて甘い
追加の規則-すべてのテーブル名と列名に小文字を使用するため、大文字と小文字の問題は検出されません
考慮すべきもう1つのことは、プライマリキー名が外部キー名と異なる場合、特定のサードパーティツールを使用できないことです。
たとえば、スキーマをVisioなどのツールにロードして、正確なERDを生成することはできません。
私はここの人々がほぼすべての側面をカバーしていることを発見しましたが、「id」は「識別子」として読まれるべきではなく、「インデックス」のように読まれるべきではなく、確かに行のアイデンティティを述べたり説明したりしないことを付け加えます。(ここで間違った表現を使用した可能性があります。修正した場合は修正してください)
それは多かれ少なかれ、人々がテーブルデータをどのように読み、どのようにコードを書くかです。個人的には、これが最も頻繁に見られる最も一般的な方法である可能性が最も高いのは、コーダーtable.id
がユニオンや結合を行う必要がない場合でも、完全な参照をとして記述することです。例えば:
SELECT cars.color, cars.model FROM cars WHERE cars.id = <some_var>
そうすれば、「番号が付けられているその車の色とモデルを教えてください」と英語に翻訳できます。「番号として識別されるその車の色とモデルを教えて」ではありません。IDは自動車を表すものではなく、自動車の唯一のインデックスであり、シリアル番号です。配列から3番目の要素を取得する場合と同じです。
したがって、私が追加したいことをまとめると、それは好みの問題であり、記述されたSQLの読み取り方法が最も一般的です。
ただし、IDが実際に記述している文字列である場合など、これは使用されない場合があります(はるかにまれな例)。たとえば、id = "RedFordMustang1970"
または同様のもの。少なくともアイデアを得るためにこれを説明できればと思っています。