问题与目标
文件适合保存简单数据,但并发写入、条件查询和关系约束很快会变复杂。关系数据库用表组织数据,并通过 SQL 提供一致的查询和修改接口。
完成标准:能连接 MySQL,创建数据库和两张有关联的表,完成插入、查询、更新和删除。本篇只建立基础模型,不展开索引优化和并发事务。
核心概念
数据库包含表,表由字段和记录构成。主键唯一标识记录,外键表达表间关系。字段类型应表达业务含义:金额不用浮点数,时间不用随意字符串,长度有边界的文本可用 VARCHAR。
SQL 大致分为:DDL 定义结构,如 CREATE;DML 修改数据,如 INSERT、UPDATE、DELETE;DQL 查询数据,如 SELECT。
示例使用 projects 和 tasks:一个项目包含多个任务,任务通过 project_id 指向项目。
普通文件并非不能存数据,而是随着需求增长,需要自己处理并发、约束、条件查询、备份和故障恢复。关系数据库把这些能力放进统一系统。表关系常见三种:一对一适合拆分可选详情,一对多由“多”的一侧保存外键,多对多需要中间表。当前项目—任务就是一对多。
类型选择以业务边界为准:
| 数据 | 常用类型 | 注意点 |
|---|---|---|
| 主键 | BIGINT UNSIGNED | 不向业务暴露递增规律 |
| 短文本 | VARCHAR(n) | n 是业务长度边界 |
| 长文本 | TEXT | 不能随意设置很大的索引前缀 |
| 精确小数 | DECIMAL(p,s) | 金额不使用二进制浮点数 |
| 时间点 | TIMESTAMP/DATETIME | 先统一时区语义 |
| 可选值 | 可空字段 | NULL 不等于空字符串或 0 |
可运行实现
Ubuntu 可安装服务和客户端:
sudo apt update
sudo apt install -y mysql-server mysql-client
sudo systemctl status mysql
sudo mysql
进入客户端后执行:
CREATE DATABASE engineering_notes
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
USE engineering_notes;
CREATE TABLE projects (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL UNIQUE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE tasks (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
project_id BIGINT UNSIGNED NOT NULL,
title VARCHAR(200) NOT NULL,
status ENUM('todo', 'doing', 'done') NOT NULL DEFAULT 'todo',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_tasks_project
FOREIGN KEY (project_id) REFERENCES projects(id)
ON DELETE CASCADE
);
SHOW TABLES;
DESCRIBE projects;
SHOW CREATE TABLE tasks;
INSERT INTO projects (name) VALUES ('engineering-basics');
INSERT INTO tasks (project_id, title, status)
VALUES
(1, 'configure Linux environment', 'done'),
(1, 'connect MySQL from Python', 'todo');
SELECT id, title, status FROM tasks ORDER BY id;
UPDATE tasks SET status = 'doing' WHERE id = 2;
DELETE FROM tasks WHERE id = 2 AND status = 'done';
最后一条删除不会命中,因为任务状态是 doing。先查询再精确修改,是操作数据时应保留的习惯。
这组 SQL 的输入是项目和任务记录,输出是带主键、状态和创建时间的关系数据。可用 SELECT ROW_COUNT() 检查上一条修改影响的行数,并再次查询验证最终状态。
结构变化使用 ALTER TABLE,例如为任务增加可选截止时间:
ALTER TABLE tasks ADD COLUMN due_at DATETIME NULL AFTER status;
应用不要使用 root 连接。由管理员创建最小权限账号,主机部分必须与实际部署来源一致:
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'replace-with-strong-password';
GRANT SELECT, INSERT, UPDATE, DELETE
ON engineering_notes.* TO 'app_user'@'localhost';
SHOW GRANTS FOR 'app_user'@'localhost';
密码只是占位符,不能提交到文档配套仓库。若应用通过 127.0.0.1 连接,要实际验证账号的 host 匹配和认证行为。
常见问题与排查
Access denied:核对连接用户、认证方式、主机来源和权限,不要把 root 账号用于应用。- 中文乱码:数据库、表、连接都应使用
utf8mb4,只改其中一层可能仍乱码。 - 外键创建失败:父子字段类型必须兼容,父表字段要有索引,已有脏数据也会阻止约束建立。
UPDATE/DELETE影响整表:遗漏WHERE是高风险操作,先执行同条件SELECT。- 用序号假设主键:自动递增值可能有空洞,应用应读取插入结果而不是推算 ID。
localhost账号无法从其他主机连接:MySQL 账号由“用户名 + 来源主机”共同确定;不要为了省事开放'%'并授予过大权限。
小结
关系模型的价值不仅是把数据放进表,还在于类型、主键和外键共同守住数据边界。基础闭环是建模、写入、精确查询,再安全修改。
许可协议:CC BY-NC 4.0
更新于 2 小时前
觉得文章有帮助?点个赞吧!
0 条评论


