You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

9.7 KiB

Database.md 规范优化

日期: 2026-01-28
类型: 文档优化
影响范围: .claude/skills/jointo-tech-stack/references/database.md

概述

database.md 规范文档进行全面优化,修复重复内容、错误示例、缺失规范,提升文档质量和一致性。

优化内容

1. 删除重复的基本约束(高优先级)

问题: "表设计规范 > 基本约束" 章节中第 4-7 条与其他章节重复。

修复:

  • 保留 8 条核心约束,删除重复内容
  • 确保每条约束唯一且清晰

修复后的基本约束:

  1. 命名规范: 表名和列名使用 snake_case
  2. 主键: 所有表使用 UUID v7 作为主键(应用层生成)
  3. 时间戳: 所有表包含 created_at, updated_at(使用 UTC aware datetime)
  4. 软删除: 使用可空的 deleted_at 时间戳
  5. 外键: ⚠️ 禁止使用数据库物理外键约束,在应用层保证引用完整性
  6. 索引: 所有关联字段必须创建索引以保证查询性能
  7. UUID 生成: ⚠️ 禁止使用数据库 server_default 生成 UUID,必须在应用层通过 default=generate_uuid 生成
  8. 注释: 使用 COMMENT ON TABLE/COLUMN 语法添加说明

2. 修复时间戳示例中的 datetime.utcnow(高优先级)

问题: "引用完整性保证 > 后台任务" 章节使用已废弃的 datetime.utcnow

修复:

# ❌ 错误
cutoff_date = datetime.utcnow() - timedelta(days=30)

# ✅ 正确
cutoff_date = datetime.now(timezone.utc) - timedelta(days=30)

影响: 确保所有示例代码符合项目时区规范。


3. 修复枚举类型迁移示例(高优先级)

问题: "枚举类型处理 > 数据库迁移" 章节的迁移脚本包含多个违反规范的内容:

  • 创建了外键约束(违反"禁止物理外键"规范)
  • 创建了数据库 UUID 生成函数(违反"禁止数据库函数"规范)
  • 缺少索引创建
  • 缺少表和列注释

修复:

-- ✅ 正确:使用 SMALLINT,无外键约束,应用层生成 UUID
CREATE TABLE folder_members (
    id UUID PRIMARY KEY,
    folder_id UUID NOT NULL,
    user_id UUID NOT NULL,
    
    -- 成员角色 (使用 SMALLINT 存储)
    role SMALLINT NOT NULL DEFAULT 3 CHECK (role IN (1, 2, 3)),
    
    created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- 表级注释
COMMENT ON TABLE folder_members IS '文件夹成员表 - 应用层保证引用完整性';

-- 列级注释
COMMENT ON COLUMN folder_members.id IS '成员记录唯一标识';
COMMENT ON COLUMN folder_members.folder_id IS '文件夹 ID - 应用层验证';
COMMENT ON COLUMN folder_members.user_id IS '用户 ID - 应用层验证';
COMMENT ON COLUMN folder_members.role IS '成员角色:1=owner, 2=editor, 3=viewer';
COMMENT ON COLUMN folder_members.created_at IS '创建时间(UTC)';
COMMENT ON COLUMN folder_members.updated_at IS '更新时间(UTC)';

-- 索引(必须创建,因为无外键约束)
CREATE INDEX idx_folder_members_folder_id ON folder_members(folder_id);
CREATE INDEX idx_folder_members_user_id ON folder_members(user_id);
CREATE INDEX idx_folder_members_folder_user ON folder_members(folder_id, user_id);

4. 添加 Relationship 配置到 Model 示例(中优先级)

问题: "表设计规范 > 表结构示例" 中的 Folder Model 缺少 Relationship 配置。

修复: 添加完整的 Relationship 配置示例:

from typing import TYPE_CHECKING, Optional
from sqlmodel import Relationship

if TYPE_CHECKING:
    from app.models.user import User

class Folder(SQLModel, table=True):
    # ... 字段定义 ...
    
    # Relationship 配置(使用 primaryjoin,因为无物理外键)
    owner: Optional["User"] = Relationship(
        sa_relationship_kwargs={
            "primaryjoin": "Folder.owner_id == User.user_id",
            "foreign_keys": "[Folder.owner_id]",
        }
    )
    
    parent_folder: Optional["Folder"] = Relationship(
        sa_relationship_kwargs={
            "primaryjoin": "Folder.parent_folder_id == Folder.id",
            "foreign_keys": "[Folder.parent_folder_id]",
        }
    )

价值: 为开发者提供完整的 Model 定义参考。


5. 添加时区规范交叉引用(低优先级)

问题: "表设计规范 > 表结构示例" 中的时间戳字段缺少规范引用。

修复: 在时间戳字段定义处添加注释:

# 时间戳(使用 UTC aware datetime)
# 详细规范请参考:backend.md > 时间与时区规范
created_at: datetime = Field(
    default_factory=lambda: datetime.now(timezone.utc),
    description="创建时间(UTC)"
)

价值: 引导开发者查阅完整的时区规范。


6. 更新目录,添加"相关规范"章节(低优先级)

问题: 文档目录缺少"相关规范"章节。

修复: 在目录中添加:

## 目录

- [PostgreSQL 17 特性](#postgresql-17-特性)
- [表设计规范](#表设计规范)
- [引用完整性保证](#引用完整性保证)
- [枚举类型处理](#枚举类型处理)
- [索引策略](#索引策略)
- [迁移管理](#迁移管理)
- [相关规范](#相关规范)  <!-- 新增 -->

7. 添加完整的 Alembic 迁移脚本示例(低优先级)

问题: "迁移管理" 章节缺少完整的迁移脚本示例。

修复: 添加完整的迁移脚本示例,包含:

  • 创建表
  • 创建索引
  • 添加表注释
  • 添加列注释(使用循环执行)
"""创建 folders 表

Revision ID: xxx
Revises: 
Create Date: 2026-01-28
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql


def upgrade() -> None:
    """升级"""
    # 1. 创建表
    op.create_table(
        'folders',
        sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True),
        sa.Column('name', sa.String(255), nullable=False),
        # ... 其他列 ...
    )
    
    # 2. 创建索引
    op.create_index('idx_folders_name', 'folders', ['name'])
    # ... 其他索引 ...
    
    # 3. 添加表注释
    op.execute("COMMENT ON TABLE folders IS '文件夹表 - 应用层保证引用完整性'")
    
    # 4. 添加列注释
    comments = {
        'id': '文件夹唯一标识',
        'name': '文件夹名称',
        # ... 其他列 ...
    }
    
    for column, comment in comments.items():
        op.execute(f"COMMENT ON COLUMN folders.{column} IS '{comment}'")


def downgrade() -> None:
    """降级"""
    op.drop_table('folders')

8. 添加"相关规范"章节(低优先级)

问题: 文档末尾缺少与其他规范的交叉引用。

修复: 添加"相关规范"章节:

## 相关规范

### 时间与时区规范

详细的时间与时区规范请参考:**backend.md > 时间与时区规范**

**核心要点**- 所有 datetime 使用 `datetime.now(timezone.utc)`
- 数据库使用 `TIMESTAMP WITHOUT TIME ZONE`
- Model 层使用 `default_factory=lambda: datetime.now(timezone.utc)`

### COMMENT 语法规范

PostgreSQL 使用 `COMMENT ON` 语法:

```sql
-- ✅ 正确
COMMENT ON TABLE table_name IS '表说明';
COMMENT ON COLUMN table_name.column_name IS '列说明';

-- ❌ 错误:PostgreSQL 不支持行内 COMMENT
CREATE TABLE wrong_table (
    id UUID PRIMARY KEY COMMENT '主键'  -- 语法错误
);

Relationship 配置规范

因为禁止物理外键,所有 Relationship 必须使用 primaryjoin

from typing import TYPE_CHECKING
from sqlmodel import Relationship

if TYPE_CHECKING:
    from app.models.related_model import RelatedModel

class CurrentModel(SQLModel, table=True):
    related_id: UUID = Field(
        sa_column=Column(PG_UUID(as_uuid=True), nullable=False, index=True),
        description="关联 ID - 应用层验证"
    )
    
    related: Optional["RelatedModel"] = Relationship(
        sa_relationship_kwargs={
            "primaryjoin": "CurrentModel.related_id == RelatedModel.id",
            "foreign_keys": "[CurrentModel.related_id]",
        }
    )

---

## 优化效果

### 文档质量提升

| 指标 | 优化前 | 优化后 |
|------|--------|--------|
| 重复内容 | 4-7 条重复约束 | 0 条重复 |
| 错误示例 | 3 处(utcnow、外键、数据库函数) | 0 处 |
| 缺失规范 | 缺少 Relationship、时区引用 | 完整覆盖 |
| 交叉引用 | 无 | 3 处(时区、COMMENT、Relationship) |
| 完整示例 | 缺少完整迁移脚本 | 完整示例 |

### 规范一致性

- ✅ 所有示例符合"禁止物理外键"规范
- ✅ 所有示例符合"禁止数据库函数"规范
- ✅ 所有示例符合"应用层生成 UUID"规范
- ✅ 所有示例符合"时区规范"(使用 `datetime.now(timezone.utc)`)
- ✅ 所有示例符合"COMMENT 语法规范"(使用 `COMMENT ON`)
- ✅ 所有示例包含必要的索引创建
- ✅ 所有示例包含 Relationship 配置

---

## 相关文件

- `.claude/skills/jointo-tech-stack/references/database.md` - 已优化
- `.claude/skills/jointo-tech-stack/references/backend.md` - 时区规范参考
- `docs/architecture/datetime-timezone-standards.md` - 完整时区规范文档

---

## 后续建议

1. **定期审查**: 每次添加新规范时,检查是否与现有内容重复
2. **示例验证**: 所有代码示例应通过实际测试验证
3. **交叉引用**: 相关规范之间添加明确的引用链接
4. **版本控制**: 重大规范变更时更新文档版本号

---

## 总结

本次优化全面提升了 `database.md` 的质量和一致性,删除了重复内容,修复了错误示例,补充了缺失规范,添加了完整的交叉引用。文档现在完全符合项目的架构约束,为开发者提供了清晰、准确、完整的数据库设计规范。