「その列が有効であるということが事実なんだから、削除された時は0(FALSE)を立てるべきだろ!」  サマリ系ならs_を頭につけてs_hogeなどと命名する, テーブルが名前順でソートされているより機能->名前順でソートされていた方が、 略語を用いる場合、その規約に従えば誰もが同じ略記をするような、明瞭な規約を掲げることができるのか? ◎ 併せて読みたい記事  → 削除を取り消す処理の実装が、かなり手抜きで済む  マスタ系ならm_を頭につけてm_hoge、 ・代理キーは内部的な値なので、運用や仕様の変更があってもまず影響しない 随時更新予定です。 一覧. What is going on with this article? それにサブクエリとか込み合ってくると混迷としてくるかも? 他の開発言語で既に略記の規約が制定されているのならば、それに合わせればいいのだけれど、 「その列が削除されたということが事実なんだから、削除された時は1(TRUE)を立てるべきだろ!」 対して長さが変わらないじゃんと言われれば確かに変わらない気もします。 ・データベース設計時に徹底してNULLを排斥しておけば、運用時に空文字とNULLが混在する事態にならない, ・そのスキーマにおいて徹底的にNULLを排斥しないと、空文字とNULLが混在して混沌と化す, MySQLは`バッククォート、SQLServerは[]角括弧、 分類方法認識の周知コストを加味した上でも分かりやすいと個人的には思います。, ・分類方法の認識が関係者全員で一致していて、かつそれを厳守しないと混乱を招く By following users and tags, you can catch up information on technical fields that you are interested in as a whole, By "stocking" the articles you like, you can search right away. この記事は、2011年頃に書かれた Yii framework サイトの wiki 記事 Guidelines for good schema design の翻訳です。, もともとは Yii 1.1 のために書かれたものですが、Yii 2, Yii 3 にもそのまま適用可能ですし、もっと広く、アクティブ・レコードのような ORM 一般に通用する内容であろうと思われます。つまり、以下の文章中の "Yii" という名前は、あなたが使っている任意のフレームワークの名前に置き換えてもよい筈です。, 事実上すべての Yii アプリケーションはデータベースの上に構築されます。Yii はデータベースの取り扱いにおいて非常に柔軟ではありますが、以下に述べる設計上の選択をすれば、そうでない場合に比べて、ものごとがより一層都合良く進みます。, 最初に、ごく大まかに言うと、Yii アプリケーションではアクティブ・レコードを多用しますので、設計上の考慮では、複雑な SQL クエリを構築しようとする人間のことよりも、アクティブ・レコードを使う上での最適化を中心に置くべきです。実際、以下に述べる設計のガイドラインの多くは、SQL フレンドリーなスキーマを作成するための良い習慣とは真っ向から対立するものです。, しかし、このガイドラインのほとんどは、他人が読んで理解できるコードを書けるようにすることを目的としています。コードにおいては名前は 意味を持つ ものであり、一貫性に欠ける命名規約はコードを追うことを非常に難しくするのです。, このことはフォーラムやチャットの #yii チャンネルで助力を求める場合に特に当てはまります。正しい意味を反映しない変な名前を使っていると、コードが何をやっているのかを明確にするための逆質問ばかりを沢山もらって、実際の問題に対してはあまり助力を得られないということになりかねません。, とは言え、以下はガイドラインに過ぎず、規則ではありません。これらのガイドラインに従わなくても、コードは動きます。しかし、これらのガイドラインを採用する方が、楽な道を歩むことが出来ます。, SQL テーブル は複数の事物を保持するものと考えられますが、モデル はその中のたった一つの事物です。$model = new Comments() という記述は何か変です。この違和感が、リレーションを定義するときをはじめとして、どこまでも付いて回ることになります。, テーブルは comments でなく comment, invoices でなく invoice としましょう。そして対応するモデル名も単数形 (Comment, Invoice) にします。, どうしても DB スキーマを変更できない場合は、少なくとも、Yii のモデル・クラスの名前を単数形に変更します。ただし、コード中に追加のコメントを記して、この不整合に対する注意を喚起しておきましょう。, これは伝統的な SQL スキーマ設計では当り前の習慣ですが、アクティブ・レコードを使う場合には、鬱陶しいものになります。たとえば、category テーブルでは、こうです。, 長い名前のやり方は、手作業で SQL クエリを組む場合にちょっとだけ読みやすくなるのは事実ですが、アクティブ・レコードで使うのには向いていません。, Yii はテーブル・プレフィックスの考え方をサポートしています。これは共有ホスト環境で すべての アプリケーションが単一のデータベースを共有する場合に有用なものです。例えば、ブログのテーブル名の頭には blog_ を付ける、時間管理のテーブル名の頭には time_ を付けるなどすると、同じデータベースの中でお互いに干渉することなく動作させることが出来ます。, しかし、クラス名 にはこれらのプレフィックスを決して含めるべきではありません。なぜなら、干渉を回避する必要が無いからです。ブログのアプリケーションは、時間管理のアプリケーションとは全くの別物です。, たいがいのテーブルは、それ自体の独立した単一カラムのユニークなプライマリ・キーを持っています(int NOT NULL AUTO_INCREMENT PRIMARY KEY というのがよくある例です)。これが id という名前 (commentid とか postid とかではなく) を持っている方が、物事がほんの少しスムーズに動くようになります。, 名前が何であっても、Yii はデータベース・スキーマを読んでプライマリ・キーが何であるかを正しく判断します。しかし、システムの他の部分ではそれに従うことが出来ず、キーが id であることを明らかに前提としている場合もあります。, 例 : CArrayDataProvider はキーが id であると見なしています。これは keyField 属性によってオーバーライド出来るものではありますが、そもそも、そういう事をする必要が無い方が好都合です。, ただし、この規則が当てはまらない場合もいくつかあります。例えば、テーブルがマルチ・カラムのプライマリ・キーを持っている場合や、テーブルのプライマリ・キーが他のテーブルの ID への外部キーである場合などです。, 古典的な設計上の失敗の一つとして、実際の意味を持つプライマリ・キー、というのがあります。以下の例では、username が user テーブルのプライマリ・キーになっています。, 整数のプライマリ・キーを作って、name をユニークにする方が断然すぐれています。, たいていのデータベースでは、このフィールドは別のテーブルのプライマリ・キーを指し示す ID を保持している、というような、テーブル間の関係を定義することが出来ます。これが外部キー制約と呼ばれるもので、他から参照されている行が削除されるのを防止するなどして、参照一貫性を保持する上で役に立ちます。, MySQL の InnoDB は外部キー制約をサポートしています。MyISAM では、外部キー制約は 定義 することは出来ますが、強制 することは出来ません。Yii はスキーマからこういう関係を読み取る方法を知っており、Gii/Giix ツールが適切なリレーションを自動的に作成してくれます。, しかし、たとえ Yii が外部キー制約を考慮しないとしても、外部キー制約はデータベースの参照一貫性を維持するための不可欠な要素です。これについて学ぶためには、ウェブ上に沢山のチュートリアルがありますので参照して下さい。, 前項と関連しますが、他のテーブル、例えば user の ID を保持するフィールドには user ではなく userid という名前を付けます。と言うのは、まず間違いなく、テーブルに含まれるすべての外部キーについて、それに対応する リレーション を定義する必要があるからです。, Yii では、クラス変数、DB フィールド、仮想属性、リレーションは単一の名前空間を共有します。従って、$model->user をテーブルの外部キー および リレーションの 両方 を示すものとして定義することは出来ません。, 外部キーを userid という名前にすれば、BELONGS_TO リレーションである $model->user が自然で分りやすい名前になります。, メモ : id でなく Id や _id を好む人もいます。これは純然たる好みの問題です。ただし一貫性を失わないようにしましょう。, 一貫性と他人にとってのコードの読みやすさというテーマに沿って、リレーションもそれぞれの性質に応じた単数形/複数形の名前を持つべきです。, 配列を返すリレーションは、モデルを一つだけ返す場合であってもそれを 配列 に入れて返します。この事実が複数形の名前の根拠となることに注意して下さい。, コードを見ただけで、リレーションが配列を返すのか単一のモデルを返すのか、区別できるようにすべきです。, 定義を見ないと分らないと言うようでは、コードの可読性と保守性を大いに低下させていると言わざるを得ません。. テーブル名から指定してあげないと、どちらのテーブルの列を見ていいか分からず警告が出てしまいます。 ⇒ fuga_codeではなく、fuga_cdとして命名する, ・略語の規則を関係者全員が知っていて、かつそれを厳守しなければ混乱を招く 東京のITスタートアップでWebアプリケーションエンジニアをしています。 データベース設計の命名規約について主流なものやおすすめがあればご教示ください。 前提:ひとまずMySQLを対象とします。 ・テーブル名は複数形かどうか(userテーブルかusersテーブルか) ・主キーにテーブル名を… ・長い, ◎ 主キーにたくさんの列を使わないといけないとき(複合主キーのとき) エクセルvbaでデータベースを扱うためのsql入門です。前回までは1つのテーブルのみを扱ってきましたが、これからは複数のテーブルを扱っていきます。複数テーブルの情報を必要に応じて結合して取得できるようになると、よりデータベースおよびsqlの利便性が感じられると思います。 実際に使えそうなテーブル名、カラム名を記録していきます。 ほぼ自分用のメモ. とか言い出す人が現れるかもしれない。。。そんなひとはいない?, ◎ 将来に漠然とした不安を抱いてしまうとき phpに引き続きdb命名規則も作成しておきます。とはいっても、自分で作成する知識も経験も無いので参考になりそうな情報を探してみました。すると、こちらのサイトで纏められていたので丸パクリ使わせてもらう事にします。テーブル名 むしろ謎基準で命名された別名で、元テーブルを判断しなくて済むぶんはいいかもしれない。 仕様が変わったんだから設計を見直すべきだとなるべきなのかは難しいところです。, 『関係モデルに存在しない概念を導入することになる』ことによるデメリットは、 ⇒列を単にfugaではなく、hoge_fugaとして命名する, ・わかりやすいかもしれない Why not register and get more from Qiita? (例えばWHERE hoge.fuga = foo.barではなくテーブル名を省略してWHERE fuga = barとしてしまう書き方は) 個々の裁量に任せると却って分からなくなってしまいます。 Help us understand the problem. ・問題3 ⇒ 『is_deleted』みたいな列を用意して、0か1を入れる, ・削除された列をもとに戻したい(削除を取り消したい)とき簡単に済む  ワーク系ならw_を頭につけてw_hogeなどと命名する, ⇒イベント系ならe_を頭につけてe_hoge、 ・命名できる要素の種類が多いため、十全な略語の規約設定・周知にコストがかかる 同じ内容を意味する語の成分(接頭語や接尾語も)は、同じ語句を使う。たとえば、日付を表す語句に、DATEならDATE、DTならDT、BI(「~日」の日本語読み)ならBIで、どれを使ってもよいが、統一させて使う。 最近は多少冗長でも一切略記をしないコーディング規約も多いらしいので悩むところ。, ユーザが任意に省略するかを選択できる項目なので別途挙げました。 『SQLアンチパターン』ISBN 978-4-87311-589-4 ⇒トランザクション系ならt_を頭につけてt_hoge、 Help us understand the problem. ◎ 主キーにできる列(候補キー)が文字列型で、長ったらしい文字が入るかもしれないとき 排除すべきなのだろうから、重複しないことをメリットとして挙げるのも間違っているのかもしれません。, テーブル名.列名で指定するのと、テーブル名つき列名で指定するんじゃ、 この方法は、従来のSQLスキーマ設計では一般的ですが、ActiveRecordを使用する場合は面倒です。 ・問題2 Help us understand the problem. データベースやらSQLとかやらで、わからないなりに実装するかどうか悩んだことを書き連ねてみます。, ◎ 併せて読み返したい書籍  リソース系ならr_を頭につけてr_hoge、 ◎ 過去に辛い思いをして理想と現実の差を知ってしまったとき |Ruby|Ruby on Rails|PHP|Laravel|JavaScript|TypeScript|Vue.js|Nuxt.js|Kotlin|Go|Android|AWS|CircleCI|Stripe|Docker... Why not register and get more from Qiita? 『略語は使って使わなくてもいいし、使うならご自由にどうぞ』という選択肢は妥協案として存在していいのか?, ◎ 列fuga_codeという名前をつけたいとき、 ほとんどのArm IPが試し放題でスタートアップは年会費無料!?Arm Flexible Access, you can read useful information later efficiently. 『一切略語を使用しない』『掲げた規約に準じた命名を行う』という選択肢は妥当であるように思われるが、 ・レコード数が減らないのでテーブルがどんどん大きくなってしまう, 『delete_flag』と命名して、 What is going on with this article? ⇒ NOT NULL制約をつけてDEFAULT ''にする, ・NULLの扱いで悩まずに済む ほとんどのArm IPが試し放題でスタートアップは年会費無料!?Arm Flexible Access, 定数で定義 'GENDERS' => ['1' => '男性', '2' => '女性', '3' => 'その他'], 定数で定義 'BLOOD_TYPES' => ['1' => 'A', '2' => 'B', '3' => 'O'], 定数で定義 'COUNTRIES' => ['1' => 'アメリカ', '2' => '日本'], you can read useful information later efficiently. ⇒ とりあえず列の大きさを(255)で定義する ・わかりやすいかもしれない, ・すべてのSQLにおいて漏れなく区切られた識別子をつけるのは地味にたいへん 画一的な略語の規約を見つけたり設定するのってなかなか難しいのですが、 ⇒ そのテーブルの一番左に列をつくり通番を振って、振られた連番を主キーにする, AUTOINCREMENT, UNSIGNED, UNIQUE, NOTNULLなどといった属性を持たせて、 By following users and tags, you can catch up information on technical fields that you are interested in as a whole, By "stocking" the articles you like, you can search right away. かつ原則的にUPDATE, INSERTのとき指定しない列をテーブルの左端にCREATEして主キーにします。, ・WHERE句で指定しなければならない条件が少なくてすむ場合がある you can read useful information later efficiently. 命名規則. Why not register and get more from Qiita? 用途 論理名 物理名 型 備考; テーブル名: ユーザー: users: カラム名: ユーザー名: screen_name: varchar: カラム名: 姓: last_name: varchar: カ … ◎ フレームワークでお手軽につくると勝手についちゃうとき postgreSQLは"ダブルクォートなど言語によって違いがあります。, ・エスケープ処理が適切ならば、SQLインジェクションを食い止めることができるかもしれない ⇒ とりあえず小数点以下の桁数を大きめに定義する 要点は、テーブル名を単数形にするということです。 comment # OK comments # Not OK invoice # OK invoices # Not OK フィールド名の前にDBテーブル名を追加しないでください. どこか別の記事を参照してください。。。。, ・誰がテーブルを作成しても主キーはとりあえず存在する ・テーブル同士を紐付けるとき、お互いが持たなければならない列数が少なくなる ⇒『予備1』みたいな列をつくる ⇒ 作成者、作成日時、更新者、更新日時をとりあえずつけておく, ・『拡張してほしい』という要望が出て来づらくなる、出て来ても小手先で対応できるかもしれない, 代理キーも削除フラグも、ある意味拡張性をもたせていると考えられるかもしれない。。。, ◎ 必ずしも値が入らない文字列型の列があったとき データベースオブジェクトの命名規約, ・問題1 略語を用いてわかりやすくなるのか? 混乱するだけじゃないのか? ⇒ 外部キー, NOTNULL, UNIQUE, CHECKみたいな制約に対して消極的になる だけどアンダーバーだけでしか区切れないと、やっぱわかりづらい。 エイリアスをつけること自体は実行速度的に良いことらしいので命名していきたいところです。, ◎ テーブルhogeに列fugaという名前をつけたいとき、 ・代理キーの連番が1,2,4,……のように飛ばない(歯抜けにならない), ・有効な列を取得したいとき、常にWHERE句に『is_deleted != 1』みたく書く必要がある More than 1 year has passed since last update.  →自然キー(ナチュラルキー)だと、後々やっぱり重複させたくなるかもしれない, ただ、そのとき代理キーがあるから良かったねで済ませるべきなのか、 (各種テーブル/ビュー/カラム/ユーザ定義関数・変数/インデックス/制約など), 俺はnameをnmとするぜ! 私はnumberをnmにするわ!など、 ちなみにNATURAL JOINが使えなくなります。, ◎ テーブルhogeが存在するとき、 What is going on with this article? By following users and tags, you can catch up information on technical fields that you are interested in as a whole, By "stocking" the articles you like, you can search right away. どうしても DB スキーマを変更できない場合は、少なくとも、Yii のモデル・クラスの名前を単数形に変更します。ただし、コード中に追加のコメントを記して、この不整合に対する注意を喚起しておきましょう。 フィールド名にテーブル名を追加しない データベースやらSQLとかやらで、わからないなりに実装するかどうか悩んだことを書き連ねてみます。 ◎ 併せて読み返したい書籍 『SQLアンチパターン』ISBN 978-4-87311-589-4 ◎ 併せて読みたい記事 データベースオブジェクトの命名規約 けれど、そもそもテーブル名を省略して列名のみで指定しようとする書き方は ステム開発入門 - Perl&Mojolicious, データベースのテーブル名とフィールド名の命名規約, 複数形ではなく単数形でデータベースのテーブルに名前を付ける li>, フィールド名の前にDBテーブル名を追加しない li>, モデルクラス名にテーブルプレフィックスを含めない li>, テーブルのID列に「id」という名前を付けます li>, 意味のある主キー名を避ける li>, データベーススキーマで外部キーの関係を定義する li>, 「id」で終わる外部キーフィールドに名前を付ける li>, 単数形/複数形の性質を反映する名前関係を行う li>.