# 数据库升级文档规范

- **当前数据库表结构版本**：`v1`

## 适用范围

- 当任务新增/修改 `.ai-specs\doc-sql\*.sql` 并导致数据库结构、字段、索引、约束、默认值或注释变化时，必须先读本文件。
- 当任务新增/修改 `.ai-specs\doc-dict\*.md` 并导致系统字典主数据或字典项变化时，必须先读本文件。
- 数据库升级 SQL 固定存放在 `.ai-transition\database-upgrade-doc`。
- 当前升级版本固定读取本文件中 `当前数据库表结构版本` 的值。

## 强制规则

- 升级 SQL 文件命名固定为 `<version>.sql`，例如 `v1.sql`、`v2.sql`、`v3.sql`。
- 当前数据库表结构版本声明为 `v1` 时，兼容变更 SQL 必须写入 `.ai-transition\database-upgrade-doc\v1.sql`。
- 默认版本文件为 `v1.sql`；不存在时，首次产生数据库结构变更必须创建。
- 修改 `.ai-specs\doc-sql\*.sql` 时，禁止只改文档；必须同步检查并补充当前版本 SQL 文件。
- 修改 `.ai-specs\doc-dict\*.md` 时，禁止只改文档；必须同步检查初始化数据和当前版本 SQL 文件。
- SQL 只记录从既有数据库升级到当前 `doc-sql` 目标结构所需的兼容变更，不重复粘贴完整建表基线。
- 同一次业务变更涉及多张表时，必须写在同一个当前版本 SQL 文件中，并按表分组。
- 修改字段名、类型、默认值、非空约束、唯一约束、普通索引、软硬删字段、注释时，都必须写对应升级 SQL。
- 新增/修改固定值域字典时，必须写入 `sys_dictionaries` 和 `sys_dictionary_details` 的幂等升级 SQL。
- 新增/修改动态值域字典时，必须至少写入 `sys_dictionaries` 的幂等升级 SQL；无固定值项时不写 `sys_dictionary_details`。
- 仅修改文档表述且不改变实际落库语义时，可以不写 SQL，但必须在最终说明中明确原因。

## SQL 要求

- SQL 默认使用 `PostgreSQL` 写法。
- 优先使用 `ALTER TABLE`、`CREATE INDEX`、`DROP INDEX`、`COMMENT ON TABLE`、`COMMENT ON COLUMN`、`UPDATE` 回填语句。
- 数据类升级 SQL 必须幂等，禁止裸 `INSERT`；必须使用 `WHERE NOT EXISTS`、`UPDATE ... FROM` 等方式兼容重复执行。
- 新增 `NOT NULL` 字段必须先给默认值或先回填历史数据，再追加 `NOT NULL` 约束。
- 新增唯一约束或唯一索引前，必须考虑历史重复数据；不能直接写会必然失败的 SQL。
- 索引创建应使用项目统一命名：唯一索引 `uk_<table_name>_<field>`，普通索引 `idx_<table_name>_<field>`。
- 字典主表重复判断固定使用 `sys_dictionaries.type`。
- 字典明细重复判断固定使用 `sys_dictionary_details.sys_dictionary_id + value`。
- 固定值域字典项变更时，先 `UPDATE` 已有 `value` 的 `label`、`sort`、`status`、`updated_at` 等展示字段，再 `INSERT` 缺失项。
- 字典主表或明细表命中已存在数据时，若表包含 `deleted_at`，恢复启用数据必须同步置空 `deleted_at`。
- 固定值域字典项废弃时，优先将 `status` 改为 `false`，禁止直接删除历史值项。
- 禁止混入 `MySQL` 方言，例如反引号、`AUTO_INCREMENT`、`ENGINE=InnoDB`、行内 `COMMENT`。

## 文件格式

```sql
-- <业务说明> / <表名> / <YYYY-MM-DD>

ALTER TABLE <table_name>
  ADD COLUMN <field_name> <type>;

COMMENT ON COLUMN <table_name>.<field_name> IS '<字段说明>';

CREATE INDEX idx_<table_name>_<field_name> ON <table_name> (<field_name>);
```

## 联动关系

- 改 `doc-sql`：同步改 `Model`、`Service`、`initialize/gorm_biz.go`，并补当前版本升级 SQL。
- 改 `doc-dict`：同步改代码枚举/校验/展示逻辑、`source/system` 初始化数据，并补当前版本升级 SQL。
- 改当前版本升级 SQL：同步确认 `doc-sql`、`Model`、迁移注册与业务读写逻辑一致。
- 版本升级：先修改本文件的 `当前数据库表结构版本`，再在 `.ai-transition\database-upgrade-doc` 新增对应 `<version>.sql`。
