Postgresql
Postgres DDL 和 DML 最佳實踐和編碼標準
是否有您可以分享和推薦的 Postgres DDL 和 DML/SQL 的最佳實踐或編碼/設計約定。
我正在尋找類似於Google程式的東西。
先感謝您。
像所有編碼標準一樣,每個項目都會有偏好。我並不是說你會喜歡我的偏好,但我會提供它們。請記住,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;
不是每個人都喜歡這種風格,但我們發現它易於閱讀、遵循和維護。
我要提出幾點:
- 如果可以,請避免使用內聯視圖。如果需要,請正式定義它們或使用 CTE。內聯視圖使維護變得更加困難,因為查詢的簡單結構和嚴格的順序被降級了。
- 有時需要子查詢,但出於同樣的原因,請盡量避免使用它們。
- 在決定是否使用
select *
命名列列表時,請考慮您是否期望返回命名類型。如果你這樣做,那select *
是最好的。否則通常你想避免select *
.- 如果您要使用儲存過程,請仔細考慮您的契約。除非您在兩者之間有某種服務發現框架,否則對這些介面的更改通常不像您希望的那麼容易。