2、数据库设计与建模:客户信息表结构设计

好,咱们直接进入正题。这一章聊的是数据库设计,说白了就是给客户数据「安个家」。我见过太多项目,前期表结构没想清楚,后期改得想哭。所以这一块,咱们一次搞定。

2.1 客户信息表:字段、类型与约束

先问个问题:客户信息表里到底该存什么?

我个人习惯,先把「必须有的」和「可能会有的」分开。必须有的,比如客户ID、姓名、联系方式。可能会有的,比如客户等级、备注信息。别一上来就搞几十个字段,后面维护起来头疼。

下面这张表,是我在多个项目中沉淀下来的核心结构。你直接拿去用,基本不会踩坑。

字段名 类型 约束 说明
id INTEGER PRIMARY KEY, AUTO INCREMENT 客户唯一标识,自增主键
name VARCHAR(100) NOT NULL 客户姓名,不能为空
phone VARCHAR(20) UNIQUE, NOT NULL 手机号,唯一且必填
email VARCHAR(100) UNIQUE 邮箱,可选但唯一
level ENUM('普通','VIP','SVIP') DEFAULT '普通' 客户等级,默认普通
created_at DATETIME DEFAULT CURRENT_TIMESTAMP 创建时间,自动生成
updated_at DATETIME ON UPDATE CURRENT_TIMESTAMP 更新时间,自动更新
注意:phone 字段我建议用 VARCHAR 而不是 INT。为什么?因为手机号可能以 0 开头,用 INT 会丢失前导零。我曾经有个同事就因为这个,数据导进去全乱了,排查了半天。

2.2 使用 SQLAlchemy 进行 ORM 建模

表结构定好了,接下来用代码把它「翻译」出来。我用的是 SQLAlchemy,Python 生态里最成熟的 ORM 框架。你想想看,如果每次操作数据库都要写原生 SQL,那得多累?ORM 就是帮你把表变成类,把行变成对象。

下面是我常用的建模方式:

from sqlalchemy import Column, Integer, String, Enum, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import func
import enum

Base = declarative_base()

class CustomerLevel(enum.Enum):
    NORMAL = "普通"
    VIP = "VIP"
    SVIP = "SVIP"

class Customer(Base):
    __tablename__ = "customers"

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(100), nullable=False, comment="客户姓名")
    phone = Column(String(20), unique=True, nullable=False, comment="手机号")
    email = Column(String(100), unique=True, comment="邮箱")
    level = Column(Enum(CustomerLevel), default=CustomerLevel.NORMAL, comment="客户等级")
    created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
    updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="更新时间")

    def __repr__(self):
        return f"<Customer(id={self.id}, name={self.name}, level={self.level})>"
小技巧:comment 参数一定要加。虽然它不影响运行,但后期维护时,你或者同事能直接通过代码知道每个字段是干嘛的。我习惯在建模阶段就把注释写清楚,省得后面再翻文档。

这里有个细节:server_defaultdefault 的区别。前者是在数据库层面设置默认值,后者是在 Python 层面。我建议时间字段用 server_default,这样即使你忘了传值,数据库也会自动补上。

2.3 数据库迁移与初始化

模型写好了,怎么把它变成真实的数据库表?手动建表?别闹了。我们用 Alembic,它是 SQLAlchemy 的官方迁移工具。

为什么要用迁移?因为项目是活的。今天加个字段,明天改个类型,总不能每次都删表重建吧?迁移工具能帮你记录每一次变更,还能回滚。

初始化步骤很简单:

  1. 安装 Alembic:pip install alembic
  2. 初始化:alembic init alembic
  3. 配置 alembic.ini 中的数据库连接字符串
  4. env.py 中导入你的模型:from your_model import Base
  5. 生成迁移脚本:alembic revision --autogenerate -m "init"
  6. 执行迁移:alembic upgrade head

嗯,这里要注意一点:--autogenerate 虽然方便,但它不是万能的。比如字段重命名,它可能会识别成「删除旧字段 + 新增新字段」,导致数据丢失。我曾经就因为这个,把生产环境的一个字段名改错了,还好有备份。

避坑指南:每次执行迁移前,先检查生成的脚本。别直接 upgrade。养成这个习惯,能省去很多麻烦。

最后,如果你只是想快速测试,也可以直接用 Base.metadata.create_all(engine) 来建表。但记住,这只适合开发环境。生产环境一定要用迁移工具。

好了,这一章的内容就这些。表结构设计、ORM 建模、迁移初始化,三步走完。下一章咱们聊聊如何用 Flask 把这些数据暴露成 API,到时候你就知道 ORM 有多香了。