首次提交by MimoCode
This commit is contained in:
@@ -0,0 +1,530 @@
|
||||
# 数据库设计文档
|
||||
|
||||
## 1. 数据库概述
|
||||
|
||||
系统使用 SQLite 作为主数据库,支持未来升级到 PostgreSQL。数据库设计遵循第三范式,确保数据一致性和查询效率。
|
||||
|
||||
## 2. ER 图
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐
|
||||
│ users │ │ categories │
|
||||
├─────────────────┤ ├─────────────────┤
|
||||
│ id (PK) │ │ id (PK) │
|
||||
│ username │ │ name │
|
||||
│ password_hash │ │ parent_id (FK) │
|
||||
│ role │ │ level │
|
||||
│ display_name │ │ icon │
|
||||
│ email │ │ sort_order │
|
||||
│ notification_ │ │ created_at │
|
||||
│ level │ │ updated_at │
|
||||
│ is_active │ └─────────────────┘
|
||||
│ created_at │ │
|
||||
│ updated_at │ │
|
||||
└─────────────────┘ │
|
||||
│ │
|
||||
│ │
|
||||
▼ ▼
|
||||
┌─────────────────────────────────────────┐
|
||||
│ medicines │
|
||||
├─────────────────────────────────────────┤
|
||||
│ id (PK) │
|
||||
│ name │
|
||||
│ generic_name │
|
||||
│ brand_name │
|
||||
│ manufacturer │
|
||||
│ specification │
|
||||
│ category_id (FK) │
|
||||
│ description │
|
||||
│ indications │
|
||||
│ adult_dose │
|
||||
│ child_dose │
|
||||
│ contraindications │
|
||||
│ notes │
|
||||
│ image_front_path │
|
||||
│ image_expiry_path │
|
||||
│ image_leaflet_paths (JSON) │
|
||||
│ expiry_grace_days (默认0,最大60) │
|
||||
│ created_by (FK → users) │
|
||||
│ created_at │
|
||||
│ updated_at │
|
||||
└─────────────────────────────────────────┘
|
||||
│
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐ ┌─────────────────┐
|
||||
│ batches │ │ audit_logs │
|
||||
├─────────────────┤ ├─────────────────┤
|
||||
│ id (PK) │ │ id (PK) │
|
||||
│ medicine_id (FK)│ │ medicine_id (FK)│
|
||||
│ batch_no │ │ batch_id (FK) │
|
||||
│ production_date │ │ user_id (FK) │
|
||||
│ expiry_date │ │ action │
|
||||
│ quantity │ │ quantity_change │
|
||||
│ location │ │ quantity_after │
|
||||
│ is_expired │ │ remark │
|
||||
│ created_at │ │ created_at │
|
||||
│ updated_at │ └─────────────────┘
|
||||
└─────────────────┘
|
||||
│
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐ ┌─────────────────┐
|
||||
│notifications │ │ settings │
|
||||
├─────────────────┤ ├─────────────────┤
|
||||
│ id (PK) │ │ id (PK) │
|
||||
│ type │ │ key │
|
||||
│ title │ │ value │
|
||||
│ content │ │ description │
|
||||
│ is_read │ │ updated_at │
|
||||
│ user_id (FK) │ └─────────────────┘
|
||||
│ created_at │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
## 3. 表结构定义
|
||||
|
||||
### 3.1 users 表(用户表)
|
||||
|
||||
```sql
|
||||
CREATE TABLE users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
role VARCHAR(20) NOT NULL DEFAULT 'user' CHECK(role IN ('admin', 'user', 'readonly')),
|
||||
display_name VARCHAR(100),
|
||||
email VARCHAR(100),
|
||||
notification_level VARCHAR(20) DEFAULT 'normal' CHECK(notification_level IN ('none', 'low', 'normal', 'high')),
|
||||
is_active BOOLEAN DEFAULT 1,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 索引
|
||||
CREATE INDEX idx_users_username ON users(username);
|
||||
CREATE INDEX idx_users_role ON users(role);
|
||||
```
|
||||
|
||||
**字段说明:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|------|------|------|--------|------|
|
||||
| id | INTEGER | 是 | 自增 | 主键 |
|
||||
| username | VARCHAR(50) | 是 | - | 用户名,唯一 |
|
||||
| password_hash | VARCHAR(255) | 是 | - | 密码哈希值 |
|
||||
| role | VARCHAR(20) | 是 | 'user' | 角色:admin/user/readonly |
|
||||
| display_name | VARCHAR(100) | 否 | NULL | 显示名称 |
|
||||
| email | VARCHAR(100) | 否 | NULL | 邮箱 |
|
||||
| notification_level | VARCHAR(20) | 否 | 'normal' | 通知等级 |
|
||||
| is_active | BOOLEAN | 否 | 1 | 是否启用 |
|
||||
| created_at | TIMESTAMP | 否 | CURRENT_TIMESTAMP | 创建时间 |
|
||||
| updated_at | TIMESTAMP | 否 | CURRENT_TIMESTAMP | 更新时间 |
|
||||
|
||||
### 3.2 categories 表(分类表)
|
||||
|
||||
```sql
|
||||
CREATE TABLE categories (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
parent_id INTEGER,
|
||||
level INTEGER NOT NULL DEFAULT 1 CHECK(level IN (1, 2)),
|
||||
icon VARCHAR(50),
|
||||
sort_order INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (parent_id) REFERENCES categories(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- 索引
|
||||
CREATE INDEX idx_categories_parent_id ON categories(parent_id);
|
||||
CREATE INDEX idx_categories_level ON categories(level);
|
||||
```
|
||||
|
||||
**字段说明:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|------|------|------|--------|------|
|
||||
| id | INTEGER | 是 | 自增 | 主键 |
|
||||
| name | VARCHAR(100) | 是 | - | 分类名称 |
|
||||
| parent_id | INTEGER | 否 | NULL | 父分类ID |
|
||||
| level | INTEGER | 是 | 1 | 分类层级:1或2 |
|
||||
| icon | VARCHAR(50) | 否 | NULL | 图标 |
|
||||
| sort_order | INTEGER | 否 | 0 | 排序顺序 |
|
||||
| created_at | TIMESTAMP | 否 | CURRENT_TIMESTAMP | 创建时间 |
|
||||
| updated_at | TIMESTAMP | 否 | CURRENT_TIMESTAMP | 更新时间 |
|
||||
|
||||
**预设分类数据:**
|
||||
|
||||
```sql
|
||||
-- 一级分类
|
||||
INSERT INTO categories (name, level, icon, sort_order) VALUES
|
||||
('药品', 1, 'medicine', 1),
|
||||
('医疗器械', 1, 'medical', 2),
|
||||
('应急用品', 1, 'emergency', 3),
|
||||
('消耗品', 1, 'consumable', 4);
|
||||
|
||||
-- 二级分类 - 药品
|
||||
INSERT INTO categories (name, parent_id, level, sort_order) VALUES
|
||||
('感冒药', 1, 2, 1),
|
||||
('退烧药', 1, 2, 2),
|
||||
('止泻药', 1, 2, 3),
|
||||
('消炎药', 1, 2, 4),
|
||||
('外用药', 1, 2, 5);
|
||||
|
||||
-- 二级分类 - 医疗器械
|
||||
INSERT INTO categories (name, parent_id, level, sort_order) VALUES
|
||||
('血压计', 2, 2, 1),
|
||||
('血糖仪', 2, 2, 2),
|
||||
('体温计', 2, 2, 3);
|
||||
|
||||
-- 二级分类 - 应急用品
|
||||
INSERT INTO categories (name, parent_id, level, sort_order) VALUES
|
||||
('创可贴', 3, 2, 1),
|
||||
('绷带', 3, 2, 2),
|
||||
('止血带', 3, 2, 3);
|
||||
|
||||
-- 二级分类 - 消耗品
|
||||
INSERT INTO categories (name, parent_id, level, sort_order) VALUES
|
||||
('酒精棉片', 4, 2, 1),
|
||||
('N95', 4, 2, 2),
|
||||
('医用手套', 4, 2, 3);
|
||||
```
|
||||
|
||||
### 3.3 medicines 表(药品表)
|
||||
|
||||
```sql
|
||||
CREATE TABLE medicines (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
generic_name VARCHAR(200),
|
||||
brand_name VARCHAR(200),
|
||||
manufacturer VARCHAR(200),
|
||||
specification VARCHAR(200),
|
||||
category_id INTEGER,
|
||||
description TEXT,
|
||||
indications TEXT,
|
||||
adult_dose TEXT,
|
||||
child_dose TEXT,
|
||||
contraindications TEXT,
|
||||
notes TEXT,
|
||||
image_front_path VARCHAR(500),
|
||||
image_expiry_path VARCHAR(500),
|
||||
image_leaflet_paths JSON,
|
||||
expiry_grace_days INTEGER DEFAULT 0 CHECK(expiry_grace_days >= 0 AND expiry_grace_days <= 60),
|
||||
created_by INTEGER,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- 索引
|
||||
CREATE INDEX idx_medicines_name ON medicines(name);
|
||||
CREATE INDEX idx_medicines_category_id ON medicines(category_id);
|
||||
CREATE INDEX idx_medicines_created_by ON medicines(created_by);
|
||||
CREATE INDEX idx_medicines_generic_name ON medicines(generic_name);
|
||||
```
|
||||
|
||||
**字段说明:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|------|------|------|--------|------|
|
||||
| id | INTEGER | 是 | 自增 | 主键 |
|
||||
| name | VARCHAR(200) | 是 | - | 药品名称 |
|
||||
| generic_name | VARCHAR(200) | 否 | NULL | 通用名称 |
|
||||
| brand_name | VARCHAR(200) | 否 | NULL | 商品名称 |
|
||||
| manufacturer | VARCHAR(200) | 否 | NULL | 生产厂家 |
|
||||
| specification | VARCHAR(200) | 否 | NULL | 规格 |
|
||||
| category_id | INTEGER | 否 | NULL | 分类ID |
|
||||
| description | TEXT | 否 | NULL | 描述 |
|
||||
| indications | TEXT | 否 | NULL | 适应症(用于搜索) |
|
||||
| adult_dose | TEXT | 否 | NULL | 成人用量 |
|
||||
| child_dose | TEXT | 否 | NULL | 儿童用量 |
|
||||
| contraindications | TEXT | 否 | NULL | 禁忌 |
|
||||
| notes | TEXT | 否 | NULL | 注意事项 |
|
||||
| image_front_path | VARCHAR(500) | 否 | NULL | 药盒正面图片路径 |
|
||||
| image_expiry_path | VARCHAR(500) | 否 | NULL | 有效期图片路径 |
|
||||
| image_leaflet_paths | JSON | 否 | NULL | 说明书图片路径数组 |
|
||||
| expiry_grace_days | INTEGER | 否 | 0 | 有效期宽限天数(最大60天) |
|
||||
| created_by | INTEGER | 否 | NULL | 创建者用户ID |
|
||||
| created_at | TIMESTAMP | 否 | CURRENT_TIMESTAMP | 创建时间 |
|
||||
| updated_at | TIMESTAMP | 否 | CURRENT_TIMESTAMP | 更新时间 |
|
||||
|
||||
### 3.4 batches 表(批次表)
|
||||
|
||||
```sql
|
||||
CREATE TABLE batches (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
medicine_id INTEGER NOT NULL,
|
||||
batch_no VARCHAR(100),
|
||||
production_date DATE,
|
||||
expiry_date DATE NOT NULL,
|
||||
quantity INTEGER NOT NULL DEFAULT 0 CHECK(quantity >= 0),
|
||||
location VARCHAR(200),
|
||||
is_expired BOOLEAN DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (medicine_id) REFERENCES medicines(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- 索引
|
||||
CREATE INDEX idx_batches_medicine_id ON batches(medicine_id);
|
||||
CREATE INDEX idx_batches_expiry_date ON batches(expiry_date);
|
||||
CREATE INDEX idx_batches_is_expired ON batches(is_expired);
|
||||
```
|
||||
|
||||
**字段说明:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|------|------|------|--------|------|
|
||||
| id | INTEGER | 是 | 自增 | 主键 |
|
||||
| medicine_id | INTEGER | 是 | - | 药品ID |
|
||||
| batch_no | VARCHAR(100) | 否 | NULL | 批次号 |
|
||||
| production_date | DATE | 否 | NULL | 生产日期 |
|
||||
| expiry_date | DATE | 是 | - | 过期日期 |
|
||||
| quantity | INTEGER | 是 | 0 | 库存数量 |
|
||||
| location | VARCHAR(200) | 否 | NULL | 存放位置 |
|
||||
| is_expired | BOOLEAN | 否 | 0 | 是否已过期 |
|
||||
| created_at | TIMESTAMP | 否 | CURRENT_TIMESTAMP | 创建时间 |
|
||||
| updated_at | TIMESTAMP | 否 | CURRENT_TIMESTAMP | 更新时间 |
|
||||
|
||||
### 3.5 audit_logs 表(审计日志表)
|
||||
|
||||
```sql
|
||||
CREATE TABLE audit_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
medicine_id INTEGER NOT NULL,
|
||||
batch_id INTEGER,
|
||||
user_id INTEGER,
|
||||
action VARCHAR(50) NOT NULL CHECK(action IN ('add_stock', 'dispense', 'adjust', 'delete', 'modify')),
|
||||
quantity_change INTEGER NOT NULL,
|
||||
quantity_after INTEGER NOT NULL,
|
||||
remark TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (medicine_id) REFERENCES medicines(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (batch_id) REFERENCES batches(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- 索引
|
||||
CREATE INDEX idx_audit_logs_medicine_id ON audit_logs(medicine_id);
|
||||
CREATE INDEX idx_audit_logs_user_id ON audit_logs(user_id);
|
||||
CREATE INDEX idx_audit_logs_created_at ON audit_logs(created_at);
|
||||
CREATE INDEX idx_audit_logs_action ON audit_logs(action);
|
||||
```
|
||||
|
||||
**字段说明:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|------|------|------|--------|------|
|
||||
| id | INTEGER | 是 | 自增 | 主键 |
|
||||
| medicine_id | INTEGER | 是 | - | 药品ID |
|
||||
| batch_id | INTEGER | 否 | NULL | 批次ID |
|
||||
| user_id | INTEGER | 否 | NULL | 操作用户ID |
|
||||
| action | VARCHAR(50) | 是 | - | 操作类型 |
|
||||
| quantity_change | INTEGER | 是 | - | 数量变化(正数增加,负数减少) |
|
||||
| quantity_after | INTEGER | 是 | - | 操作后数量 |
|
||||
| remark | TEXT | 否 | NULL | 备注 |
|
||||
| created_at | TIMESTAMP | 否 | CURRENT_TIMESTAMP | 创建时间 |
|
||||
|
||||
### 3.6 notifications 表(通知表)
|
||||
|
||||
```sql
|
||||
CREATE TABLE notifications (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
type VARCHAR(50) NOT NULL CHECK(type IN ('expiry_warning', 'low_stock', 'system')),
|
||||
title VARCHAR(200) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
is_read BOOLEAN DEFAULT 0,
|
||||
user_id INTEGER,
|
||||
related_id INTEGER,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- 索引
|
||||
CREATE INDEX idx_notifications_user_id ON notifications(user_id);
|
||||
CREATE INDEX idx_notifications_type ON notifications(type);
|
||||
CREATE INDEX idx_notifications_is_read ON notifications(is_read);
|
||||
CREATE INDEX idx_notifications_created_at ON notifications(created_at);
|
||||
```
|
||||
|
||||
**字段说明:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|------|------|------|--------|------|
|
||||
| id | INTEGER | 是 | 自增 | 主键 |
|
||||
| type | VARCHAR(50) | 是 | - | 通知类型 |
|
||||
| title | VARCHAR(200) | 是 | - | 通知标题 |
|
||||
| content | TEXT | 是 | - | 通知内容 |
|
||||
| is_read | BOOLEAN | 否 | 0 | 是否已读 |
|
||||
| user_id | INTEGER | 否 | NULL | 用户ID |
|
||||
| related_id | INTEGER | 否 | NULL | 关联ID(药品/批次) |
|
||||
| created_at | TIMESTAMP | 否 | CURRENT_TIMESTAMP | 创建时间 |
|
||||
|
||||
### 3.7 settings 表(系统设置表)
|
||||
|
||||
```sql
|
||||
CREATE TABLE settings (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
key VARCHAR(100) NOT NULL UNIQUE,
|
||||
value TEXT,
|
||||
description VARCHAR(500),
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 索引
|
||||
CREATE INDEX idx_settings_key ON settings(key);
|
||||
```
|
||||
|
||||
**字段说明:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|------|------|------|--------|------|
|
||||
| id | INTEGER | 是 | 自增 | 主键 |
|
||||
| key | VARCHAR(100) | 是 | - | 设置键名,唯一 |
|
||||
| value | TEXT | 否 | NULL | 设置值 |
|
||||
| description | VARCHAR(500) | 否 | NULL | 设置描述 |
|
||||
| updated_at | TIMESTAMP | 否 | CURRENT_TIMESTAMP | 更新时间 |
|
||||
|
||||
**预设设置数据:**
|
||||
|
||||
```sql
|
||||
INSERT INTO settings (key, value, description) VALUES
|
||||
('ai_provider', 'openai', 'AI 服务提供者'),
|
||||
('openai_api_key', '', 'OpenAI API Key'),
|
||||
('openai_model', 'gpt-4o', 'OpenAI 模型'),
|
||||
('notification_providers', '[]', '启用的通知提供者列表'),
|
||||
('expiry_warning_days', '90,30,7', '到期提醒天数(逗号分隔)'),
|
||||
('low_stock_threshold', '5', '低库存阈值'),
|
||||
('max_upload_size', '10485760', '最大上传文件大小(字节)'),
|
||||
('expiry_grace_days_max', '60', '有效期宽限最大天数');
|
||||
```
|
||||
|
||||
## 4. 关系说明
|
||||
|
||||
### 4.1 一对多关系
|
||||
|
||||
- **users → medicines**: 一个用户可以创建多个药品
|
||||
- **users → audit_logs**: 一个用户可以有多条审计日志
|
||||
- **users → notifications**: 一个用户可以有多条通知
|
||||
- **categories → medicines**: 一个分类可以包含多个药品
|
||||
- **categories → categories**: 一个分类可以有多个子分类
|
||||
- **medicines → batches**: 一个药品可以有多个批次
|
||||
- **medicines → audit_logs**: 一个药品可以有多条审计日志
|
||||
|
||||
### 4.2 级联操作
|
||||
|
||||
- 删除用户:相关药品、审计日志、通知保留(created_by/set NULL)
|
||||
- 删除分类:相关药品的 category_id 设为 NULL
|
||||
- 删除药品:相关批次、审计日志级联删除
|
||||
- 删除批次:相关审计日志的 batch_id 设为 NULL
|
||||
|
||||
## 5. 视图设计
|
||||
|
||||
### 5.1 药品库存视图
|
||||
|
||||
```sql
|
||||
CREATE VIEW v_medicine_stock AS
|
||||
SELECT
|
||||
m.id,
|
||||
m.name,
|
||||
m.generic_name,
|
||||
m.brand_name,
|
||||
m.specification,
|
||||
c.name as category_name,
|
||||
COALESCE(SUM(b.quantity), 0) as total_quantity,
|
||||
MIN(b.expiry_date) as nearest_expiry_date,
|
||||
COUNT(b.id) as batch_count
|
||||
FROM medicines m
|
||||
LEFT JOIN batches b ON m.id = b.medicine_id AND b.is_expired = 0
|
||||
LEFT JOIN categories c ON m.category_id = c.id
|
||||
GROUP BY m.id;
|
||||
```
|
||||
|
||||
### 5.2 即将过期药品视图
|
||||
|
||||
```sql
|
||||
CREATE VIEW v_expiring_medicines AS
|
||||
SELECT
|
||||
m.id,
|
||||
m.name,
|
||||
m.expiry_grace_days,
|
||||
b.id as batch_id,
|
||||
b.batch_no,
|
||||
b.expiry_date,
|
||||
b.quantity,
|
||||
julianday(b.expiry_date) - julianday('now') as days_until_expiry
|
||||
FROM medicines m
|
||||
JOIN batches b ON m.id = b.medicine_id
|
||||
WHERE b.is_expired = 0
|
||||
AND b.expiry_date <= date('now', '+' || (90 + m.expiry_grace_days) || ' days');
|
||||
```
|
||||
|
||||
## 6. 索引策略
|
||||
|
||||
### 6.1 主要索引
|
||||
|
||||
| 表名 | 索引名 | 字段 | 用途 |
|
||||
|------|--------|------|------|
|
||||
| users | idx_users_username | username | 用户登录查询 |
|
||||
| medicines | idx_medicines_name | name | 药品搜索 |
|
||||
| medicines | idx_medicines_category_id | category_id | 分类筛选 |
|
||||
| batches | idx_batches_medicine_id | medicine_id | 药品批次查询 |
|
||||
| batches | idx_batches_expiry_date | expiry_date | 到期提醒查询 |
|
||||
| audit_logs | idx_audit_logs_created_at | created_at | 审计日志时间查询 |
|
||||
|
||||
### 6.2 复合索引
|
||||
|
||||
```sql
|
||||
-- 药品搜索复合索引
|
||||
CREATE INDEX idx_medicines_search ON medicines(name, generic_name, brand_name);
|
||||
|
||||
-- 批次库存查询复合索引
|
||||
CREATE INDEX idx_batches_stock ON batches(medicine_id, is_expired, expiry_date);
|
||||
```
|
||||
|
||||
## 7. 数据迁移策略
|
||||
|
||||
### 7.1 使用 Alembic
|
||||
|
||||
```bash
|
||||
# 初始化 Alembic
|
||||
alembic init alembic
|
||||
|
||||
# 生成迁移脚本
|
||||
alembic revision --autogenerate -m "initial"
|
||||
|
||||
# 执行迁移
|
||||
alembic upgrade head
|
||||
|
||||
# 回滚迁移
|
||||
alembic downgrade -1
|
||||
```
|
||||
|
||||
### 7.2 版本控制
|
||||
|
||||
- 每次数据库变更都生成迁移脚本
|
||||
- 迁移脚本存储在 `alembic/versions/` 目录
|
||||
- 支持向前和向后迁移
|
||||
|
||||
## 8. 数据备份策略
|
||||
|
||||
### 8.1 备份方案
|
||||
|
||||
```bash
|
||||
# SQLite 备份
|
||||
cp data/yaoxiang.db data/yaoxiang_backup_$(date +%Y%m%d).db
|
||||
|
||||
# 或使用 sqlite3 命令
|
||||
sqlite3 data/yaoxiang.db ".backup 'data/yaoxiang_backup_$(date +%Y%m%d).db'"
|
||||
```
|
||||
|
||||
### 8.2 自动备份
|
||||
|
||||
可通过 cron 任务定期备份:
|
||||
|
||||
```bash
|
||||
# 每天凌晨2点备份
|
||||
0 2 * * * /path/to/backup_script.sh
|
||||
```
|
||||
Reference in New Issue
Block a user