下载工作台
Go 数据库实战

电商库表设计实战

试读上半部分 · 解锁后可读全文

第 7 章 · 电商库表设计实战

本章目标:在 shop-db 项目中完成 shop_db 电商核心库的完整 DDL walkthrough;逐表讲解 categoriesproductsusersordersorder_linescartscart_items 的字段含义、外键约束索引策略;理解 slug + is_published + price(分) 字段约定;输出与 gin-web ch05 GORM 模型字段对照表,为 ch08~ch12 的 Java 访问层打基础。

学时建议:5~6 小时(含 2 小时 DDL 跟练与 ER 图绘制)

前置:完成 go-database ch01~ch06(SQL 查询、JOIN、事务、DDL、ER 与范式);了解基本电商业务名词。


7.1 场景说明:从 ER 图到可执行 DDL

ch06 已将 shop_db 抽象为 ER 模型。本章把模型落地为 MySQL 8 可执行 DDL,作为 shop-db 与后续 毕业项目 ch17 的 schema 基线。

业务实体表名与其它模块关系
商品分类categoriesgin-web gorm.Model Category
商品productsgin-web gorm.Model Productslug/is_published
用户users简化版账户表
订单ordersgin-web 可扩展 Order
订单行order_lines下单快照价
购物车carts / cart_itemsgo-dev ch06 Cart 概念持久化
说明:教学项目路径 ~/go-learn/shop-db;数据库名 shop_db;对外 API 域名 https://api.example.com 仅为占位,不涉及任何企业内部仓库。

字段演进约定(全模块统一):

旧字段(gin-web ch05 示例)正式字段(shop-db ch07+)说明
skuslugURL 友好标识,如 wireless-mouse
active / is_activeis_published是否上架展示
price DECIMAL(10,2) / BigDecimalprice BIGINT(分)存储,避免浮点误差

7.2 全局 ER 关系图

┌─────────────┐       ┌─────────────┐       ┌─────────────┐
│ categories  │ 1   N │  products   │ N   M │    tags     │  (ch13 扩展,本章预留)
│ id, slug    │◄──────│ category_id │       │  (可选)     │
└─────────────┘       └──────┬──────┘       └─────────────┘
                             │
         ┌───────────────────┼───────────────────┐
         │ N                 │ N                 │ N
         ▼                   ▼                   ▼
┌─────────────┐       ┌─────────────┐       ┌─────────────┐
│ cart_items  │       │ order_lines │       │  (reviews)  │  ch17 扩展
│ cart_id     │       │ order_id    │       └─────────────┘
│ product_id  │       │ product_id  │
└──────┬──────┘       └──────┬──────┘
       │ N                 │ N
       ▼ 1                 ▼ 1
┌─────────────┐       ┌─────────────┐
│   carts     │       │   orders    │
│ user_id     │       │ user_id     │
└──────┬──────┘       └──────┬──────┘
       │ N                 │ N
       └─────────┬─────────┘
                 ▼ 1
          ┌─────────────┐
          │    users    │
          │ id, email   │
          └─────────────┘

关系摘要

关系类型外键位置ON DELETE 建议
Category → Product1:Nproducts.category_idRESTRICT(有商品禁删分类)
User → Order1:Norders.user_idRESTRICT
Order → OrderLine1:Norder_lines.order_idCASCADE
Product → OrderLine1:Norder_lines.product_idRESTRICT(保历史单价)
User → Cart1:1carts.user_id UNIQUECASCADE
Cart → CartItem1:Ncart_items.cart_idCASCADE
Product → CartItem1:Ncart_items.product_idRESTRICT

7.3 建库与字符集

MySQL 8(shop-db 默认):

CREATE DATABASE IF NOT EXISTS shop_db
  DEFAULT CHARACTER SET utf8mb4
  DEFAULT COLLATE utf8mb4_unicode_ci;

USE shop_db;

Docker 快速启动(可选):

docker run -d --name shop-mysql \
  -e MYSQL_ROOT_PASSWORD=root_pass \
  -e MYSQL_DATABASE=shop_db \
  -e MYSQL_USER=shop_user \
  -e MYSQL_PASSWORD=shop_pass \
  -p 3306:3306 \
  mysql:8.0
配置项教学值说明
库名shop_db与 python-database db-demo 同名便于对照
字符集utf8mb4支持 emoji 与完整 Unicode
引擎InnoDB支持事务与外键

7.4 表 1:categories(商品分类)

CREATE TABLE IF NOT EXISTS categories (
    id          BIGINT       NOT NULL AUTO_INCREMENT,
    name        VARCHAR(64)  NOT NULL,
    slug        VARCHAR(64)  NOT NULL,
    sort_order  INT          NOT NULL DEFAULT 0,
    created_at  DATETIME(3)  NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
    updated_at  DATETIME(3)  NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
                    ON UPDATE CURRENT_TIMESTAMP(3),
    PRIMARY KEY (id),
    UNIQUE KEY uk_categories_slug (slug),
    KEY idx_categories_sort (sort_order, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
字段类型约束说明
idBIGINTPK, AUTOsurrogate 主键
nameVARCHAR(64)NOT NULL展示名,如「数码配件」
slugVARCHAR(64)NOT NULL, UNIQUEURL 段,如 digital-accessories
sort_orderINTDEFAULT 0前台排序,越小越靠前
created_atDATETIME(3)DEFAULT now毫秒精度审计
updated_atDATETIME(3)ON UPDATE应用层或 DB 自动维护

设计要点

  • slug 全局唯一,供 /catalog/{slug}/ 路由使用。
  • 不在分类表存商品数量;用 COUNT(*) 或冗余字段(ch14 优化再议)。

7.5 表 2:products(商品)

CREATE TABLE IF NOT EXISTS products (
    id            BIGINT        NOT NULL AUTO_INCREMENT,
    category_id   BIGINT        NOT NULL,
    title         VARCHAR(128)  NOT NULL,
    slug          VARCHAR(128)  NOT NULL,
    description   TEXT          NULL,
    price         BIGINT        NOT NULL COMMENT '单价,单位:分',
    stock         INT           NOT NULL DEFAULT 0,
    is_published  TINYINT(1)    NOT NULL DEFAULT 0,
    created_at    DATETIME(3)   NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
    updated_at    DATETIME(3)   NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
                      ON UPDATE CURRENT_TIMESTAMP(3),
    PRIMARY KEY (id),
    UNIQUE KEY uk_products_slug (slug),
    KEY idx_products_category_published (category_id, is_published, created_at DESC),
    KEY idx_products_published_price (is_published, price),
    CONSTRAINT fk_products_category
        FOREIGN KEY (category_id) REFERENCES categories(id)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    CONSTRAINT chk_products_price CHECK (price >= 0),
    CONSTRAINT chk_products_stock CHECK (stock >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
字段类型约束说明
category_idBIGINTFK → categories所属分类
titleVARCHAR(128)NOT NULL商品标题
slugVARCHAR(128)UNIQUE商品 URL 标识
descriptionTEXT可空详情 HTML/Markdown
priceBIGINT≥0单价(分),5990 = ¥59.90
stockINT≥0可售库存
is_publishedTINYINT(1)0/11=上架,0=草稿/下架

价格(分)示例

展示价存储值 priceJava 转换
¥0.011priceCents / 100.0 展示用
¥59.905990Math.round(yuan * 100)BigDecimal
¥199.0019900禁止用 double 直接存库

索引策略 §7.5.1

索引名服务查询
idx_products_category_published(category_id, is_published, created_at DESC)分类页已上架商品列表
idx_products_published_price(is_published, price)全站按价排序、筛选
uk_products_slugslug详情页 /products/{slug}/

7.6 表 3:users(用户)

CREATE TABLE IF NOT EXISTS users (
    id            BIGINT        NOT NULL AUTO_INCREMENT,
    email         VARCHAR(255)  NOT NULL,
    password_hash VARCHAR(255)  NOT NULL,
    nickname      VARCHAR(64)   NOT NULL DEFAULT '',
    is_active     TINYINT(1)    NOT NULL DEFAULT 1,
    created_at    DATETIME(3)   NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
    updated_at    DATETIME(3)   NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
                      ON UPDATE CURRENT_TIMESTAMP(3),
    PRIMARY KEY (id),
    UNIQUE KEY uk_users_email (email),
    KEY idx_users_active (is_active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
字段说明
email登录账号,唯一
password_hashbcrypt/argon2 摘要,禁止存明文
nickname展示名,如 user-demo
is_active0=禁用,1=正常

7.7 表 4:ordersorder_lines(订单)

7.7.1 orders

CREATE TABLE IF NOT EXISTS orders (
    id          BIGINT        NOT NULL AUTO_INCREMENT,
    user_id     BIGINT        NOT NULL,
    order_no    VARCHAR(32)   NOT NULL,
    status      VARCHAR(16)   NOT NULL DEFAULT 'pending',
    total_cents BIGINT        NOT NULL DEFAULT 0,
    created_at  DATETIME(3)   NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
    updated_at  DATETIME(3)   NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
                    ON UPDATE CURRENT_TIMESTAMP(3),
    PRIMARY KEY (id),
    UNIQUE KEY uk_orders_order_no (order_no),
    KEY idx_orders_user_created (user_id, created_at DESC),
    KEY idx_orders_status (status, created_at DESC),
    CONSTRAINT fk_orders_user
        FOREIGN KEY (user_id) REFERENCES users(id)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    CONSTRAINT chk_orders_status
        CHECK (status IN ('pending', 'paid', 'shipped', 'cancelled')),
    CONSTRAINT chk_orders_total CHECK (total_cents >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
字段说明
order_no业务单号,如 ORD-20260819-0001,唯一
status状态机:pending → paid → shipped;cancelled 终态
total_cents订单总金额(分),可与明细汇总校验

以下内容需解锁后阅读

试读已结束。解锁本章 ¥5.00,或开通年度会员畅读全部教程。
年度会员 ¥199.00/年; 小紫 AI 工作台有效会员 ¥99.00/年

正文仅在服务端鉴权后下发,未付费无法获取下半部分内容。