Postgres DDL 和 DML 最佳实践和编码标准

Edm*_*mon 5 postgresql best-practices dml ddl

是否有您可以共享和推荐的 Postgres DDL 和 DML/SQL 的最佳实践或编码/设计约定。

我正在寻找类似于谷歌编程的东西

先感谢您。

Chr*_*ers 9

像所有编码标准一样,每个项目都会有偏好。我并不是说你会喜欢我的偏好,但我会提供它们。请记住,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,
...
);
Run Code Online (Sandbox Code Playgroud)

这很好,但这意味着人们必须阅读您的 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$$;
Run Code Online (Sandbox Code Playgroud)

这使得可以通过通用文档工具获得注释,这在大型项目中非常有用。最大的限制是评论必须遵循定义。

对于 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;
Run Code Online (Sandbox Code Playgroud)

并非每个人都喜欢这种风格,但我们发现它易于阅读、遵循和维护。

我要说的几个要点:

  1. 如果可以,请避免内联视图。如果需要,请正式定义它们或使用 CTE。内联视图使维护变得更加困难,因为查询的简单结构和严格的顺序被降级了。

  2. 有时需要子查询,但出于同样的原因尽量避免它们。

  3. 在决定是使用select *命名列列表还是使用命名列列表时,请考虑您是否希望返回命名类型。如果你这样做,那么select *是可取的。否则通常你想避免select *.

  4. 如果您打算使用存储过程,请仔细考虑您的合同。除非您有某种服务发现框架,否则对这些接口的更改通常并不像您希望的那么容易。


Nei*_*gan 6

  1. 制作所有标识符 snake_case

  2. 不要使用关键字作为标识符。

  3. 使用前导下划线命名函数参数,以避免列名产生歧义。

  4. 使用:=的,而不是在PL / pgSQL的分配=(两者都是允许的,但是:=是官方)

  5. 最大标识符长度为 63 字节。如果太长,PostgreSQL 会自动截断,所以不要让它们超过 63 个字节(63 个 ASCII 字符)。