Files
hospital_performance/.qoder/repowiki/zh/content/数据模型详解/数据库约束设计.md
2026-02-28 15:16:15 +08:00

22 KiB
Raw Blame History

数据库约束设计

**本文档引用的文件** - [models.py](file://backend/app/models/models.py) - [finance.py](file://backend/app/models/finance.py) - [001_initial.py](file://backend/alembic/versions/001_initial.py) - [002_template.py](file://backend/alembic/versions/002_template.py) - [database.py](file://backend/app/core/database.py) - [config.py](file://backend/app/core/config.py) - [database.md](file://docs/database.md) - [main.py](file://backend/app/main.py)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构概览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考虑
  8. 故障排除指南
  9. 结论

简介

本文件详细阐述了医院绩效管理系统的数据库约束设计,涵盖唯一性约束、检查约束、索引设计和外键约束的实现原理与业务意义。通过对系统中各个数据表的约束策略进行深入分析,帮助开发者和运维人员理解数据完整性保障机制,并提供针对约束冲突的处理策略和优化建议。

项目结构

该系统采用基于 SQLAlchemy 的 ORM 设计,数据库约束主要通过以下方式实现:

  • 数据模型层定义:在模型类中直接声明约束和索引
  • 迁移脚本层:通过 Alembic 版本化管理数据库结构变更
  • 配置层:数据库连接和会话管理
graph TB
subgraph "数据模型层"
Models[ORM 模型定义]
Constraints[约束声明]
Indexes[索引定义]
end
subgraph "迁移管理层"
Alembic[Alembic 迁移]
Initial[初始版本]
Template[模板版本]
end
subgraph "配置层"
Config[数据库配置]
Engine[异步引擎]
Session[会话管理]
end
Models --> Alembic
Constraints --> Alembic
Indexes --> Alembic
Alembic --> Initial
Alembic --> Template
Config --> Engine
Engine --> Session

图表来源

章节来源

核心组件

系统的核心数据模型包括科室、员工、考核指标、考核记录、工资记录等关键实体。每个实体都配备了相应的约束策略以确保数据完整性。

主要数据实体

实体名称 主键字段 唯一约束 外键约束 检查约束
departments id code
staff id employee_id department_id
indicators id code weight > 0
assessments id staff_id, assessor_id, reviewer_id
assessment_details id assessment_id, indicator_id
salary_records id staff_id
users id username staff_id
performance_plans id plan_code department_id, staff_id, parent_plan_id, submitter_id, approver_id
plan_kpi_relations id (plan_id, indicator_id) 唯一 plan_id, indicator_id
indicator_templates id template_code
template_indicators id (template_id, indicator_id) 唯一 template_id, indicator_id
department_finances id department_id amount >= 0

章节来源

架构概览

系统采用三层约束设计架构:

graph TB
subgraph "约束层次"
Layer1[业务层约束<br/>模型定义]
Layer2[持久层约束<br/>数据库层面]
Layer3[应用层约束<br/>应用程序逻辑]
end
subgraph "约束类型"
Unique[唯一性约束]
Check[检查约束]
FK[外键约束]
Index[索引约束]
end
subgraph "应用场景"
Business[业务规则]
DataIntegrity[数据完整性]
QueryOptimization[查询优化]
Referential[参照完整性]
end
Layer1 --> Unique
Layer1 --> Check
Layer1 --> FK
Layer1 --> Index
Unique --> Business
Check --> DataIntegrity
FK --> Referential
Index --> QueryOptimization

图表来源

详细组件分析

唯一性约束设计

唯一性约束是确保数据唯一性的基础机制,系统在多个关键字段上实施了唯一性约束。

唯一性约束实现

表名 唯一字段 约束目的 业务意义
departments code 科室编码唯一性 防止重复科室标识,便于精确识别
staff employee_id 员工工号唯一性 确保员工身份唯一标识,避免重复录入
users username 用户名唯一性 保证系统用户身份唯一,防止登录冲突
indicators code 指标编码唯一性 确保考核指标的唯一标识,便于管理和查询
performance_plans plan_code 计划编码唯一性 防止重复计划标识,维护计划体系完整性
indicator_templates template_code 模板编码唯一性 确保模板的唯一标识,便于模板管理和复用
plan_kpi_relations (plan_id, indicator_id) 关联关系唯一性 防止重复关联,确保计划-指标关系的准确性
template_indicators (template_id, indicator_id) 关联关系唯一性 防止重复关联,确保模板-指标关系的准确性

唯一性约束触发条件

flowchart TD
Start([数据插入/更新]) --> CheckUnique["检查唯一性约束"]
CheckUnique --> UniqueExists{"是否存在重复值?"}
UniqueExists --> |是| RaiseError["抛出唯一性约束异常"]
UniqueExists --> |否| Continue["继续执行操作"]
RaiseError --> HandleConflict["处理冲突"]
HandleConflict --> Rollback["回滚事务"]
Continue --> Commit["提交事务"]
Rollback --> End([结束])
Commit --> End

图表来源

章节来源

检查约束设计

检查约束用于强制执行复杂的业务规则,确保数据符合预定义的条件。

检查约束实现

表名 约束条件 约束名称 业务含义
indicators weight > 0 ck_indicator_weight 确保指标权重必须为正数,保证计算逻辑正确性
department_finances amount >= 0 ck_finance_amount 确保财务金额不能为负数,维护财务数据准确性

检查约束验证流程

sequenceDiagram
participant Client as 客户端
participant DB as 数据库
participant Trigger as 检查约束触发器
Client->>DB : INSERT/UPDATE 操作
DB->>Trigger : 验证检查约束
Trigger->>Trigger : 计算约束条件
Trigger->>Trigger : 判断条件是否满足
alt 条件满足
Trigger->>DB : 允许操作
DB-->>Client : 操作成功
else 条件不满足
Trigger->>DB : 拒绝操作
DB-->>Client : 抛出检查约束异常
end

图表来源

章节来源

外键约束设计

外键约束确保参照完整性,防止出现孤立记录和无效引用。

外键约束实现

表名 外键字段 引用表 约束类型 业务意义
staff department_id departments 必须引用有效科室 确保员工属于存在的科室
assessments staff_id staff 必须引用有效员工 确保考核记录对应有效员工
assessments assessor_id staff 可选引用有效员工 确保考核人存在且有效
assessments reviewer_id staff 可选引用有效员工 确保审核人存在且有效
assessment_details assessment_id assessments 必须引用有效考核记录 确保明细对应有效考核
assessment_details indicator_id indicators 必须引用有效指标 确保明细对应有效指标
salary_records staff_id staff 必须引用有效员工 确保工资记录对应有效员工
users staff_id staff 可选引用有效员工 确保用户关联有效员工
performance_plans department_id departments 可选引用有效科室 确保计划关联有效科室
performance_plans staff_id staff 可选引用有效员工 确保计划关联有效员工
performance_plans parent_plan_id performance_plans 自引用 确保计划层级关系正确
performance_plans submitter_id users 可选引用有效用户 确保提交人存在且有效
performance_plans approver_id users 可选引用有效用户 确保审批人存在且有效
plan_kpi_relations plan_id performance_plans 必须引用有效计划 确保关联关系有效
plan_kpi_relations indicator_id indicators 必须引用有效指标 确保关联关系有效
template_indicators template_id indicator_templates 必须引用有效模板 确保关联关系有效
template_indicators indicator_id indicators 必须引用有效指标 确保关联关系有效
department_finances department_id departments 必须引用有效科室 确保财务记录对应有效科室

外键约束级联行为

classDiagram
class Department {
+id : int
+name : str
+code : str
+children : Department[]
}
class Staff {
+id : int
+employee_id : str
+department_id : int
+department : Department
}
class Assessment {
+id : int
+staff_id : int
+staff : Staff
+assessor_id : int
+reviewer_id : int
}
class PerformancePlan {
+id : int
+department_id : int
+staff_id : int
+parent_plan_id : int
+submitter_id : int
+approver_id : int
+parent_plan : PerformancePlan
}
Department --> Staff : "1 : N"
Staff --> Assessment : "1 : N"
PerformancePlan --> PerformancePlan : "self-ref"

图表来源

章节来源

索引设计策略

索引设计直接影响查询性能和数据检索效率,系统针对高频查询场景建立了多维索引。

单列索引设计

表名 索引字段 索引名称 查询场景 性能收益
departments dept_type idx_dept_type 按科室类型查询 快速筛选特定类型科室
departments parent_id idx_dept_parent 按上级科室查询 快速获取子科室层级
staff department_id idx_staff_dept 按科室查询员工 快速定位科室员工
staff status idx_staff_status 按状态查询员工 快速筛选特定状态员工
indicators indicator_type idx_indicator_type 按指标类型查询 快速筛选指标类型
assessments staff_id idx_assessment_staff 按员工查询考核记录 快速获取员工考核历史
assessments period_year, period_month idx_assessment_period 按时间段查询考核记录 快速定位特定期间记录
assessments status idx_assessment_status 按状态查询考核记录 快速筛选特定状态记录
assessment_details assessment_id idx_detail_assessment 按考核记录查询明细 快速获取考核明细
assessment_details indicator_id idx_detail_indicator 按指标查询明细 快速获取指标相关明细
salary_records staff_id idx_salary_staff 按员工查询工资记录 快速获取员工工资历史
salary_records period_year, period_month idx_salary_period 按时间段查询工资记录 快速定位特定期间工资
users username idx_user_username 按用户名查询用户 快速定位用户账户
performance_plans plan_level idx_plan_level 按计划层级查询 快速筛选特定层级计划
performance_plans plan_year idx_plan_year 按年度查询计划 快速定位年度计划
performance_plans department_id idx_plan_department 按科室查询计划 快速获取科室计划
performance_plans status idx_plan_status 按状态查询计划 快速筛选特定状态计划
indicator_templates template_type idx_template_type 按模板类型查询 快速筛选模板类型
indicator_templates is_active idx_template_active 按启用状态查询 快速筛选有效模板
plan_kpi_relations plan_id idx_relation_plan 按计划查询关联 快速获取计划关联指标
plan_kpi_relations indicator_id idx_relation_indicator 按指标查询关联 快速获取指标关联计划
template_indicators template_id idx_ti_template 按模板查询关联 快速获取模板关联指标
template_indicators indicator_id idx_ti_indicator 按指标查询关联 快速获取指标关联模板
department_finances department_id idx_finance_dept 按科室查询财务记录 快速获取科室财务数据
department_finances period_year, period_month idx_finance_period 按时间段查询财务记录 快速定位特定期间财务
department_finances finance_type idx_finance_type 按财务类型查询 快速筛选收支类型
department_finances category idx_finance_category 按类别查询财务记录 快速筛选特定类别

复合索引设计思路

复合索引通过组合多个字段来优化特定查询模式:

flowchart TD
QueryPattern[查询模式分析] --> IdentifyFields["识别查询字段"]
IdentifyFields --> Selectivity["评估选择性"]
Selectivity --> OrderFields["确定字段顺序"]
OrderFields --> TestPerformance["测试查询性能"]
TestPerformance --> CreateIndex["创建复合索引"]
CreateIndex --> MonitorUsage["监控索引使用"]
MonitorUsage --> OptimizeIndex["优化索引设计"]
subgraph "复合索引示例"
PeriodIndex["idx_assessment_period<br/>(year, month)"]
RelationIndex["idx_ti_unique<br/>(template_id, indicator_id)"]
PlanIndex["idx_plan_department<br/>(department_id, status)"]
end

图表来源

章节来源

约束冲突处理策略

当数据库约束被违反时,系统需要有一套完善的冲突处理机制。

错误处理流程

sequenceDiagram
participant App as 应用程序
participant DB as 数据库
participant Handler as 错误处理器
App->>DB : 执行数据库操作
DB->>DB : 验证所有约束
alt 约束验证失败
DB->>Handler : 抛出约束异常
Handler->>Handler : 分析异常类型
Handler->>Handler : 生成用户友好错误消息
Handler->>App : 返回错误响应
else 约束验证成功
DB->>App : 返回成功响应
end

约束冲突类型及处理

冲突类型 触发条件 处理策略 用户反馈
唯一性冲突 插入重复唯一值 提示用户修改唯一字段值 "该[字段]已存在,请使用其他值"
外键冲突 引用不存在的外键值 提示用户选择有效引用值 "请选择有效的[关联实体]"
检查约束冲突 数据不符合检查条件 提示用户修正数据格式 "[字段]必须满足[条件说明]"
级联删除冲突 尝试删除有子记录的父记录 提示用户先删除子记录或调整级联策略 "请先删除子记录或调整关联关系"

章节来源

依赖关系分析

系统约束设计涉及多个层面的依赖关系,形成了完整的数据完整性保障体系。

graph TB
subgraph "模型层依赖"
ModelBase[Base Model]
ConstraintMixin[Constraint Mixin]
IndexMixin[Index Mixin]
end
subgraph "约束实现"
UniqueConstraint[Unique Constraint]
CheckConstraint[Check Constraint]
ForeignKeyConstraint[Foreign Key Constraint]
IndexConstraint[Index Constraint]
end
subgraph "迁移层依赖"
AlembicOps[Alembic Operations]
MigrationScripts[Migration Scripts]
end
subgraph "配置层依赖"
DatabaseConfig[Database Configuration]
AsyncEngine[Async Engine]
SessionManager[Session Manager]
end
ModelBase --> ConstraintMixin
ModelBase --> IndexMixin
ConstraintMixin --> UniqueConstraint
ConstraintMixin --> CheckConstraint
IndexMixin --> IndexConstraint
AlembicOps --> MigrationScripts
DatabaseConfig --> AsyncEngine
AsyncEngine --> SessionManager
MigrationScripts --> UniqueConstraint
MigrationScripts --> CheckConstraint
MigrationScripts --> ForeignKeyConstraint

图表来源

章节来源

性能考虑

合理的约束设计不仅保证数据完整性,还能显著提升系统性能。

索引性能优化

查询性能分析

查询类型 索引使用情况 性能影响 优化建议
等值查询 使用精确匹配索引 高性能 确保查询条件包含索引字段
范围查询 使用范围扫描索引 中等性能 优化查询条件,减少扫描范围
复合查询 使用复合索引 高性能 确保查询条件覆盖索引前缀
排序查询 使用排序索引 高性能 确保ORDER BY字段包含在索引中
连接查询 使用连接索引 高性能 确保JOIN字段建立索引

索引维护策略

flowchart TD
Monitor[监控索引使用] --> AnalyzeUsage["分析索引使用率"]
AnalyzeUsage --> IdentifyUnused["识别未使用索引"]
IdentifyUnused --> DropUnused["删除无用索引"]
AnalyzeUsage --> IdentifyMissing["识别缺失索引"]
IdentifyMissing --> CreateIndex["创建必要索引"]
CreateIndex --> Monitor
DropUnused --> Monitor
Monitor --> RebuildIndex["重建碎片索引"]
RebuildIndex --> Monitor

约束对性能的影响

约束类型 正面影响 负面影响 性能平衡点
唯一性约束 数据一致性保证 插入/更新时额外检查 在高频写入场景下适度放宽
检查约束 业务规则强制执行 数据验证开销 复杂检查约束需要谨慎使用
外键约束 参照完整性保障 关联查询性能影响 对频繁关联查询考虑性能权衡
索引约束 查询性能提升 写入性能下降 基于查询模式优化索引设计

故障排除指南

常见约束问题诊断

唯一性约束冲突

问题症状:插入或更新数据时报唯一性约束错误

诊断步骤

  1. 检查冲突的具体字段和值
  2. 验证是否存在重复数据
  3. 确认业务逻辑是否允许重复
  4. 检查数据清理流程

解决方案

  • 修改唯一字段值
  • 清理重复数据
  • 调整业务逻辑
  • 重新设计唯一性策略

外键约束冲突

问题症状:引用不存在的数据时报外键约束错误

诊断步骤

  1. 确认被引用表中是否存在对应记录
  2. 检查关联字段的数据类型和格式
  3. 验证数据插入顺序
  4. 检查是否有级联删除策略

解决方案

  • 先插入父记录再插入子记录
  • 使用正确的关联值
  • 调整级联删除策略
  • 实施数据预校验

检查约束冲突

问题症状:数据不符合检查条件时报错

诊断步骤

  1. 检查具体违反的约束条件
  2. 验证数据格式和范围
  3. 确认业务规则合理性
  4. 检查数据转换逻辑

解决方案

  • 修正数据格式
  • 调整业务规则
  • 实施数据验证
  • 优化约束条件

数据库迁移问题

迁移失败处理

常见问题

  • 字段已存在导致迁移失败
  • 索引创建冲突
  • 外键约束依赖问题

处理策略

  1. 检查当前数据库状态
  2. 手动执行必要的DDL操作
  3. 调整迁移脚本顺序
  4. 实施回滚和重试机制

章节来源

结论

本系统的数据库约束设计体现了多层次、全方位的数据完整性保障机制。通过合理运用唯一性约束、检查约束、外键约束和索引约束,系统在保证数据准确性和一致性的前提下,实现了高效的查询性能和良好的扩展性。

设计亮点

  1. 层次化约束设计:从模型层到数据库层的完整约束覆盖
  2. 业务导向的约束策略:每个约束都有明确的业务意义和触发条件
  3. 性能优化的索引设计:针对高频查询场景的复合索引策略
  4. 完善的冲突处理机制:从技术层面到用户体验的全面考虑

持续改进建议

  1. 监控和分析:建立约束使用情况的监控机制
  2. 定期优化:根据查询模式变化调整索引策略
  3. 文档完善:持续更新约束设计文档和最佳实践
  4. 性能测试:定期进行约束对性能影响的评估测试

通过这套完整的约束设计体系,系统能够可靠地支撑医院绩效管理的各项业务需求,为医疗质量管理提供坚实的数据基础。