Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > mysql数据定义与数据操作

MySQL数据定义与数据操作综合实战示例

作者:troy128

本文系统讲解MySQL的数据定义语言(DDL)与数据操作语言(DML)核心技能,涵盖数据库与表的创建、修改、删除,以及数据的增删改查操作,通过实例详解 CREATE、ALTER、INSERT、SELECT、UPDATE、DELETE 等语句,并重点介绍事务的 ACID 特性及 BEGIN/COMMIT/ROLLBACK 使用

这篇是 MySQL 入门系列的第二篇,正好接着你之前看的底层存储机制,把最常用的 DDL(数据定义)和 DML(数据操作)语法捋一遍。核心就一句话:‌DDL 管表结构,DML 管表数据,两者别混用。

1. 引言

在上一篇文章中,我们介绍了 MySQL 的基本概念、安装配置以及常用客户端工具的使用。本篇将深入 MySQL 的核心操作——数据定义语言(DDL)与数据操作语言(DML),带你掌握建库、建表、增删改查等最常用的技能。

无论你是刚接触数据库的新手,还是希望系统梳理基础知识的开发者,本文都会用清晰的示例和通俗的解释,帮你快速上手 MySQL 的数据定义与数据操作。

2. 数据定义语言(DDL)基础

数据定义语言(Data Definition Language,DDL)用于定义和管理数据库对象,主要包括数据库、表、索引、视图等。DDL 的核心操作可以概括为「增删改查」四个字:创建(CREATE)、删除(DROP)、修改(ALTER)和查看(SHOW / DESCRIBE)。

2.1 数据库的创建与删除

创建数据库使用 CREATE DATABASE 语句,可以同时指定字符集和排序规则:

-- 创建数据库,指定 utf8mb4 字符集
CREATE DATABASE IF NOT EXISTS mydb
  DEFAULT CHARACTER SET utf8mb4
  DEFAULT COLLATE utf8mb4_general_ci;

删除数据库使用 DROP DATABASE,操作前请务必确认,因为该操作不可恢复:

DROP DATABASE IF EXISTS mydb;

查看当前实例下有哪些数据库:

SHOW DATABASES;

2.2 表的创建

表是数据库中存储数据的基本单位。创建表时需要定义字段名、数据类型以及约束条件:

CREATE TABLE IF NOT EXISTS student (
  id INT UNSIGNED AUTO_INCREMENT COMMENT '主键ID',
  name VARCHAR(50) NOT NULL COMMENT '姓名',
  age TINYINT UNSIGNED DEFAULT 0 COMMENT '年龄',
  email VARCHAR(100) UNIQUE COMMENT '邮箱',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生表';

常用数据类型速查:

数据类型说明典型用途
INT / BIGINT整数主键、计数
VARCHAR(n)变长字符串姓名、地址
CHAR(n)定长字符串固定长度编码
DECIMAL(p,s)精确小数金额
DATE / DATETIME日期 / 日期时间生日、创建时间
TEXT长文本文章内容
BOOLEAN / TINYINT(1)布尔状态标记

2.3 修改表结构

使用 ALTER TABLE 可以动态调整表结构,常见操作如下:

-- 新增字段
ALTER TABLE student ADD COLUMN phone VARCHAR(20) COMMENT '电话';
-- 修改字段类型
ALTER TABLE student MODIFY COLUMN age SMALLINT UNSIGNED DEFAULT 0 COMMENT '年龄';
-- 重命名字段
ALTER TABLE student CHANGE COLUMN email contact_email VARCHAR(100) COMMENT '联系邮箱';
-- 删除字段
ALTER TABLE student DROP COLUMN phone;

2.4 删除表

DROP TABLE IF EXISTS student;

注意:DROP TABLE 会连同表结构和数据一起删除,执行前务必做好备份。

3. 数据操作语言(DML)核心

数据操作语言(Data Manipulation Language,DML)用于对表中的数据进行增、删、改、查,是日常开发中使用最频繁的 SQL 语句。

3.1 插入数据(INSERT)

单行插入:

INSERT INTO student (name, age, email)
VALUES ('张三', 20, 'zhangsan@example.com');

多行批量插入:

INSERT INTO student (name, age, email) VALUES
('李四', 22, 'lisi@example.com'),
('王五', 21, 'wangwu@example.com'),
('赵六', 23, 'zhaoliu@example.com');

插入时也可以省略字段列表,但必须按表定义的字段顺序提供全部值(不推荐,易出错):

INSERT INTO student VALUES (NULL, '孙七', 24, 'sunqi@example.com', NOW());

3.2 查询数据(SELECT)

查询是 DML 中使用频率最高的操作。基础查询语法:

-- 查询所有字段
SELECT * FROM student;
-- 查询指定字段
SELECT id, name, age FROM student;
-- 带条件查询
SELECT id, name, age FROM student WHERE age > 20;
-- 排序
SELECT id, name, age FROM student ORDER BY age DESC;
-- 分页
SELECT id, name, age FROM student ORDER BY id LIMIT 10 OFFSET 0;

常用条件与运算符:

运算符说明示例
= / !=等于 / 不等于WHERE age = 20
> / < / >= / <=比较WHERE age >= 20
BETWEEN … AND …区间WHERE age BETWEEN 20 AND 25
IN (…)在集合中WHERE name IN ('张三','李四')
LIKE模糊匹配WHERE name LIKE '张%'
AND / OR逻辑与 / 或WHERE age > 20 AND name LIKE '张%'
IS NULL / IS NOT NULL空值判断WHERE email IS NULL

3.3 更新数据(UPDATE)

更新数据时务必带上 WHERE 条件,否则会更新全表数据:

-- 更新单条记录
UPDATE student SET age = 21 WHERE id = 1;
-- 更新多条记录
UPDATE student SET age = age + 1 WHERE age < 20;
-- 更新多个字段
UPDATE student SET age = 22, email = 'new@example.com' WHERE id = 2;

安全提示:生产环境中执行 UPDATE 前,建议先用相同条件的 SELECT 确认影响范围。

3.4 删除数据(DELETE)

删除数据同样需要谨慎使用 WHERE:

-- 删除指定记录
DELETE FROM student WHERE id = 3;
-- 清空表数据(保留表结构)
TRUNCATE TABLE student;

DELETE 与 TRUNCATE 的区别:

对比项DELETETRUNCATE
是否可带 WHERE可以不可以
是否记录日志逐行记录不逐行记录
速度较慢很快
自增 ID 是否重置不重置重置
是否可回滚(事务内)可以不可以

4. 事务与 ACID 特性

事务(Transaction)是一组逻辑上不可分割的数据库操作,要么全部成功,要么全部失败。它保证了多个 DML 操作作为一个整体执行,是保证数据一致性的重要机制。

4.1 事务的四大特性(ACID)

特性英文说明
原子性Atomicity事务内的所有操作要么全部提交成功,要么全部回滚,不存在「执行了一半」的状态
一致性Consistency事务执行前后,数据库始终处于合法状态,约束(主键、外键、唯一等)始终被满足
隔离性Isolation多个事务并发执行时互不干扰,一个事务未提交的修改对其他事务不可见
持久性Durability事务一旦提交,其修改将永久保存,即使系统崩溃也不会丢失

4.2 事务的基本操作:BEGIN / COMMIT / ROLLBACK

MySQL 中默认每条 DML 语句是自动提交的。如果需要把多条操作放进同一个事务,需要显式开启事务:

-- 开启事务
BEGIN;
-- 执行一组 DML 操作
INSERT INTO student (name, age, email) VALUES ('钱八', 25, 'qianba@example.com');
UPDATE student SET age = age + 1 WHERE id = 1;
-- 全部成功,提交事务
COMMIT;

如果事务中途出错,可以使用 ROLLBACK 撤销本事务内所有未提交的修改:

BEGIN;
-- 第一条操作成功
INSERT INTO student (name, age, email) VALUES ('孙九', 26, 'sunjiu@example.com');
-- 第二条操作失败(例如违反唯一约束)
INSERT INTO student (name, age, email) VALUES ('周十', 27, 'sunjiu@example.com');
-- ERROR 1062: Duplicate entry ...
-- 回滚,撤销本事务内的所有修改
ROLLBACK;

提示:COMMIT 之后事务结束,修改永久生效;ROLLBACK 之后事务结束,修改全部撤销。事务内未提交的修改对其他连接不可见。

4.3 DML 操作在事务中的行为

5. 综合实战示例

下面通过一个完整的示例,串联本篇文章介绍的核心操作。

5.1 建库建表

-- 创建数据库
CREATE DATABASE IF NOT EXISTS shop DEFAULT CHARSET utf8mb4;
USE shop;
-- 创建商品表
CREATE TABLE IF NOT EXISTS product (
  id INT UNSIGNED AUTO_INCREMENT COMMENT '商品ID',
  name VARCHAR(100) NOT NULL COMMENT '商品名称',
  price DECIMAL(10,2) NOT NULL COMMENT '价格',
  stock INT UNSIGNED DEFAULT 0 COMMENT '库存',
  status TINYINT DEFAULT 1 COMMENT '状态:1上架 0下架',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';

5.2 数据操作

-- 插入商品
INSERT INTO product (name, price, stock) VALUES
('手机', 2999.00, 100),
('耳机', 199.00, 500),
('充电器', 59.00, 1000);
-- 查询价格大于 100 的商品,按价格降序
SELECT id, name, price, stock FROM product
WHERE price > 100
ORDER BY price DESC;
-- 给所有商品涨价 10%
UPDATE product SET price = price * 1.1;
-- 删除库存为 0 的商品
DELETE FROM product WHERE stock = 0;

5.3 操作流程示意

下面是本示例的完整操作流程:

6. 常见问题与注意事项

6.1 忘记 WHERE 条件

UPDATE 和 DELETE 不带 WHERE 会作用于全表,这是新手最容易犯的错误。建议养成先 SELECT 后 UPDATE/DELETE 的习惯。

6.2 字符集不一致导致乱码

建库、建表时统一使用 utf8mb4,连接串中也应指定 characterEncoding=utf8,避免中文乱码。

6.3 主键与自增

主键建议使用无符号整数自增(INT UNSIGNED AUTO_INCREMENT),避免业务字段作为主键带来的耦合。

6.4 备份意识

6.5 常见 SQL 错误与排查

新手在编写 SQL 时经常遇到各类报错,下面列出 5 个高频错误,并给出错误提示、原因分析、解决方案与正确示例。

错误 1:字段名拼写错误

错误提示示例:

SELECT id, name, age FROM student WHERE ag > 20;
ERROR 1054 (42S22): Unknown column 'ag' in 'where clause'

原因分析: 字段名拼写错误(ag 应为 age),MySQL 无法在表中找到该列。

解决方案: 使用 DESCRIBE student; 或 SHOW COLUMNS FROM student; 查看表结构,确认字段名后再编写 SQL。

正确 SQL:

SELECT id, name, age FROM student WHERE age > 20;

错误 2:数据类型不匹配

错误提示示例:

INSERT INTO student (name, age, email) VALUES ('张三', '二十', 'zhangsan@example.com');
ERROR 1366 (HY000): Incorrect integer value: '二十' for column 'age' at row 1

原因分析: age 字段是整数类型,却传入了字符串 '二十',MySQL 无法完成类型转换。

解决方案: 严格按字段数据类型传值,数字类型传数字,日期类型传合法日期格式。

正确 SQL:

INSERT INTO student (name, age, email) VALUES ('张三', 20, 'zhangsan@example.com');

错误 3:违反唯一约束

错误提示示例:

INSERT INTO student (name, age, email) VALUES ('李四', 22, 'zhangsan@example.com');
ERROR 1062 (23000): Duplicate entry 'zhangsan@example.com' for key 'student.email'

原因分析: email 字段设置了 UNIQUE 唯一约束,插入的邮箱与已有记录重复。

解决方案: 插入前先查询确认该值是否已存在,或使用 INSERT IGNORE、ON DUPLICATE KEY UPDATE 处理冲突。

正确 SQL:

-- 先检查是否已存在
SELECT id FROM student WHERE email = 'zhangsan@example.com';
-- 或使用 INSERT IGNORE 忽略重复
INSERT IGNORE INTO student (name, age, email) VALUES ('李四', 22, 'zhangsan@example.com');

错误 4:外键约束失败

错误提示示例:

INSERT INTO student (name, age, dept_id) VALUES ('王五', 21, 999);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails

原因分析: dept_id 引用了 dept 表的主键,但 dept 表中不存在 id = 999 的部门记录,外键校验失败。

解决方案: 先确认被引用表中存在对应记录,再插入子表数据;或检查外键字段是否允许为 NULL。

正确 SQL:

-- 先确认部门存在
SELECT id FROM dept WHERE id = 999;
-- 部门存在后再插入
INSERT INTO student (name, age, dept_id) VALUES ('王五', 21, 999);

错误 5:字符集不一致导致乱码

错误提示示例:

INSERT INTO student (name) VALUES ('张三');
ERROR 1366 (HY000): Incorrect string value: '\xE5\xBC\xA0\xE4\xB8\x89' for column 'name'

原因分析: 客户端连接字符集与表字符集不一致(如连接使用 latin1,表使用 utf8mb4),中文写入时被截断或报错。

解决方案: 连接时统一指定字符集,建库建表统一使用 utf8mb4。

正确 SQL:

-- 连接时指定字符集
SET NAMES utf8mb4;
-- 建表时指定字符集
CREATE TABLE IF NOT EXISTS student (
  name VARCHAR(50) NOT NULL COMMENT '姓名'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

执行 DROP、TRUNCATE 等不可逆操作前,务必确认数据已备份。

7. 索引与约束基础

索引与约束是 MySQL 中提升查询性能、保证数据完整性的两大核心机制。本节将介绍常用索引的创建方式、常见约束的作用,以及使用时的注意事项。

7.1 索引的创建

索引用于加速数据检索,可以基于一个或多个字段创建。常用创建方式有两种:CREATE INDEX 和 ALTER TABLE ADD INDEX。

普通索引(单列):

-- 使用 CREATE INDEX 创建普通索引
CREATE INDEX idx_student_name ON student(name);
-- 使用 ALTER TABLE 添加普通索引
ALTER TABLE student ADD INDEX idx_student_age (age);

唯一索引(保证字段值不重复):

CREATE UNIQUE INDEX idx_student_email ON student(email);
ALTER TABLE student ADD UNIQUE INDEX idx_student_email (email);

联合索引(多个字段组合,遵循最左前缀原则):

CREATE INDEX idx_name_age ON student(name, age);
ALTER TABLE student ADD INDEX idx_name_age (name, age);

提示:联合索引中字段的顺序很重要,查询条件应尽量匹配索引的最左前缀,才能充分利用索引。

7.2 常见约束

约束用于保证数据的完整性与一致性,可以在建表时定义,也可以通过 ALTER TABLE 添加。

约束类型作用示例
主键约束(PRIMARY KEY)唯一标识一行,非空且唯一PRIMARY KEY (id)
外键约束(FOREIGN KEY)保证表间引用完整性FOREIGN KEY (dept_id) REFERENCES dept(id)
唯一约束(UNIQUE)保证字段值不重复email VARCHAR(100) UNIQUE
非空约束(NOT NULL)字段不允许为空name VARCHAR(50) NOT NULL
默认值约束(DEFAULT)未提供值时使用默认值age TINYINT DEFAULT 0

在建表时定义约束:

CREATE TABLE IF NOT EXISTS student (
  id INT UNSIGNED AUTO_INCREMENT COMMENT '主键ID',
  name VARCHAR(50) NOT NULL COMMENT '姓名',
  age TINYINT UNSIGNED DEFAULT 0 COMMENT '年龄',
  email VARCHAR(100) UNIQUE COMMENT '邮箱',
  dept_id INT UNSIGNED COMMENT '部门ID',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (id),
  CONSTRAINT fk_student_dept FOREIGN KEY (dept_id) REFERENCES dept(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生表';

通过 ALTER TABLE 添加约束:

-- 添加唯一约束
ALTER TABLE student ADD UNIQUE (email);
-- 添加外键约束
ALTER TABLE student ADD CONSTRAINT fk_student_dept
  FOREIGN KEY (dept_id) REFERENCES dept(id);

7.3 索引与约束对比

对比项索引约束
主要目的提升查询性能保证数据完整性
是否影响写入速度会(写入时需维护索引)会(写入时需校验)
是否可重复创建可创建多个主键/唯一等有唯一性要求
是否占用存储空间是(额外索引文件)部分约束会隐式创建索引
典型场景高频查询字段主键、外键、唯一、非空

7.4 索引使用注意事项

8. 总结

本文系统讲解了 MySQL 的数据定义语言(DDL)与数据操作语言(DML)核心内容:

掌握这些基础后,你已经具备了日常开发中最常用的 MySQL 操作能力。下一篇文章我们将继续深入索引、约束与事务等进阶主题,敬请期待。

9. 参考资料与延伸阅读

为了帮助你进一步巩固 MySQL 基础、深入理解底层原理,这里整理了一些官方文档、经典书籍和社区博客,供不同学习阶段参考。

9.1 官方文档

9.2 经典书籍

9.3 推荐阅读的 CSDN 博客

提示:以上博客链接为占位符,你可以根据实际阅读体验替换为更合适的文章地址。建议优先选择带完整示例、结论清晰的博客,并结合官方文档交叉验证。

到此这篇关于MySQL数据定义与数据操作综合实战示例的文章就介绍到这了,更多相关mysql数据定义与数据操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文