# DB 契约 — 数据库命名与使用规则

## 1. 基本原则

1. 默认使用 `InnoDB`、`utf8mb4` 和 `utf8mb4_unicode_ci`。
2. 数据库、表、字段、索引只使用小写英文字母、数字和下划线。
3. 命名必须表达业务含义，禁止拼音、无意义缩写和中文标识符。
4. 新表、新字段和索引必须有明确用途，禁止预留 `field1`、`ext1` 等无语义字段。
5. 表和业务字段必须填写中文 Comment。
6. 只保存必要数据，禁止在普通业务字段中保存密码、密钥、令牌等敏感明文。
7. 无法确认的业务规则必须先确认，禁止根据名称猜测。
8. DDL 必须经过审核、备份和测试环境验证后执行。

## DDL 变更规范

1. 禁止直接在生产环境手工修改表结构。
2. 每次变更提供用途、影响表字段、兼容性、预览、执行、回滚和注意事项。
3. 新增非空字段时先评估历史数据；必要时按“新增可空字段、回填、改为非空”分步执行。
4. 删除或重命名字段前先扫描代码、接口、报表、任务和外部系统依赖。
5. 大表变更必须评估锁表时间、磁盘空间、复制延迟和在线 DDL 能力。
6. 修改 Comment 时只允许改变 Comment，不得顺带改变类型、NULL、默认值、字符集、生成表达式和索引。
7. 批量更新或删除前必须先执行相同条件的 `SELECT` 预览影响范围。
8. 所有 DDL 和数据修复 SQL 由人工审核后执行。

## 表前缀含义

| 前缀 | 含义 | 示例 |
|------|------|------|
| `admin_` | 系统用户侧实体 | `admin_user`, `admin_depa` |
| `sys_` | 系统功能表（权限/角色/站点/配置） | `sys_role`, `sys_permission`, `sys_site` |
| `attr_` | 属性类表（通用属性、零件关联属性） | `attr_type`, `attr_value`, `attr_factory` |
| `wash_` | 数据清单业务表 | `wash_sheet`, `wash_sheet_item` |
| `biz_` | 业务数据表 | `biz_product`（业务扩展用） |

「零件关联属性」下的所有表统一用 `attr_` 前缀，不要用 `biz_`。

## 主键命名规则

格式：`{去掉前缀的表名}_id`

| 表名 | 主键字段 |
|------|---------|
| `admin_user` | `admin_id` |
| `admin_depa` | `admin_depa_id` |
| `sys_role` | `sys_role_id` |
| `sys_permission` | `sys_permission_code`（字符串主键，例外） |
| `sys_site` | `sys_site_id` |
| `attr_factory` | `factory_id` |
| `wash_sheet` | `wash_sheet_id` |
| `wash_sheet_item` | `wash_sheet_item_id` |

## 字段前缀规则

表内所有字段带表名前缀（`admin_user` 表的字段都以 `admin_` 开头）。
例外：联表展示的计算字段（如 `admin_depa_names`）不带前缀，标注只读。

## 外键列命名规则

**FK 列名不能与被引用表的主键同名。**

使用 `_lnk_` 标记关联关系：

```
格式：{本表前缀}_lnk_{被引用字段名}

示例：
  admin_user_depa 表的 FK 列：
    admin_user_depa_lnk_admin_id   → 引用 admin_user.admin_id
    admin_user_depa_lnk_depa_id    → 引用 admin_depa.admin_depa_id

  wash_sheet_item 表的 FK 列：
    wash_sheet_item_lnk_sheet_id   → 引用 wash_sheet.wash_sheet_id
    wash_sheet_item_lnk_factory_id → 引用 attr_factory.factory_id
```

## 多对多中间表

命名：`{表A前缀}_{表B简称}` 或 `{sys_前缀}{A}_{B}`

| 中间表 | 连接关系 |
|--------|---------|
| `admin_user_depa` | admin_user ↔ admin_depa |
| `sys_admin_role` | admin_user ↔ sys_role |
| `sys_member_role` | member ↔ sys_role |
| `sys_depa_role` | admin_depa ↔ sys_role |
| `sys_role_permission` | sys_role ↔ sys_permission |

多对多绑定统一用**全量替换**：先 DELETE 旧记录，再批量 INSERT 新记录。

## Model 使用规则

- `$table` 填写物理表名，`$key` 填写主键字段名
- 需要 JOIN 展示时覆盖 `gridFrom()` 和 `gridSelect()`
- 需要 GROUP BY 时覆盖 `gridGroupBy()`
- 联表展示字段（如 `sys_site_name`）在 `gridInsert/gridUpdate` 里必须 `unset` 后再写库
- 使用 Medoo 的 `$this->db` 操作，禁止在 Model 里拼裸 SQL 字符串

## 数据库连接

- 默认连接：`Mvc::$cfg['db']['default']`（配置在 `config/database.php`）
- 多库场景：`Db::instance('other')` 按名称取连接
- 禁止在 Action 里直接 new PDO 或操作数据库
