现在把 Table、主键、外键和约束放进一个完整但简单的在线商店。系统需要保存用户、商品、订单,以及每个订单具体包含哪些商品。我们使用 users、products、orders 和 order_items 四张 Table。
这与前面的简化模型有一处重要变化:不再直接把 product_id 放在 orders。真实订单可能包含多个商品,所以 order_items 专门记录“哪笔订单包含哪个商品,以及买了多少”。
users:账号资料
id 唯一识别用户;name 与 email 必填;email 还要唯一,避免两个账号使用同一邮箱。
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(200) NOT NULL UNIQUE
);products:商品的正式资料
商品必须有名称与精确价格,category 可以暂时未知。
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
category VARCHAR(100)
);orders:谁在何时下单
orders 记录用户、日期和状态。user_id 引用 users.id,所以订单必须属于真实用户;status 默认 pending。
CREATE TABLE orders (
id INT PRIMARY KEY,
user_id INT NOT NULL,
order_date DATE NOT NULL,
status VARCHAR(50) DEFAULT 'pending',
FOREIGN KEY (user_id) REFERENCES users(id)
);order_items:订单里的每一种商品
每条 Row 代表一笔订单中的一种商品。order_id 指向 orders,product_id 指向 products,quantity 记录数量。同一 order_id 可以出现多次,于是一笔订单可以包含任意数量的商品。
CREATE TABLE order_items (
id INT PRIMARY KEY,
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL,
FOREIGN KEY (order_id) REFERENCES orders(id),
FOREIGN KEY (product_id) REFERENCES products(id)
);订单 1001 的三条明细
| 商品 | 数量 |
|---|---|
| Keyboard | 1 |
| Mouse | 2 |
| Webcam | 1 |
| id | order_id | product_id | quantity |
|---|---|---|---|
| 1 | 1001 | 1 | 1 |
| 2 | 1001 | 2 | 2 |
| 3 | 1001 | 5 | 1 |
四张 Table 如何连接
一个 User 可以有多个 Orders;一个 Order 可以有多个 Order Items;一个 Product 也可以出现在多个 Order Items。每类正式信息只保存在自己的 Table 中。
users.id1 → manyorders.user_idorders.id1 → manyorder_items.order_idproducts.id1 → manyorder_items.product_id为什么不在 orders 增加 product_1、product_2?
下一笔订单可能有四个商品,之后又可能有十个。若不断新增 Column,结构会变得奇怪且难以查询。order_items 用 Row 表示数量变化:订单有 1 个还是 100 个商品,Table 结构都不用改变。这是重要的关系型设计思想——不要因为记录数量变化而不断增加 Column。
JOIN 重新组成完整订单
拆开保存不等于看不懂。连接四张表后,可以返回订单编号、用户名、商品名、数量和价格。
SELECT o.id AS order_id, u.name AS user_name,
p.name AS product_name, oi.quantity, p.price
FROM orders AS o
INNER JOIN users AS u ON o.user_id = u.id
INNER JOIN order_items AS oi ON o.id = oi.order_id
INNER JOIN products AS p ON oi.product_id = p.id;知识测验
知识测验
知识测验
设计活动报名系统
一个用户能报名多个活动,一个活动也有多位用户。设计 users、events、registrations 三张 Table:列出主要字段、主键、外键和必要约束。registrations 还要保存 registered_at 与 status。最后说明为什么不能在 events 中放 attendee_1、attendee_2。