web-dev-qa-db-ja.com

Postgres DDLおよびDMLのベストプラクティスとコーディング標準

PostgresのDDLとDML/SQLの両方について、共有および推奨できるベストプラクティスまたはコーディング/設計規則はありますか?.

私はGoogleが programming に対して持っているものと同様のものを探しています。

前もって感謝します。

5
Edmon

すべてのコーディング標準と同様に、すべてのプロジェクトには好みがあります。私の好みを気に入ってくれるとは言っていませんが、提供します。 LedgerSMB は、コードの半分がSQLとなるモデルに向かっているため、これらについて検討する必要があったことを覚えておいてください。

私たちが最初に行ったのは、DDLは人間のレビュー担当者ではなく、自動ドキュメント化ツール用にドキュメント化する必要があることを決定することでした。ヒューマンレビュアーのルート(ドキュメントを減らす)を使用する場合は、次のようにします。

CREATE TABLE asset_item (
    id serial not null unique, -- internal id
    tag text primary key, -- accounting control code
    description text not null,
...
);

それは素晴らしいことですが、それは、人々があなたが伝えたいことを理解するためにDDLファイルを読む必要があることを意味します。 autodoc文書化ツールのルートを使用すると、別の結果が得られます。

CREATE TABLE asset_item (
    id serial not null unique,
    tag text primary key,
    description text not null,
...
);

COMMENT ON TABLE asset_item IS $$ This table stores the fixed asset items.$$;
COMMENT ON COLUMN  asset_item.id IS $$Internal id, used for joins$$;
COMMENT ON COLUMN asset_item.tag IS $$Accounting control code$$;

これにより、大規模なプロジェクトで非常に役立つ一般的なドキュメントツールを通じてコメントを利用できるようになります。大きな制限は、コメントが定義に従う必要があることです。

DMLの場合、通常はクエリを正当化し、一方に動詞を、もう一方に条件または識別子を並べます。例は次のとおりです。

   SELECT ai.id, ai.tag, ai.description, coalesce(ai.start_depreciation, ai.purchase_date),
          adm.short_name, ai.usable_life
           - months_passed(coalesce(ai.start_depreciation, ai.purchase_date),
                                  coalesce(max(r.report_date),
                                           ai.start_depreciation,
                                           ai.purchase_date))/ 12,
          ai.purchase_value - ai.salvage_value, ai.salvage_value, max(r.report_date),
          sum(rl.amount), ai.purchase_value - sum(rl.amount)
     FROM asset_item ai
     JOIN asset_class ac ON (ai.asset_class_id = ac.id)
     JOIN asset_dep_method adm ON (adm.id = ac.method)
LEFT JOIN asset_report_line rl ON (ai.id = rl.asset_id)
LEFT JOIN asset_report r on (rl.report_id = r.id)
    WHERE r.id IS NULL OR r.approved_at IS NOT NULL
 GROUP BY ai.id, ai.tag, ai.description, ai.start_depreciation, ai.purchase_date,
          adm.short_name, ai.usable_life, ai.purchase_value, salvage_value
   HAVING (NOT 2 = ANY(as_array(r.report_class)))
          AND (NOT 4 = ANY(as_array(r.report_class)))
          OR max(r.report_class) IS NULL
 ORDER BY ai.id, ai.tag, ai.description;

誰もがこのスタイルを気に入っているわけではありませんが、読みやすく、フォローしやすく、維持しやすいと感じています。

私が指摘するいくつかの大きなポイント:

  1. 可能であれば、インラインビューを避けます。それらを正式に定義するか、必要に応じてCTEを使用します。インラインビューでは、クエリの単純な構造と厳密な順序が低下するため、メンテナンスが難しくなります。

  2. 時々サブクエリが必要ですが、同じ理由でできる限りそれらを避けてください。

  3. select *を使用するか、名前付き列リストを使用するかを決定するときは、名前付き型を戻すかどうかを検討してください。その場合は、select *が推奨されます。それ以外の場合、通常はselect *を避けます。

  4. ストアドプロシージャを使用する場合は、契約を慎重に検討してください。これらのインターフェイスへの変更は、間にサービス検出フレームワークを配置しない限り、希望するほど簡単ではありません。

9
Chris Travers
  1. すべての識別子を作成snake_case

  2. 識別子にキーワードを使用しないでください。

  3. 列名のあいまいさを回避するために、関数のパラメーターに先頭に下線を付けます。

  4. PL/pgSQLでの割り当てには、:=の代わりに=を使用します(どちらも使用できますが、:=は公式です)

  5. 識別子の最大長は63バイトです。 PostgreSQLは長すぎると警告なしに切り捨てるので、63バイト(63 ASCII文字)より長くしないでください。

6
Neil McGuigan