私にはいくつかのアイデアがあり、そのいくつかは時間の経過とともに蓄積されてきましたが、データベースをモデル化するときに何がスムーズに進むのかを本当に知りたいです。
全員の入力を1つのリストにまとめます。
命名基準
データ型
コード内
ドキュメント
正規化と参照整合性
メンテナンス:定期的なスクリプトを実行して検索
良くなる
私がまだ言及していないことの1つ:
データベースキーワードをオブジェクト名として使用しないでください。あなたはそれらを使用するたびにそれらを修飾する必要はありません
作成時にスペルを間違えた場合は、気づいたらすぐに修正してください。このテーブルでは、UserNameは実際にはUsernmaeであることを覚えておく必要はありません。それに対して書かれたコードがあまりない場合は、修正するのがはるかに簡単です。
暗黙の結合(コンマ構文)は使用せず、常に結合を指定してください。
Oracleの私の標準は次のとおりです。
SQL Serverでは、唯一の変更は、データベースオブジェクト名にキャメルケースを使用することです(つまり、party_nameの代わりにPartyName)。
クエリは、1行に1つの句または条件を含む複数行で記述される傾向があります。
SELECT field1, field2, field2
FROM tablename t1
JOIN tablename2 t2 ON t1.id = t2.tablename_id
WHERE t1.field1 = 'blah'
AND t2.field2 = 'foo'
SELECT句が十分に長い場合は、1行に1つのフィールドに分割します。
データベースを定期的にバックアップすることを忘れないでください。
データベースが特定のアプリケーション用である場合は、バージョンテーブルを用意して、データベースのリリースをコードのリリースと照合できるようにします(他の理由もあります)。
フィールド名にタイプ名を使用しないでください。年配の人は、lpszFieldNameの古いMS標準とそれに続く愚かさを覚えているでしょう。
通常の言語規則に従った説明的なフィールド名を使用します。たとえば、「NameFirst」ではなく「FirstName」
フィールド名の各単語は大文字です
アンダースコアなし
「インデックス」などの通常のキーワードは使用しないでください
オブジェクトタイプの前にANYTHINGを付けないでください。たとえば、tblCustomersやspCustomersGetは使用しません。これらは適切なソートを可能にせず、ゼロ値を提供します。
スキーマを使用して、データベースの個別の領域を定義します。 sales.Customersやhr.Employeesなど。これにより、人々が使用するほとんどのプレフィックスが削除されます。
あらゆる種類のループは、疑いを持って表示する必要があります。通常、より良いセットベースの方法があります。
複雑な結合にはビューを使用します。
可能な場合は、複雑な結合を避けてください。 CustomerPhoneNumbersテーブルがある方がより魅力的かもしれません。しかし正直なところ、実際にいくつの電話番号を保存する必要がありますか?顧客テーブルにフィールドを追加するだけです。 DBクエリが高速になり、理解しやすくなります。
1つのテーブルがフィールド「EmployeeId」を呼び出す場合、それを参照するすべての単一テーブルはその名前を使用する必要があります。拡張テーブルにあるという理由だけでCustomerServiceRepIdを呼び出す必要はありません。
ほとんどすべてのテーブルの末尾に「s」が付いています。例:顧客、注文など。結局のところ、テーブルには多くのレコードが保持されています。
分析ツールを使用して、クエリ、インデックス、および外部キーの関係を評価します。あなたのために生成されるかもしれないものでさえ。驚かれるかもしれません。
多対多の関係をサポートするリンクテーブルには、名前に両方のリンクテーブルがあります。たとえば、SchoolsGradesです。テーブル名で何をするのかを簡単に見分けることができます。
一貫性を保つ。慣例に従って1つのパスを開始する場合は、前のすべての作業をリファクタリングする意思がない限り、途中で馬を変更しないでください。これは、混乱と膨大な量のやり直しを引き起こす結果となる「もしも素晴らしいと思いませんか」というアイデアにブレーキをかけるはずです。
入力する前によく考えてください。そのテーブル、フィールド、sproc、またはビューが本当に必要ですか?他の場所でカバーされていませんか?追加する前にコンセンサスを取得してください。そして、何らかの理由でそれを取り出さなければならない場合は、最初にチームに相談してください。私は、DBAが開発者に関係なく毎日最新の変更を加える場所に行ってきました。これは面白くない。
私は常にフィールド名のタイプ(「sFirstName」、「sLastName」、または「iEmployeeID」)を使用しないようにしています。それらは最初は一致しますが、何かが変更されると同期がとれなくなり、依存オブジェクトも変更する必要があるため、後でそれらの名前を変更することは大きな頭痛の種です。
IntellisenseとGUIツールを使用すると、列のタイプを簡単に見つけることができるので、これは必要ないと思います。
すべてのvarchar/nvarcharの選択が適切であることを確認してください。
すべてのNULL可能列の選択が適切であることを確認します-可能な場合はNULL可能列を避けます-NULLを許可することは正当な位置である必要があります。
ここでの提案から使用する可能性のある他のルールに関係なく、データベースにストアドプロシージャを作成します。このストアドプロシージャを定期的に実行して、使用しているルールまたは標準のシステムの状態を判断します(これの一部は小さなSQLです) -サーバー固有):
何らかの理由でDBMSシステムの参照整合性を使用できない場合は、孤立したレコードを探します(私のシステムには、プロセスのテーブルとテストのテーブルがあります。したがって、system_health SP私は一方向のFK関係しかないため、テストなしのプロセス)
空のスキーマを探す
主キーのないテーブルを探す
インデックスのないテーブルを探す
ドキュメントのないデータベースオブジェクトを探します(SQL Server拡張プロパティを使用してドキュメントをデータベースに配置します-このドキュメントは列のように細かくすることができます)。
システム固有の問題を探します-アーカイブする必要のあるテーブル、通常の月次または日次処理の一部ではない例外、デフォルトの有無にかかわらず特定の一般的な列名(たとえば、CreateDate)。
非決定論的UDFを探す
TODOコメントを探して、DB内のコードに未テストまたはプレリリースのコードが含まれていないことを確認します。
これらすべてを自動化して、システムの状態の全体像を把握できます。
WITH句は、クエリを管理可能な部分に分割するのに役立ちます。
また、クエリの実行プランの効率化にも役立ちます。
誰もがSQLクエリ(ビュー、ストアドプロシージャなど)を同じ基本形式で記述します。これは、今後の開発/保守作業に本当に役立ちます。
一貫した命名基準。全員が同じページにいて、同じ形式(キャメルケース、特定のプレフィックスなど)を使用すると、システムを正確に維持できるようになります。
いくつかの好き嫌い。
私の意見では、プレフィックスはあらゆる面で恐ろしいものです。私は現在、テーブルにプレフィックスが付いており、テーブル内の列に2文字のテーブル名の頭字語が付いているシステムで作業しています。頭字語が論理的ではないため、このデータベースでの作業に毎日少なくとも30分を浪費しています。接頭辞を付けて何かを示したい場合は、代わりにスキーマ所有者を使用してください。
プロジェクトの開始からNVarcharを使用するのは、テキストデータが多言語文字をサポートする必要があるというわずかなヒントさえある場合です。将来の計画と思考が不足しているために大規模なデータベースをアップグレードすることは、苦痛であり、時間を浪費します。
Where句内の各条件を読みやすくするために新しい行に分割します(括弧で囲まれてタブで囲まれたステートメントではなく)。これは私にとって重要な標準だと思います。
私はある会社で働いていました。そこでは、パラメーターまたは変数の宣言を実行するときは常にコンマを行の先頭に配置する必要があるという基準がありました。これは明らかにそれをより読みやすくしました、しかし私はそれが完全な悪夢であるとわかりました。
表形式のSQL。
select a.field1, b.field2
from any_table a
inner join blah b on b.a_id = a.a_id
inner join yet_another y on y.longer_key = b.b_id
where a.field_3 > 7
and b.long_field_name < 2;
これの一部は、均一に長いエイリアス名を使用することです(この例では、a、b、およびyはすべて長さ1です)。
この種のフォーマットを使用すると、「どのテーブルが「a」によってエイリアスされているか」などの一般的な質問にすばやく答えることができます。および「どのフィールドがテーブルTをクエリに結合しますか?」構造の適用や更新にそれほど時間はかからず、多くの時間を節約できることがわかりました。コードを書くよりも読むことに多くの時間を費やしています。
優れたデータベース設計と正規化。
3NFまたはBCNFへの正規化(詳細については この質問 )に加えて、次のことが役立つことがわかりました。
したがって、「People」テーブルには「PersonID」列があります。
他のいくつかの(小さいながらも)コメントは壁に投げつけます...
SQL Serverデータベーススキーマは、テーブルとストアドプロシージャの整理、およびセキュリティの制御の両方に役立ちます。
すべてのトランザクションテーブルは、常に誰がいつレコードを作成したかを追跡し、レコードを別々の列で更新する必要があります。将来の監査の課題につながる可能性のある「更新日」を単に使用した実装を見てきました。
オフライン/同期要件のあるプロジェクトのすべての行の行識別子にGUIDを使用します。
私はここで他の人と同じ慣習をたくさん守っていますが、まだ言われていないことをいくつか言いたかったのです。
テーブルに複数の名前が好きか単数の名前が好きかに関わらず、一貫性を保ってください。どちらか一方を選択しますが、両方を使用しないでください。
テーブルの主キーの名前はテーブルと同じで、接尾辞は_PKです。外部キーの名前は対応する主キーと同じですが、接尾辞は_FKです。たとえば、Productテーブルの主キーはProduct_PKと呼ばれます。 Orderテーブルでは、対応する外部キーはProduct_FKです。私はこの習慣を私の別のDBAの友人から拾い上げました、そして今のところ私はそれが好きです。
INSERT INTO ... SELECTを実行するときは常に、SELECT部分のすべての列にエイリアスを付けて、INSERT INTO部分の列の名前と一致させ、保守と一致の確認を容易にします。
13-クエリを評価する
それは本当だ。時々あなたはあなたが望むものを手に入れません。
私にとっては、テーブルとフィールドに正確な内容で名前を付け、(私たちにとっては)明確なスペイン語で、空白なしでアッパーキャメルケースを使用すると常に役立ちます。
ユーザー名:NombreUsuario
姓名:ApellidoPaterno
2番目の姓:ApellidoMaterno
などなど
「データベース」を「SQL製品」と解釈すると、私の答えは「言及するには多すぎます。このテーマに関する本全体を書くことができます」です。幸いなことに、誰かが持っています。
私たちはJoeCelkoのSQLプログラミングスタイル(ISBN 978-0120887972)を使用しています。 SQLコード。」
このアプローチの利点は次のとおりです。
実際には、私たちは本の処方箋から逸脱しますが、驚くほどめったにありません。
テーブル名が主キー名および説明キーと一致する
私はつい最近、これに何年も同意した後、船を飛び越え、今ではすべてのテーブルに「ID」列があります。
はい、私は知っています、テーブルをリンクするとき、それは曖昧です!しかし、ProductIDをProductIDにリンクするのもそうです。では、なぜ余分な入力を行うのでしょうか。
この:
SELECT p.Name, o.Quantity FROM Products p, Orders o WHERE o.ProductID = p.ID
これよりわずかに優れています:
SELECT p.Name, o.Quantity FROM Products p, Orders o WHERE o.ProductID = p.ProductID
どちらもテーブルまたはエイリアスのプレフィックスが必要になることに注意してください。しかし、入力する回数がわずかに少ないだけでなく(説明的な名前が長い数十のテーブルに掛けると、データ集約型のアプリケーションですばやく加算されます)、すべての結合でどのテーブルが親テーブルであるかを簡単に知ることができます。クエリで8〜10個のテーブルを結合する場合、かなり役立ちます。
EMP_ID_CONV_FCTR_WTF_LOL_WAK_A_WAK_HU_HUのような怪物を積極的に奨励する略語の包括的な辞書など、ばかげた略語の規則は避けてください。このルールは、私が以前に見た実際の一連のガイドラインに触発されています。
すべてを文書化します。 wikiタイプのドキュメントはセットアップが簡単で、ソフトウェアは無料です。
最初にインターフェースを理解し、次にデータベースを設計するようにしてください。ほとんどの場合、使用するデータがどのように機能する必要があるかを理解してから、データベースを設計する方がはるかに優れています。ほとんどの悪いDB設計は、物事が前もってではなく進化するときに起こります。
次に、作業するデータベースの標準とバージョンを定義します。コード要素(ビュー、関数など)、データベースの命名の標準を定義します。列、テーブルの命名規則。列の型規則。コーディングテンプレート。
フィールドの標準データベースタイプまたは特注タイプを持つタイプをどのように定義するかを検討するのに時間を費やすのは、事前に整理するのに適しています。
ドキュメントの一部として、アプリケーションの禁止事項と推奨事項のリストが含まれています。これには、好みの嫌いな機能のカーソル、トリガーが含まれています。
定期的に確認してください。
最も重要な標準は次のとおりです。デフォルトではデータベースがありません。データベースがなければ(少なくともまだ)人生がはるかに楽だったプロジェクトのためにデータベースを手に入れる開発者が多すぎることに気づきました。これはツールボックス内の単なるツールであり、すべての問題が釘であるとは限りません。
データベースの不適切な使用は、貧血のドメインモデル、テストが不十分なコード、および不要なパフォーマンスの問題につながります。
MS-SQLでは、常にdbo。が所有するオブジェクトがあり、それらのオブジェクトへの呼び出しの前にdboを付けています。
私たちの開発者が、自分たちが誤って所有しているオブジェクトをなぜ呼び出せないのか疑問に思うことが何度もあります。
#5を除いて、あなたがそこに置いたほぼすべてに同意します。開発するシステムにはさまざまな機能領域があるため、テーブルとストアドプロシージャにプレフィックスを使用することがよくあります。そのため、テーブルとsprocに、どの領域に基づいてManagementStudioで適切にグループ化できるようにする識別子をプレフィックスとして付ける傾向があります。それらはに属します。
例:cjso_Users、cjso_Rolesの場合、routing_Users、routing_Rolesがあります。これはデータの複製のように聞こえるかもしれませんが、実際には2つの異なるユーザー/ロールテーブルはシステムの完全に別個の機能用です(cjsoは顧客ベースのeコマースアプリ用であり、ルーティングはルーティングを使用する従業員とディストリビューターを表しますシステム)。
私はテーブルの命名規則が好きです:
People Table
PEO_PersonID
PEO_FirstName
...
これは、大きなクエリをもう少し読みやすくするのに役立ちます。結合はもう少し意味があります:
Select * -- naughty!
From People
Join Orders on PEO_PersonID = ORD_PersonID
--...
命名規則ではなく、命名の一貫性だと思います。