Files
xuanzhi-service/server/.ai-specs/sys-specs/business-table-spec.md

5.6 KiB
Raw Permalink Blame History

业务表 SQL 规范

适用范围

  • 当任务是新增/修改 .ai-specs/doc-sql/*.sql 时,先读本文件。
  • 当前项目关系型数据库默认是 PostgreSQLdoc-sql 文件必须直接使用 PostgreSQL 写法。
  • 涉及状态、类型、级别、来源、模式、分类等值域字段时,必须先读 .ai-specs/sys-specs/business-dictionary-spec.md,并先补对应的 .ai-specs/doc-dict/<dict-code>.md;固定值域字典补值项定义,动态值域字典补说明文档。

强制输出

  • 文档路径固定:.ai-specs/doc-sql/<table_name>.sql
  • 文件必须是可执行 SQL不再使用 Markdown 包裹 SQL。
  • 文件头部必须使用 SQL 注释声明基本信息,注释后直接输出 SQL 主体。
  • 基本信息固定顺序:# 标题## 基本信息模块表名模型迁移接入删除策略 → 按需补 字典 行 → 职责
  • 每张业务表必须显式声明删除策略,只允许两种:软删表硬删表
  • 软删表Model 应使用 global.GVA_MODEL 或显式包含 DeletedAtdoc-sql 必须包含 deleted_at 字段和对应索引
  • 硬删表Model 不应因沿用默认基类而隐式带出 DeletedAtdoc-sql 不写 deleted_at
  • 硬删表 建模时禁止直接嵌入 global.GVA_MODEL;应显式定义 IDCreatedAtUpdatedAt,或使用不包含 DeletedAt 的硬删基类
  • 硬删表Service 删除逻辑必须执行物理删除;禁止依赖 GORM 软删行为或查询侧隐式过滤 deleted_at
  • 硬删表 如果后续需要保留删除痕迹,必须先把 doc-sql 删除策略改为 软删表,再同步修改 Model、索引和删除逻辑
  • doc-sql 声明为 硬删表 时,后续生成 model/<module>/*.go 必须按 doc-sql 字段逐项建模;即使项目默认模型带软删,也不得自动补 DeletedAt
  • doc-sql 声明为 硬删表 时,后续生成 initialize/gorm_biz.go 迁移只注册该硬删模型;迁移结果不得比 doc-sql 多出 deleted_at
  • doc-sql 声明为 硬删表 时,唯一索引直接按业务唯一性生成;不得为了兼容软删把 deleted_at 拼入唯一索引
  • book 模块当前所有 doc-sql/book*.sql 均按 硬删表 处理;生成 model/book/*.go 时必须使用硬删建模规则
  • 有字典字段时,每个字典单独占一行:-- <字段中文名>字典:<dict-code>
  • SQL 主体固定按这个顺序组织:CREATE TABLECOMMENT ON TABLECOMMENT ON COLUMNCREATE UNIQUE INDEX / CREATE INDEX
  • 表名、字段名、索引名统一使用 snake_case
  • 唯一索引命名固定:uk_<table_name>_<field>
  • 普通索引命名固定:idx_<table_name>_<field>
  • 字典字段只存字典项 Value,禁止存 Label
  • 固定值域字典 字段如果默认值来自字典,直接写稳定字典项 Value
  • 动态值域字典 字段在 doc-sql 中只表达字段本身的结构约束、是否必填和索引;禁止伪造默认值、伪造固定值项或伪造 CHECK IN (...)
  • 文件只写已确认字段、约束、索引;禁止再补 字段设计索引设计关联关系删除与兼容自检 等重复章节
  • 仅修改 SQL 注释说明且不改变字段、约束、索引、默认值、注释等落库语义时,不需要补数据库升级 SQL。

PostgreSQL 写法

  • 主键自增优先写 bigserial PRIMARY KEY
  • 时间字段优先写 timestamp with time zone
  • 软删表 的软删字段统一写 deleted_at timestamp with time zone
  • 注释统一写 COMMENT ON TABLECOMMENT ON COLUMN
  • 索引统一单独写 CREATE UNIQUE INDEXCREATE INDEX
  • 禁止混入 AUTO_INCREMENT、反引号、ENGINE=InnoDB、行内 COMMENTUNIQUE KEYKEY ...MySQL 方言

输出模板

-- # <表中文名>
--
-- ## 基本信息
--
-- 模块:<module>
-- 表名:<table_name>
-- 模型model/<module>/<file>.go
-- 迁移接入initialize/gorm_biz.go
-- 删除策略:硬删表
-- <字段中文名>字典:<dict-code>
-- 职责:<一句话职责>

CREATE TABLE <table_name> (
  id bigserial PRIMARY KEY,
  created_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
  <field_1> <type> <constraint>,
  <field_2> <type>
);

COMMENT ON TABLE <table_name> IS '<表中文名>';
COMMENT ON COLUMN <table_name>.id IS '主键';
COMMENT ON COLUMN <table_name>.created_at IS '创建时间';
COMMENT ON COLUMN <table_name>.updated_at IS '更新时间';
COMMENT ON COLUMN <table_name>.<field_1> IS '<字段说明>';
COMMENT ON COLUMN <table_name>.<field_2> IS '<字段说明>';

CREATE UNIQUE INDEX uk_<table_name>_<field_1> ON <table_name> (<field_1>);
CREATE INDEX idx_<table_name>_<field_2> ON <table_name> (<field_2>);
  • 软删表 参考上面的硬删模板,在 updated_at 后追加 deleted_at timestamp with time zone,并同步补 COMMENT ON COLUMN <table_name>.deleted_at IS '删除时间';CREATE INDEX idx_<table_name>_deleted_at ON <table_name> (deleted_at);
  • 硬删表 按模板直接输出,不追加 deleted_at
  • 没有字典字段,就删除对应“字典”注释行
  • 没有唯一索引或普通索引,就删除对应 SQL 行
  • 如果字段默认值来自 固定值域字典,直接写字典项 Value,例如 DEFAULT 'draft'
  • 如果字段引用 动态值域字典,就删除默认值示例,按业务真实规则只保留结构约束和索引

复刻目标

  • 只看本文件,应能直接写出类似 .ai-specs/doc-sql/book_author.sql 的文件
  • 先定字典,再写 doc-sql,再进入 Model、迁移和业务代码