Day 3 | MySQL + 数据库设计:前端视角看不到的世界


前端的数据世界 vs 后端的数据世界

前端开发者每天和数据打交道,但数据是这样的:

// 你眼里的"数据"
const accident = {
  id: 1,
  title: '迎泽大街交通事故',
  severity: '严重',
  location: { lng: 112.549, lat: 37.857 },
  imageUrls: ['https://minio.../img1.jpg', 'https://minio.../img2.jpg']
}

后端眼里同一份数据,是这样的:

-- t_accident 表(事故主表)
SELECT * FROM t_accident WHERE id = 1;

+----+---------------------+---------+------------+-----------+
| id | title               | severity| longitude  | latitude  |
+----+---------------------+---------+------------+-----------+
|  1 | 迎泽大街交通事故     | 严重    | 112.549    | 37.857    |
+----+---------------------+---------+------------+-----------+

-- t_accident_image 表(事故图片关联表)
SELECT * FROM t_accident_image WHERE accident_id = 1;

+----+-------------+------------------------------+
| id | accident_id | url                          |
+----+-------------+------------------------------+
|  1 |           1 | https://minio.../img1.jpg    |
|  2 |           1 | https://minio.../img2.jpg    |
+----+-------------+------------------------------+

前端一个对象,后端可能是三张表 + 两次 JOIN + 一次聚合查询。这就是为什么前端学后端,最难的一关是数据库设计思维


数据库设计的核心概念(前端人听得懂的版本)

1. 表 = 类型,字段 = 属性,外键 = 关联

-- 事故表(主表)
CREATE TABLE t_accident (
    id          BIGINT PRIMARY KEY AUTO_INCREMENT,
    title       VARCHAR(255)  NOT NULL COMMENT '事故标题',
    severity    VARCHAR(20)   NOT NULL COMMENT '严重程度:严重/一般/轻微',
    longitude   DECIMAL(10, 6) COMMENT '经度',
    latitude    DECIMAL(10, 6) COMMENT '纬度',
    location    VARCHAR(500)   COMMENT '地点描述',
    description TEXT           COMMENT '事故描述',
    occur_time  DATETIME       COMMENT '发生时间',
    create_time DATETIME       DEFAULT CURRENT_TIMESTAMP,
    update_time DATETIME       DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

2. 主键、外键、索引——为什么你的查询很慢

-- 给经纬度加索引(高频查询字段)
CREATE INDEX idx_location ON t_accident(longitude, latitude);

-- 给时间加索引(按时间范围查询)
CREATE INDEX idx_occur_time ON t_accident(occur_time);

-- 给严重程度加索引(分类统计)
CREATE INDEX idx_severity ON t_accident(severity);

前端类比: 索引就像书的目录。查"第5章"不需要翻完前4章——这就是索引的作用。给 WHERE longitude = ? AND latitude = ? 经常查的字段加索引。

3. 一对多关系:事故 → 图片

CREATE TABLE t_accident_image (
    id          BIGINT PRIMARY KEY AUTO_INCREMENT,
    accident_id BIGINT         NOT NULL,
    url         VARCHAR(500)   NOT NULL,
    type        VARCHAR(20)    COMMENT 'image/video',
    FOREIGN KEY (accident_id) REFERENCES t_accident(id)
);

前端类比: accident.images = [] 在前端是数组,在后端是一张独立的表,用 accident_id 关联回来。


MyBatis-Plus:让 SQL 写得像前端查询

纯手写 SQL 对前端开发者来说门槛太高。MyBatis-Plus(MyBatis 的增强工具)让这件事变得像调用方法一样简单:

// Mapper 接口(对应一张表)
@Mapper
public interface AccidentMapper extends BaseMapper<Accident> {
    // MyBatis-Plus 自动生成:SELECT * FROM t_accident WHERE id = ?
    // 你只需要写复杂查询
}

// Service
@Service
public class AccidentService {
    @Autowired private AccidentMapper accidentMapper;

    // 按 ID 查询(自动生成,不用写 SQL)
    public Accident getById(Long id) {
        return accidentMapper.selectById(id);
    }

    // 按严重程度统计(手写 SQL)
    public Long countBySeverity(String severity) {
        return accidentMapper.selectCount(
            new LambdaQueryWrapper<Accident>()
                .eq(Accident::getSeverity, severity)
        );
    }
}

前端类比: accidentMapper.selectById(id) 等于 store.state.accidents[id]。只是数据来源从内存变成了数据库。


AI 辅助写 SQL 的实战方法

真实项目中,SQL 往往是最需要 AI 辅助的部分。以下是让 AI 帮你写 SQL 的正确姿势:

场景1:建表语句生成

Prompt:"我有一个事故记录表 t_accident(字段:id, title, severity, longitude, latitude, occur_time),
请生成 MySQL 建表语句,包含主键、自动更新时间、合适的索引,用于事故一张图的热力图查询(按经纬度范围查询)。"

场景2:复杂统计查询

Prompt:"我需要一条 SQL 统计每个严重程度的事故数量,并计算平均发生间隔。
表 t_accident,字段:id, severity(严重/一般/轻微), occur_time(DATETIME)。
MySQL 8.0 环境。"

场景3:数据迁移

Prompt:"我要把 t_accident.image_urls(JSON数组字段)里的图片URL拆分到 t_accident_image 表,
每张图片一行,用 Python pymysql 执行。表结构和数据如下:[粘贴表结构]"

今日任务清单

  1. 安装并启动 MySQL:Windows 上建议用 phpStudy 快速启动,验证连接:
    import pymysql
    conn = pymysql.connect(host='localhost', user='root', password='123456', database='accident_db')
    print(conn.cursor().execute("SELECT 1"))
    conn.close()
    
  2. 阅读真实项目的表结构:查看 accident_db 下的所有表,理解 t_accidentt_causet_user 之间的关系
  3. 让 AI 生成一条 JOIN 查询:关联 t_accidentt_accident_image,返回事故及其所有图片URL(JSON 数组格式)

思维升级

数据库不是"存储数据的地方",是一个有结构、有约束、有性能要求的数据系统
前端学后端,学会用 SQL 思考数据,而不是只学怎么 CRUD。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐