web-dev-qa-db-ja.com

最も有用なデータベース標準のいくつかは何ですか?

私にはいくつかのアイデアがあり、そのいくつかは時間の経過とともに蓄積されてきましたが、データベースをモデル化するときに何がスムーズに進むのかを本当に知りたいです。

  1. テーブル名が主キー名および説明キーと一致する
  2. スキーマは機能領域ごとです
  3. 可能な場合は複合主キーを避けます(一意の制約を使用します)
  4. キャメルケースのテーブル名とフィールド名
  5. テーブルの前にtbl_を付けたり、procの前にSP_を付けたりしないでください(ハンガリアン記法なし)
  6. OLTPデータベースは少なくともBCNF/4NFである必要があります
44
Raj More

全員の入力を1つのリストにまとめます。

命名基準

  • スキーマは機能領域(製品、注文、出荷)によって名前が付けられています
  • ハンガリアン記法なし:オブジェクト名に型名がありません(strFirstNameなし)
  • オブジェクト名に登録済みのキーワードを使用しないでください
  • オブジェクト名にスペースや特殊文字を使用しないでください(許可されるのはアルファ番号+アンダースコアのみです)
  • 自然な方法でオブジェクトに名前を付けます(NameFirstではなくFirstName)
  • テーブル名は、主キー名および説明フィールド(SalesType – SalesTypeId、SalesTypeDescription)と一致する必要があります
  • Tbl_またはsp_のプレフィックスを付けないでください
  • オブジェクト名による名前コード(CustomerSearch、CustomerGetBalance)
  • キャメルケースデータベースオブジェクト名
  • 列名は単数である必要があります
  • テーブル名は複数形にすることができます
  • すべての制約にビジネス名を付ける(MustEnterFirstName)

データ型

  • テーブル全体で同じ変数タイプを使用します(郵便番号– 1つのテーブルで数値を使用し、別のテーブルでvarcharを使用することはお勧めできません)
  • 多国籍企業にいつ行くかわからない顧客情報(名前、住所)などにはnNVarCharを使用してください

コード内

  • 常に大文字のキーワード
  • 暗黙の結合を使用しないでください(コンマ構文)-常に明示的なINNER JOIN/OUTERJOINを使用してください
  • 1行に1つのJOIN
  • 1行に1つのWHERE句
  • ループなし–セットベースのロジックに置き換えます
  • エイリアスには、A、B、Cではなく短い形式のテーブル名を使用してください
  • 頼りになるものがない限り、トリガーを避けてください
  • 疫病のようなカーソルは避けてください( http://www.sqlservercentral.com/articles/T-SQL/66097/ を読んでください)

ドキュメント

  • データベース図を作成する
  • データディクショナリを作成する

正規化と参照整合性

  • 可能な限り単一列の主キーを使用します。必要に応じて、一意の制約を使用します。
  • 参照整合性は常に適用されます
  • ON DELETECASCADEを避ける
  • OLTPは少なくとも4NFである必要があります
  • すべての1対多の関係を潜在的な多対多の関係として評価します
  • ユーザーが生成しない主キー
  • 更新ベースではなく挿入ベースのモデルを構築する
  • PKからFKは同じ名前である必要があります(Employee.EmployeeIdはEmployeeSalary.EmployeeIdと同じフィールドです)
  • 二重結合がある場合を除きます(Person.PersonIdはPersonRelation.PersonId_ParentおよびPersonRelation.PersonId_Childに結合します)

メンテナンス:定期的なスクリプトを実行して検索

  • テーブルのないスキーマ
  • 孤立したレコード
  • 主キーのないテーブル
  • インデックスのないテーブル
  • 非決定論的UDF
  • バックアップ、バックアップ、バックアップ

良くなる

  • 一貫性を保つ
  • エラーを修正
  • Joe CelkoのSQLプログラミングスタイル(ISBN 978-0120887972)を読む
11
Raj More
  • たとえば、Personに3つのストアドプロシージャがある場合は、同じプレフィックスを持つ同様にターゲットにされたストアドプロシージャに名前を付けます。そうすれば、人のすべてが1つの場所にグループ化され、すべてのprocを調べて見つける必要がなく、簡単に見つけることができます。
    • PersonUpdate
    • PersonDelete
    • PersonCreate
  • 関連データを持つテーブルのグループがある場合は、テーブルに対して同様のことを行います。例えば:
    • InvoiceHeaders
    • InvoiceLines
    • InvoiceLineDetails
  • データベース内にスキーマのオプションがある場合は、それらを使用します。見るのはずっといいです:
    • Invoice.Header
    • Invoice.Line.Items
    • Invoice.Line.Item.Details
    • Person.Update
    • Person.Delete
    • Person.Create
  • その目標を達成するための他の合理的なアプローチがない限り、トリガーを使用しないでください。
  • フィールド名に意味のあるプレフィックスを付けると、誰かが説明しなくても、フィールド名がどのテーブルからのものであるかがわかります。そうすれば、参照されているフィールド名を見ると、それがどのテーブルからのものであるかを簡単に知ることができます。
  • 同様のデータを含むフィールドには一貫したデータ型を使用します。つまり、電話番号を数値として1つのテーブルに格納し、varcharを別のテーブルに格納しないでください。実際、それを数値として保存しないでください。負の電話番号に出くわした場合、私は怒ってしまいます。
  • テーブル/フィールド名にスペースやその他のあいまいな文字を使用しないでください。それらは完全に英数字である必要があります-または、アンダースコアを除いて完全にアルファベットである必要があります。現在、テーブル名とフィールド名にスペース、疑問符、感嘆符が含まれている継承システムに取り組んでいます。毎日デザイナーを殺したくなります!
  • オブジェクト名として構文キーワードを使用しないでください。構文キーワードからデータを取得しようとすると頭痛の種になります。オブジェクト名を[index]としてラップする必要はありません。これは、入力する必要がなかった2つの不要な文字です。
19
BenAlabaster

私がまだ言及していないことの1つ:

データベースキーワードをオブジェクト名として使用しないでください。あなたはそれらを使用するたびにそれらを修飾する必要はありません

作成時にスペルを間違えた場合は、気づいたらすぐに修正してください。このテーブルでは、UserNameは実際にはUsernmaeであることを覚えておく必要はありません。それに対して書かれたコードがあまりない場合は、修正するのがはるかに簡単です。

暗黙の結合(コンマ構文)は使用せず、常に結合を指定してください。

13
HLGEM

Oracleの私の標準は次のとおりです。

  • キーワードは常に大文字です。
  • データベースオブジェクト名は常に小文字です。
  • アンダースコアはスペースを置き換えます(つまり、SQL Serverなどで一般的なキャメルケースの規則はありません)。
  • 主キーはほとんどの場合「id」という名前になります。
  • 参照整合性が適用されます。
  • 整数値(テーブルIDを含む)は通常、常にNUMBER(19,0)になります。これは、これが64ビットの符号付き整数に収まるため、より厄介なBigIntegerの代わりにJava long型を使用できるようになるためです。
  • 一部の列名に「_number」を追加するという誤った呼び方にもかかわらず、そのような列のタイプは、数値タイプではなくVARCHAR2になります。数値タイプは、算術演算を行う主キーと列用に予約されています。
  • 私は常に技術的な主キーを使用します。そして
  • 各テーブルには、キー生成のための独自のシーケンスがあります。そのシーケンスの名前は_seqになります。

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つのフィールドに分割します。

10
cletus
  • すべての制約に名前を付ける
9
Edward Shtern

データベースを定期的にバックアップすることを忘れないでください。

8
Stan R.

データベースが特定のアプリケーション用である場合は、バージョンテーブルを用意して、データベースのリリースをコードのリリースと照合できるようにします(他の理由もあります)。

7
RichardOD
  1. フィールド名にタイプ名を使用しないでください。年配の人は、lpszFieldNameの古いMS標準とそれに続く愚かさを覚えているでしょう。

  2. 通常の言語規則に従った説明的なフィールド名を使用します。たとえば、「NameFirst」ではなく「FirstName」

  3. フィールド名の各単語は大文字です

  4. アンダースコアなし

  5. 「インデックス」などの通常のキーワードは使用しないでください

  6. オブジェクトタイプの前にANYTHINGを付けないでください。たとえば、tblCustomersやspCustomersGetは使用しません。これらは適切なソートを可能にせず、ゼロ値を提供します。

  7. スキーマを使用して、データベースの個別の領域を定義します。 sales.Customersやhr.Employeesなど。これにより、人々が使用するほとんどのプレフィックスが削除されます。

  8. あらゆる種類のループは、疑いを持って表示する必要があります。通常、より良いセットベースの方法があります。

  9. 複雑な結合にはビューを使用します。

  10. 可能な場合は、複雑な結合を避けてください。 CustomerPhoneNumbersテーブルがある方がより魅力的かもしれません。しかし正直なところ、実際にいくつの電話番号を保存する必要がありますか?顧客テーブルにフィールドを追加するだけです。 DBクエリが高速になり、理解しやすくなります。

  11. 1つのテーブルがフィールド「EmployeeId」を呼び出す場合、それを参照するすべての単一テーブルはその名前を使用する必要があります。拡張テーブルにあるという理由だけでCustomerServiceRepIdを呼び出す必要はありません。

  12. ほとんどすべてのテーブルの末尾に「s」が付いています。例:顧客、注文など。結局のところ、テーブルには多くのレコードが保持されています。

  13. 分析ツールを使用して、クエリ、インデックス、および外部キーの関係を評価します。あなたのために生成されるかもしれないものでさえ。驚かれるかもしれません。

  14. 多対多の関係をサポートするリンクテーブルには、名前に両方のリンクテーブルがあります。たとえば、SchoolsGradesです。テーブル名で何をするのかを簡単に見分けることができます。

  15. 一貫性を保つ。慣例に従って1つのパスを開始する場合は、前のすべての作業をリファクタリングする意思がない限り、途中で馬を変更しないでください。これは、混乱と膨大な量のやり直しを引き起こす結果となる「もしも素晴らしいと思いませんか」というアイデアにブレーキをかけるはずです。

  16. 入力する前によく考えてください。そのテーブル、フィールド、sproc、またはビューが本当に必要ですか?他の場所でカバーされていませんか?追加する前にコンセンサスを取得してください。そして、何らかの理由でそれを取り出さなければならない場合は、最初にチームに相談してください。私は、DBAが開発者に関係なく毎日最新の変更を加える場所に行ってきました。これは面白くない。

7
NotMe

私は常にフィールド名のタイプ(「sFirstName」、「sLastName」、または「iEmployeeID」)を使用しないようにしています。それらは最初は一致しますが、何かが変更されると同期がとれなくなり、依存オブジェクトも変更する必要があるため、後でそれらの名前を変更することは大きな頭痛の種です。

IntellisenseとGUIツールを使用すると、列のタイプを簡単に見つけることができるので、これは必要ないと思います。

6
SqlRyan

すべてのvarchar/nvarcharの選択が適切であることを確認してください。

すべてのNULL可能列の選択が適切であることを確認します-可能な場合はNULL可能列を避けます-NULLを許可することは正当な位置である必要があります。

ここでの提案から使用する可能性のある他のルールに関係なく、データベースにストアドプロシージャを作成します。このストアドプロシージャを定期的に実行して、使用しているルールまたは標準のシステムの状態を判断します(これの一部は小さなSQLです) -サーバー固有):

  • 何らかの理由でDBMSシステムの参照整合性を使用できない場合は、孤立したレコードを探します(私のシステムには、プロセスのテーブルとテストのテーブルがあります。したがって、system_health SP私は一方向のFK関係しかないため、テストなしのプロセス)

  • 空のスキーマを探す

  • 主キーのないテーブルを探す

  • インデックスのないテーブルを探す

  • ドキュメントのないデータベースオブジェクトを探します(SQL Server拡張プロパティを使用してドキュメントをデータベースに配置します-このドキュメントはのように細かくすることができます)。

  • システム固有の問題を探します-アーカイブする必要のあるテーブル、通常の月次または日次処理の一部ではない例外、デフォルトの有無にかかわらず特定の一般的な列名(たとえば、CreateDate)。

  • 非決定論的UDFを探す

  • TODOコメントを探して、DB内のコードに未テストまたはプレリリースのコードが含まれていないことを確認します。

これらすべてを自動化して、システムの状態の全体像を把握できます。

5
Cade Roux

WITH句は、クエリを管理可能な部分に分割するのに役立ちます。

また、クエリの実行プランの効率化にも役立ちます。

5
Tom Hubbard

誰もがSQLクエリ(ビュー、ストアドプロシージャなど)を同じ基本形式で記述します。これは、今後の開発/保守作業に本当に役立ちます。

3
lance

一貫した命名基準。全員が同じページにいて、同じ形式(キャメルケース、特定のプレフィックスなど)を使用すると、システムを正確に維持できるようになります。

3
Marshall

いくつかの好き嫌い。

私の意見では、プレフィックスはあらゆる面で恐ろしいものです。私は現在、テーブルにプレフィックスが付いており、テーブル内の列に2文字のテーブル名の頭字語が付​​いているシステムで作業しています。頭字語が論理的ではないため、このデータベースでの作業に毎日少なくとも30分を浪費しています。接頭辞を付けて何かを示したい場合は、代わりにスキーマ所有者を使用してください。

プロジェクトの開始からNVarcharを使用するのは、テキストデータが多言語文字をサポートする必要があるというわずかなヒントさえある場合です。将来の計画と思考が不足しているために大規模なデータベースをアップグレードすることは、苦痛であり、時間を浪費します。

Where句内の各条件を読みやすくするために新しい行に分割します(括弧で囲まれてタブで囲まれたステートメントではなく)。これは私にとって重要な標準だと思います。

私はある会社で働いていました。そこでは、パラメーターまたは変数の宣言を実行するときは常にコンマを行の先頭に配置する必要があるという基準がありました。これは明らかにそれをより読みやすくしました、しかし私はそれが完全な悪夢であるとわかりました。

3
Peter

表形式の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をクエリに結合しますか?」構造の適用や更新にそれほど時間はかからず、多くの時間を節約できることがわかりました。コードを書くよりも読むことに多くの時間を費やしています。

2
Carl Manaster

優れたデータベース設計と正規化

2
Lance Roberts
  • テーブルには、単数、小文字、アンダースコア、プレフィックスなしで名前が付けられます
  • フィールドも小文字、アンダースコアなし、プレフィックスなし
  • 「st_」で始まるストアドプロシージャ(適切にソートされます)
  • テーブルのように扱われるビューにはプレフィックスがありません
  • 特別レポートなどのために作成されたビューには、「v」プレフィックスが付いています
  • パフォーマンスのために作成されたインデックス付きビューには、「ixv」プレフィックスが付いています
  • すべてのインデックスには意図的な名前が付いています(自動命名なし)
  • 代理キーのintIDENTITYよりもuniqueidentifier(順次増分)を強く優先します
  • VARCHAR/NVARCHARフィールドを人為的に100または255に制限しないでください。息をのむ余地を与えてください。これは1980年代ではなく、フィールドは最大長までパディングされて保存されません。
  • 3NF最低基準
  • 列レベルの外部キーよりもテーブルの結合を優先します。システムが時間の経過とともに成長するにつれて、多くの1:mの仮定に挑戦します。
  • 主キーとして、自然キーではなく、常に代理キーを使用してください。 すべて「自然」キー(SSN、ユーザー名、電話番号、内部コードなど)に関する仮定は最終的には異議を唱えられます。
2
richardtallent

3NFまたはBCNFへの正規化(詳細については この質問 )に加えて、次のことが役立つことがわかりました。

  • テーブルに複数名詞として名前を付ける
  • 列にSigularという名前を付ける

したがって、「People」テーブルには「PersonID」列があります。

  • 3NFまたはBCNFのルールが引き続き適用される限り、複合キーに問題はありません。多くの場合(「多対多」の場合など)、これは完全に望ましいことです。
  • 列名でテーブル名を繰り返さないでください。 peoplePersonIDは、とにかくtable.columnとして記述した方が適切であり、はるかに読みやすく、したがって自己文書化されます。 People.PersonIDは、少なくとも私にとっては優れています。
  • ON DELETE CASCADEは慎重に使用する必要があります。
  • NULLは、不明または適用できないという2つのことのいずれかを意味することに注意してください。
  • NULLは結合に興味深い影響を与えることにも注意してください。したがって、LEFT、RIGHT、およびFULLの外部結合を練習してください。
2
Alan

他のいくつかの(小さいながらも)コメントは壁に投げつけます...

SQL Serverデータベーススキーマは、テーブルとストアドプロシージャの整理、およびセキュリティの制御の両方に役立ちます。

すべてのトランザクションテーブルは、常に誰がいつレコードを作成したかを追跡し、レコードを別々の列で更新​​する必要があります。将来の監査の課題につながる可能性のある「更新日」を単に使用した実装を見てきました。

オフライン/同期要件のあるプロジェクトのすべての行の行識別子にGUIDを使用します。

2
Cody C

私はここで他の人と同じ慣習をたくさん守っていますが、まだ言われていないことをいくつか言いたかったのです。

テーブルに複数の名前が好きか単数の名前が好きかに関わらず、一貫性を保ってください。どちらか一方を選択しますが、両方を使用しないでください。

テーブルの主キーの名前はテーブルと同じで、接尾辞は_PKです。外部キーの名前は対応する主キーと同じですが、接尾辞は_FKです。たとえば、Productテーブルの主キーはProduct_PKと呼ばれます。 Orderテーブルでは、対応する外部キーはProduct_FKです。私はこの習慣を私の別のDBAの友人から拾い上げました、そして今のところ私はそれが好きです。

INSERT INTO ... SELECTを実行するときは常に、SELECT部分​​のすべての列にエイリアスを付けて、INSERT INTO部分の列の名前と一致させ、保守と一致の確認を容易にします。

1
Scott

13-クエリを評価する

それは本当だ。時々あなたはあなたが望むものを手に入れません。

私にとっては、テーブルとフィールドに正確な内容で名前を付け、(私たちにとっては)明確なスペイン語で、空白なしでアッパーキャメルケースを使用すると常に役立ちます。

ユーザー名:NombreUsuario

姓名:ApellidoPaterno

2番目の姓:ApellidoMaterno

などなど

1
Broken_Window
1
A-K

「データベース」を「SQL製品」と解釈すると、私の答えは「言及するには多すぎます。このテーマに関する本全体を書くことができます」です。幸いなことに、誰かが持っています。

私たちはJoeCelkoのSQLプログラミングスタイル(ISBN 978-0120887972)を使用しています。 SQLコード。」

このアプローチの利点は次のとおりです。

  • 男は私よりもこの種のことをよく知っています(SQLヒューリスティックに関する別の本はありますか?!);
  • 作業はすでに完了しています。チームの誰かに本を渡して読んだり参照したりすることができます。
  • 誰かが私のコーディングスタイルを気に入らなければ、私は他の誰かを責めることができます。
  • 私は最近、SO別のCelkoの本を推薦することで、たくさんの担当者を獲得しました:)

実際には、私たちは本の処方箋から逸脱しますが、驚くほどめったにありません。

1
onedaywhen

テーブル名が主キー名および説明キーと一致する

私はつい最近、これに何年も同意した後、船を飛び越え、今ではすべてのテーブルに「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個のテーブルを結合する場合、かなり役立ちます。

1
Neil N

EMP_ID_CONV_FCTR_WTF_LOL_WAK_A_WAK_HU_HUのような怪物を積極的に奨励する略語の包括的な辞書など、ばかげた略語の規則は避けてください。このルールは、私が以前に見た実際の一連のガイドラインに触発されています。

1
MatthewMartin

すべてを文書化します。 wikiタイプのドキュメントはセットアップが簡単で、ソフトウェアは無料です。

最初にインターフェースを理解し、次にデータベースを設計するようにしてください。ほとんどの場合、使用するデータがどのように機能する必要があるかを理解してから、データベースを設計する方がはるかに優れています。ほとんどの悪いDB設計は、物事が前もってではなく進化するときに起こります。

次に、作業するデータベースの標準とバージョンを定義します。コード要素(ビュー、関数など)、データベースの命名の標準を定義します。列、テーブルの命名規則。列の型規則。コーディングテンプレート。

フィールドの標準データベースタイプまたは特注タイプを持つタイプをどのように定義するかを検討するのに時間を費やすのは、事前に整理するのに適しています。

ドキュメントの一部として、アプリケーションの禁止事項と推奨事項のリストが含まれています。これには、好みの嫌いな機能のカーソル、トリガーが含まれています。

定期的に確認してください。

1
u07ch

最も重要な標準は次のとおりです。デフォルトではデータベースがありません。データベースがなければ(少なくともまだ)人生がはるかに楽だったプロジェクトのためにデータベースを手に入れる開発者が多すぎることに気づきました。これはツールボックス内の単なるツールであり、すべての問題が釘であるとは限りません。

データベースの不適切な使用は、貧血のドメインモデル、テストが不十分なコード、および不要なパフォーマンスの問題につながります。

1

MS-SQLでは、常にdbo。が所有するオブジェクトがあり、それらのオブジェクトへの呼び出しの前にdboを付けています。

私たちの開発者が、自分たちが誤って所有しているオブジェクトをなぜ呼び出せないのか疑問に思うことが何度もあります。

1
ScottE

#5を除いて、あなたがそこに置いたほぼすべてに同意します。開発するシステムにはさまざまな機能領域があるため、テーブルとストアドプロシージャにプレフィックスを使用することがよくあります。そのため、テーブルとsprocに、どの領域に基づいてManagementStudioで適切にグループ化できるようにする識別子をプレフィックスとして付ける傾向があります。それらはに属します。

例:cjso_Users、cjso_Rolesの場合、routing_Users、routing_Rolesがあります。これはデータの複製のように聞こえるかもしれませんが、実際には2つの異なるユーザー/ロールテーブルはシステムの完全に別個の機能用です(cjsoは顧客ベースのeコマースアプリ用であり、ルーティングはルーティングを使用する従業員とディストリビューターを表しますシステム)。

0
TheTXI

私はテーブルの命名規則が好きです:

People Table
PEO_PersonID
PEO_FirstName 
...

これは、大きなクエリをもう少し読みやすくするのに役立ちます。結合はもう少し意味があります:

Select * -- naughty!
From People
Join Orders on PEO_PersonID = ORD_PersonID
--...

命名規則ではなく、命名の一貫性だと思います。

0
Pondidum