Files
railwaysystem/docs/database-v2/03_constraint_index_review.md
T

127 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RailwaySystem 数据库 V2 约束与索引技术审查报告 (Round 1 修订版)
> **审查依据**:[`RailwaySystem 数据库 V2 字段设计与 Kingbase DDL 规范 V1.0.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/doc/RailwaySystem%20数据库%20V2%20字段设计与%20Kingbase%20DDL%20规范%20V1.0.md) 及 Round 1 审查要求
> **审查对象**:[`005_constraints.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/005_constraints.sql) 与 [`006_indexes.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/006_indexes.sql)
---
## 1. 主键(PRIMARY KEY)审查
V2 模型包含 21 张正式业务表,主键设计清晰划分为两类:
### 1.1 业务编码主键 (8 张基础表,varchar(32))
- 适用表:`train_teacher` (t_id), `train_student` (s_id), `train_course` (c_id), `train_resource` (resource_id), `train_classroom_info` (class_room_id), `train_training_site` (site_id), `train_electronic_board` (board_id), `train_dormitory_info` (dorm_id), `train_class_plan` (plan_id)。
- **审查结论**:保持既有若依与业务系统自定义编码惯例,支持业务前缀与分布式生成;在 Kingbase 中具备唯一 B-Tree 聚集索引。
### 1.2 数字自增主键 (13 张关系/过程表,bigint identity)
- 适用表:`train_course_resource` (id), `train_plan_course` (plan_course_id), `train_enrollment` (enrollment_id), `train_lesson` (lesson_id), `train_accommodation` (accommodation_id), `train_dorm_auth` (auth_id), `train_class_report` (report_id), `train_student_checkin` (checkin_id), `train_score_item` (score_item_id), `train_student_score` (score_id), `train_study_duration` (dur_id), `train_student_portrait` (portrait_id)。
- **语法形式**:`BIGINT GENERATED BY DEFAULT AS IDENTITY`。
- **审查结论**:严格杜绝 MySQL 方言 `AUTO_INCREMENT`,在 KingbaseES 下生成标准序列并被 JDBC 驱动识别。
---
## 2. 外键约束(FOREIGN KEY)审查
### 2.1 26 组业务外键全量拓扑
```text
train_course_resource (c_id) -> train_course (c_id)
train_course_resource (resource_id) -> train_resource (resource_id)
train_electronic_board (bind_classroom_id) -> train_classroom_info (class_room_id)
train_plan_course (plan_id) -> train_class_plan (plan_id)
train_plan_course (c_id) -> train_course (c_id)
train_enrollment (plan_id) -> train_class_plan (plan_id)
train_enrollment (student_id) -> train_student (s_id)
train_lesson (plan_course_id) -> train_plan_course (plan_course_id)
train_lesson (t_id) -> train_teacher (t_id)
train_lesson (class_room_id) -> train_classroom_info (class_room_id)
train_lesson (site_id) -> train_training_site (site_id)
train_accommodation (enrollment_id) -> train_enrollment (enrollment_id)
train_accommodation (dorm_id) -> train_dormitory_info (dorm_id)
train_dorm_auth (accommodation_id) -> train_accommodation (accommodation_id)
train_class_report (enrollment_id) -> train_enrollment (enrollment_id)
train_student_checkin (enrollment_id) -> train_enrollment (enrollment_id)
train_student_checkin (lesson_id) -> train_lesson (lesson_id)
train_student_checkin (board_id) -> train_electronic_board (board_id)
train_score_item (plan_id) -> train_class_plan (plan_id)
train_score_item (plan_course_id) -> train_plan_course (plan_course_id)
train_student_score (enrollment_id) -> train_enrollment (enrollment_id)
train_student_score (score_item_id) -> train_score_item (score_item_id)
train_study_duration (enrollment_id) -> train_enrollment (enrollment_id)
train_study_duration (plan_course_id) -> train_plan_course (plan_course_id)
train_study_duration (resource_id) -> train_resource (resource_id)
train_student_portrait (enrollment_id) -> train_enrollment (enrollment_id)
```
### 2.2 删除规则原则审查
- **核心合规**:所有 26 组外键规则均为 `ON DELETE NO ACTION`,**零级联删除(CASCADE)**;
- **业务依据**:培训班作废、课程停用或学员离校,绝不可导致学员考勤、历史成绩、学时记录与住宿轨迹发生连带物理抹除,系统必须保留可追溯痕迹;
- **系统表解耦**:所有培训表未对 `sys_user` 建立物理外键约束,仅在业务代码层做逻辑关联,避免跨领域强耦合。
---
## 3. 唯一约束(UNIQUE)审查
V2 DDL 共注入 13 组核心业务 UNIQUE 约束:
| 序号 | 约束名称 | 作用表 | 约束字段 | 业务防重目标 |
| :--- | :--- | :--- | :--- | :--- |
| 1 | `uq_student_idcard_hash` | `train_student` | `id_card_hash` | 学员身份证精确防重(允许 NULL) |
| 2 | `uq_course_code` | `train_course` | `c_code` | 课程业务编码全局唯一 |
| 3 | `uq_board_sn` | `train_electronic_board` | `board_sn` | 班牌设备硬件序列号全局唯一 |
| 4 | `uq_dorm_building_room` | `train_dormitory_info` | `(dorm_building, dorm_room)` | 楼栋与房间组合唯一 |
| 5 | `uq_course_resource` | `train_course_resource` | `(c_id, resource_id)` | 课程与资源绑定防重复 |
| 6 | `uq_plan_course` | `train_plan_course` | `(plan_id, c_id)` | 同一培训班不可重复配置相同课程 |
| 7 | `uq_enrollment` | `train_enrollment` | `(plan_id, student_id)` | 同一学员不可重复加入同一培训班 |
| 8 | `uq_accommodation` | `train_accommodation` | `(enrollment_id)` | 一次参训单期唯一有效住宿分配 |
| 9 | `uq_dorm_auth` | `train_dorm_auth` | `(accommodation_id)` | 一次住宿安排对应唯一门禁同步记录 |
| 10 | `uq_class_report` | `train_class_report` | `(enrollment_id)` | 一次参训对应唯一现场报到结论 |
| 11 | `uq_student_checkin` | `train_student_checkin` | `(enrollment_id, lesson_id)` | 一个学员一堂课只有一条考勤结论 |
| 12 | `uq_student_score` | `train_student_score` | `(enrollment_id, score_item_id)` | 一个学员在某考核项只有一条最终得分 |
| 13 | `uq_student_portrait` | `train_student_portrait` | `(enrollment_id)` | 一次参训对应一份全周期评价画像 |
---
## 4. 检查约束(CHECK)审查 (Round 1 扩充)
在 Round 1 审查中,单行检查约束由原先的 4 条大幅扩充至 9 条,全面覆盖时间有效性、场地互斥、数值合法与系统字段联动:
| 序号 | 约束名称 | 作用表 | 约束定义 | 校验逻辑目标 |
| :---: | :--- | :--- | :--- | :--- |
| 1 | `chk_lesson_time` | `train_lesson` | `start_time < end_time` | 课次开始时间必须早于结束时间 |
| 2 | `chk_lesson_venue` | `train_lesson` | `(venue_type = 1 AND class_room_id IS NOT NULL AND site_id IS NULL) OR (venue_type = 2 AND site_id IS NOT NULL AND class_room_id IS NULL)` | **场地互斥**:教室与实训场地二选一,杜绝混淆 |
| 3 | `chk_score_item_weight` | `train_score_item` | `weight >= 0.00 AND weight <= 100.00` | 单项成绩权重必须在 0~100 之间 |
| 4 | `chk_score_item_full` | `train_score_item` | `full_score > 0.00` | 满分设定必须大于 0 |
| 5 | `chk_student_score_nonneg` | `train_student_score` | `score >= 0.00` | **分值非负**:未录入不建行,录入则必须非负 |
| 6 | `chk_study_seconds` | `train_study_duration` | `study_seconds >= 0` | 累计学习秒数必须非负 |
| 7 | `chk_study_time` | `train_study_duration` | `end_time IS NULL OR start_time IS NULL OR end_time >= start_time` | **学时先后**:学习结束时间不得早于开始时间 |
| 8 | `chk_study_source_system` | `train_study_duration` | `source_event_id IS NULL OR source_system IS NOT NULL` | **单号匹配**:有外部单号时必须声明来源系统 |
| 9 | `chk_dorm_capacity` | `train_dormitory_info` | `capacity > 0` | **容量正数**:宿舍房间核定床位数必须大于 0 |
---
## 5. 索引(INDEX)审查
[`006_indexes.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/006_indexes.sql) 包含外键索引、排课多维复合索引与部分唯一索引:
1. **外键索引**:为所有 26 组外键列配置独立 B-Tree 索引,杜绝父表更新锁定子表或关联全表扫描;
2. **排课多维冲突高频复合索引**:
- 教师时间冲突检测:`idx_lesson_teacher_time (t_id, start_time, end_time)`;
- 教室时间冲突检测:`idx_lesson_classroom_time (class_room_id, start_time, end_time)`;
- 场地时间冲突检测:`idx_lesson_site_time (site_id, start_time, end_time)`;
3. **双非空过滤的部分唯一索引(Partial Unique Index)**:
- `uq_idx_study_source_event` on `train_study_duration(source_system, source_event_id) WHERE source_system IS NOT NULL AND source_event_id IS NOT NULL`;
- **审查要点**:严格杜绝 `source_system` 为空而单号有值时的幂等逃逸。