MySQL 入门教程 · 第一课

102次阅读
没有评论

共计 4606 个字符,预计需要花费 12 分钟才能阅读完成。

0. 快速上手

A. 本机安装(图形界面习惯)

  • Windows:安装 MySQL 8.0 + Workbench,安装时记住 root 密码。
  • macOS(Homebrew):
brew install mysql
brew services start mysql
mysql -uroot

B. Docker(最干净)

docker run --name mysql8 -e MYSQL_ROOT_PASSWORD=Passw0rd! \
  -p 3306:3306 -d mysql:8.0
# 进入
docker exec -it mysql8 mysql -uroot -p

1. 第一次连接与基础设置

进入 MySQL 后,先做三件小事:创建业务库、设置字符集、建立普通账号。

-- 1) 新建数据库(统一用 utf8mb4 防止中文 / 表情乱码)CREATE DATABASE shop
  DEFAULT CHARACTER SET utf8mb4
  DEFAULT COLLATE utf8mb4_0900_ai_ci;

-- 2) 创建业务账号并授予最小权限
CREATE USER 'shop_user'@'%' IDENTIFIED BY 'Shop@123';
GRANT ALL PRIVILEGES ON shop.* TO 'shop_user'@'%';
FLUSH PRIVILEGES;

-- 3) 切换到业务库
USE shop;

2. 数据模型(最小可用电商示例)

四张表:用户、商品、订单、明细。范式友好、外键清晰。

-- 用户
CREATE TABLE users (
  user_id     BIGINT PRIMARY KEY AUTO_INCREMENT,
  name        VARCHAR(100) NOT NULL,
  email       VARCHAR(255) UNIQUE,
  created_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

-- 商品
CREATE TABLE products (
  product_id  BIGINT PRIMARY KEY AUTO_INCREMENT,
  title       VARCHAR(200) NOT NULL,
  price       DECIMAL(10,2) NOT NULL CHECK (price >= 0),
  stock       INT NOT NULL DEFAULT 0,
  created_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

-- 订单(主表)CREATE TABLE orders (
  order_id    BIGINT PRIMARY KEY AUTO_INCREMENT,
  user_id     BIGINT NOT NULL,
  status      ENUM('paid','canceled','refunded') NOT NULL DEFAULT 'paid',
  amount      DECIMAL(10,2) NOT NULL,
  created_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT fk_orders_user FOREIGN KEY (user_id)
    REFERENCES users(user_id)
) ENGINE=InnoDB;

-- 订单明细(子表)CREATE TABLE order_items (
  item_id     BIGINT PRIMARY KEY AUTO_INCREMENT,
  order_id    BIGINT NOT NULL,
  product_id  BIGINT NOT NULL,
  quantity    INT NOT NULL CHECK (quantity > 0),
  unit_price  DECIMAL(10,2) NOT NULL,
  CONSTRAINT fk_items_order   FOREIGN KEY (order_id)   REFERENCES orders(order_id),
  CONSTRAINT fk_items_product FOREIGN KEY (product_id) REFERENCES products(product_id)
) ENGINE=InnoDB;

插入一点练习数据:

INSERT INTO users (name,email) VALUES
 ('Alice','alice@example.com'),('Bob','bob@example.com'),('Carol','carol@example.com');

INSERT INTO products (title,price,stock) VALUES
 ('机械键盘',399.00,50),('人体工学鼠标',259.00,100),('27 寸显示器',1699.00,20);

-- 一笔订单(Alice 买了两样)INSERT INTO orders (user_id,status,amount) VALUES (1,'paid',399.00+259.00);
INSERT INTO order_items (order_id,product_id,quantity,unit_price) VALUES
 (1,1,1,399.00),
 (1,2,1,259.00);

3. CRUD:会查会改会删(谨慎)

-- C: 新增商品 / 用户
INSERT INTO products (title,price,stock) VALUES ('USB-C 集线器',159.00,80);

-- R: 查询(挑列 + 条件 + 排序 + 限制)SELECT product_id, title, price
FROM products
WHERE price BETWEEN 100 AND 500
ORDER BY price DESC
LIMIT 5;

-- U: 更新(只改需要的行)UPDATE products SET stock = stock - 1
WHERE product_id = 1 AND stock > 0;

-- D: 删除(务必加条件)DELETE FROM products WHERE product_id = 999;  -- 示例:基本无影响

4. 聚合与分组(GROUP BY / HAVING)

-- 每位用户的订单数与总金额(仅 paid)SELECT u.user_id, u.name,
       COUNT(o.order_id) AS n_orders,
       SUM(o.amount)     AS revenue
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id AND o.status='paid'
GROUP BY u.user_id, u.name
HAVING COALESCE(SUM(o.amount),0) >= 0
ORDER BY revenue DESC;

要点

  • WHERE 发生在分组前,HAVING 发生在分组后。
  • COALESCE 处理空值,避免 NULL 参与计算。

5. 连接(JOIN)与避免重复计数

-- 订单 + 用户(横向补充)SELECT o.order_id, u.name, o.amount, o.created_at
FROM orders o
JOIN users u ON o.user_id = u.user_id;

-- 订单 GMV = 明细数量 × 单价(先在明细汇总再回连,避免倍增)SELECT o.order_id, u.name,
       SUM(oi.quantity * oi.unit_price) AS gmv
FROM orders o
JOIN users u     ON o.user_id = u.user_id
JOIN order_items oi ON o.order_id = oi.order_id
GROUP BY o.order_id, u.name
ORDER BY gmv DESC;

6. 视图、约束与事务(基础三件套)

视图:把常用查询固化

CREATE OR REPLACE VIEW v_user_revenue AS
SELECT u.user_id, u.name, COALESCE(SUM(o.amount),0) AS revenue
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id AND o.status='paid'
GROUP BY u.user_id, u.name;
SELECT * FROM v_user_revenue ORDER BY revenue DESC;

事务:要么都成功,要么都回滚

START TRANSACTION;
  INSERT INTO orders (user_id,status,amount) VALUES (2,'paid',1699.00);
  INSERT INTO order_items (order_id,product_id,quantity,unit_price)
    VALUES (LAST_INSERT_ID(),3,1,1699.00);
COMMIT;  -- 出错就 ROLLBACK

约束:用数据库替你“守规则”

  • 外键保证“订单一定属于存在的用户”。
  • CHECK (quantity> 0) 防止负数。
  • UNIQUE(email) 防止重复注册。

7. 索引初识与 EXPLAIN(性能从理解开始)

建立索引(高选择性列 / 连接键 / 过滤常用列)

CREATE INDEX idx_orders_user_created ON orders(user_id, created_at);
CREATE INDEX idx_products_title ON products(title);

查看执行计划

EXPLAIN
SELECT order_id FROM orders
WHERE user_id = 1 AND created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY);

关注 type(最好是 ref/range/const 而不是 ALL)、key 是否命中、rows 预估。

口诀:联合索引遵循“左前缀”。上例 user_id, created_at 的索引能支持 WHERE user_id = ?WHERE user_id=? AND created_at>=?,但 能只靠它高效支持 WHERE created_at>=?


8. 备份与恢复(最基本操作)

# 备份一个库
mysqldump -h127.0.0.1 -uroot -p --databases shop > shop.sql

# 只备份表结构(无数据)mysqldump -uroot -p shop --no-data > schema.sql

# 恢复
mysql -uroot -p < shop.sql

9. 常见坑与经验法则(入门就规避)

  • 字符集:统一 utf8mb4,别用历史 utf8(那是“阉割版”)。
  • 金钱:用 DECIMAL(10,2),不要 FLOAT/DOUBLE
  • 时间:业务推荐 DATETIME(时区独立),跨时区 / 审计再考虑 TIMESTAMP
  • 自增主键BIGINT AUTO_INCREMENT 足够耐用。
  • 布尔TINYINT(1) + 约束 / 约定。
  • 删除数据:先 SELECT ... WHERE ... 验证条件再 DELETE
  • JOIN 倍增:先在明细 GROUP BY 再回连,或确保连接键唯一。

10. 练习(建议动手 15–20 分钟)

  1. 新增两位用户、两件商品;插入 3 笔订单(含至少一笔 2 个明细)。
  2. 写一个查询:统计最近 30 天每位用户的 订单数、总金额、客单价(总金额 / 订单数),按总金额倒序。
  3. orders(status, created_at) 建合适索引,验证你的查询 EXPLAIN 不再是全表扫描。
  4. 用事务模拟“下单减库存”:下单成功则 products.stock 减对应数量,任何一步失败整体回滚。
  5. 创建视图 v_daily_gmv(date, gmv):按天汇总 GMV(只统计 paid)。

正文完
 1
一诺
版权声明:本站原创文章,由 一诺 于2025-10-10发表,共计4606字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
验证码