2-mysql
SQL 按功能大致分为:
- DDL(Data Definition Language):数据定义语言,用来操作数据库、表、字段等结构
- DML(Data Manipulation Language):数据操作语言,用来增删改表中的数据
- DQL(Data Query Language):数据查询语言,用来查询表中的数据
- DCL(Data Control Language):数据控制语言,用来管理用户和权限
- TCL(Transaction Control Language):事务控制语言,用来提交、回滚事务
基础
常用数据类型
| 类型 | 说明 | 示例 |
|---|---|---|
| tinyint | 小整数 | 状态、布尔值 |
| int | 整数 | 用户 id、数量 |
| bigint | 大整数 | 雪花 id、访问量 |
| decimal(m, d) | 精确小数 | 金额 |
| float/double | 浮点数 | 统计值 |
| char(n) | 定长字符串 | 性别、固定编码 |
| varchar(n) | 变长字符串 | 用户名、标题 |
| text | 长文本 | 文章内容 |
| date | 日期 | 2026-06-22 |
| time | 时间 | 05:24:00 |
| datetime | 日期时间 | 2026-06-22 05:24:00 |
| timestamp | 时间戳 | 通常用于创建时间、更新时间 |
金额优先使用 decimal,不要用 float 或 double,避免精度误差。
常用约束
| 约束 | 说明 |
|---|---|
| primary key | 主键,唯一且非空 |
| auto_increment | 自增,一般配合整数主键 |
| not null | 非空 |
| unique | 唯一 |
| default | 默认值 |
| foreign key | 外键,建立表之间的关联 |
| check | 检查约束,MySQL 8.0 开始真正生效 |
常见建表例子:
create table user ( id bigint primary key auto_increment, username varchar(50) not null unique, password varchar(100) not null, age int default 0, create_time datetime default current_timestamp, update_time datetime default current_timestamp on update current_timestamp);DDL
数据库操作
show databases;
create database [if not exists] 数据库名 default charset utf8mb4 collate utf8mb4_general_ci;
use 数据库名;
select database();
drop database [if exists] 数据库名;utf8mb4 比 utf8 更完整,可以存储 emoji 等字符。
表操作
show tables;
desc 表名;
show create table 表名;
create table 表名 ( 字段1 类型 [约束], 字段2 类型 [约束]);
drop table [if exists] 表名;
truncate table 表名;drop 删除整张表结构和数据,truncate 保留表结构但清空数据。
修改表
alter table 表名 add 字段名 类型 [约束];
alter table 表名 modify 字段名 新类型 [新约束];
alter table 表名 change 旧字段名 新字段名 类型 [约束];
alter table 表名 drop 字段名;
alter table 表名 rename to 新表名;DML
新增
insert into 表名 (字段1, 字段2)values (值1, 值2);
insert into 表名 (字段1, 字段2)values (值1, 值2), (值1, 值2);如果省略字段列表,则 values 必须和表字段顺序完全一致,不推荐这样写。
修改
update 表名set 字段1 = 值1, 字段2 = 值2[where 条件];没有 where 会修改整张表,执行前要特别注意。
删除
delete from 表名 [where 条件];没有 where 会删除整张表的数据。
DQL
完整书写顺序:
select 字段列表from 表名列表where 条件列表group by 分组字段列表having 分组后条件列表order by 排序字段列表limit 分页参数;实际执行顺序大致是:
from -> where -> group by -> having -> select -> order by -> limit条件查询
| 条件 | 说明 |
|---|---|
| =, <>, !=, >, >=, <, <= | 比较 |
| between … and … | 范围查询,包含边界 |
| in (…) | 在指定集合中 |
| like | 模糊匹配,% 匹配任意多个字符,_ 匹配单个字符 |
| is null / is not null | 判断空值 |
| and / or / not | 逻辑运算 |
null 不能用 = null 判断,要用 is null。
聚合函数
| 聚合函数 | 返回值 |
|---|---|
| max | 最大值 |
| min | 最小值 |
| count | 计数 |
| avg | 平均值 |
| sum | 总和 |
select count(*) from user;
select dept_id, count(*) as totalfrom employeegroup by dept_idhaving total > 5;where 在分组前过滤,不能直接使用聚合函数;having 在分组后过滤,可以使用聚合函数。
排序和分页
select *from userorder by create_time desc, id asclimit 0, 10;limit 起始索引, 查询条数,第 n 页的起始索引是 (n - 1) * pageSize。
DCL
用户管理
查询用户:
use mysql;
select user, host from user;创建用户:
create user '用户名'@'主机名' identified by '密码';修改用户密码:
alter user '用户名'@'主机名' identified by '新密码';删除用户:
drop user '用户名'@'主机名';'用户名'@'localhost' 表示只能本机登录,'用户名'@'%' 表示任意主机都可以登录。
权限控制
查询权限:
show grants for '用户名'@'主机名';授予权限:
grant 权限列表 on 数据库名.表名 to '用户名'@'主机名';撤销权限:
revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名';刷新权限:
flush privileges;常见权限有 all、select、insert、update、delete、create、drop。
函数
字符串函数
| 函数 | 说明 |
|---|---|
| concat(s1, s2, …) | 字符串拼接 |
| lower(s) | 转小写 |
| upper(s) | 转大写 |
| length(s) | 返回字节长度 |
| char_length(s) | 返回字符长度 |
| substring(s, start, len) | 截取字符串 |
| trim(s) | 去除首尾空格 |
| replace(s, old, new) | 替换字符串 |
数值函数
| 函数 | 说明 |
|---|---|
| ceil(x) | 向上取整 |
| floor(x) | 向下取整 |
| round(x, d) | 四舍五入 |
| mod(x, y) | 取模 |
| rand() | 随机数 |
日期函数
| 函数 | 说明 |
|---|---|
| now() | 当前日期时间 |
| curdate() | 当前日期 |
| curtime() | 当前时间 |
| year(date) | 年 |
| month(date) | 月 |
| day(date) | 日 |
| date_add(date, interval n type) | 增加时间 |
| datediff(date1, date2) | 日期差 |
流程函数
select if(score >= 60, '及格', '不及格') as resultfrom student;
select case when score >= 90 then '优秀' when score >= 60 then '及格' else '不及格' end as levelfrom student;多表查询
连接查询
| 连接 | 描述 |
|---|---|
| 内连接 | 取两表数据交集 |
| 左外连接 | 取左表全部数据和两表交集 |
| 右外连接 | 取右表全部数据和两表交集 |
| 自连接 | 同一张表通过别名自己连接自己 |
内连接:
select e.name, d.name as dept_namefrom employee einner join department d on e.dept_id = d.id;左外连接:
select e.name, d.name as dept_namefrom employee eleft join department d on e.dept_id = d.id;隐式内连接也能写成:
select e.name, d.namefrom employee e, department dwhere e.dept_id = d.id;实际开发中更推荐显式 join ... on ...,可读性更好。
联合查询
联合查询取多个查询结果的并集:
select 字段列表 from 表1unionselect 字段列表 from 表2;union 去重,union all 不去重。
使用要求:
- 多个查询的列数必须一致
- 对应列的数据类型最好一致
- 和
or的区别是union可以合并多个表或多个查询结果
子查询
子查询就是嵌套 select,可以出现在 where、from、select 等位置。
标量子查询
结果是单行单列:
select *from employeewhere salary > (select avg(salary) from employee);列子查询
结果是单列多行,常配合 in、not in、any、all 使用:
select *from employeewhere dept_id in ( select id from department where name in ('研发部', '测试部'));行子查询
结果是一行多列:
select *from employeewhere (salary, manager_id) = ( select salary, manager_id from employee where name = '张三');表子查询
结果是多行多列,通常放在 from 后作为临时表:
select t.*from ( select dept_id, count(*) as total from employee group by dept_id) twhere t.total > 5;索引
索引可以提高查询效率,但会占用空间,并降低新增、修改、删除数据的速度。
常见索引
| 索引 | 说明 |
|---|---|
| primary key | 主键索引 |
| unique | 唯一索引 |
| index | 普通索引 |
| fulltext | 全文索引 |
| composite index | 联合索引 |
基本语法
create index 索引名 on 表名(字段名);
create unique index 索引名 on 表名(字段名);
create index 索引名 on 表名(字段1, 字段2);
show index from 表名;
drop index 索引名 on 表名;使用原则
- 经常出现在
where、order by、group by、join on中的字段适合建索引 - 区分度高的字段更适合建索引,比如手机号、用户名
- 数据量很小的表不一定需要索引
- 联合索引遵循最左前缀原则
- 不要给频繁更新且查询价值不高的字段建索引
事务
事务是一组 SQL 操作,要么全部成功,要么全部失败,常用于转账、下单、扣库存等场景。
四大特性 ACID
| 特性 | 说明 |
|---|---|
| 原子性 Atomicity | 事务中的操作要么全部成功,要么全部失败 |
| 一致性 Consistency | 事务执行前后,数据保持业务上的一致 |
| 隔离性 Isolation | 多个事务并发执行时互不干扰 |
| 持久性 Durability | 事务提交后,对数据的修改会持久保存 |
基本语法
start transaction;
update account set money = money - 100 where id = 1;update account set money = money + 100 where id = 2;
commit;回滚:
start transaction;
update account set money = money - 100 where id = 1;update account set money = money + 100 where id = 2;
rollback;关闭自动提交:
select @@autocommit;
set @@autocommit = 0;并发问题
| 问题 | 说明 |
|---|---|
| 脏读 | 一个事务读到另一个事务尚未提交的数据 |
| 不可重复读 | 同一事务中两次读取同一行数据,结果不同 |
| 幻读 | 同一事务中两次范围查询,结果数量不同 |
隔离级别
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| read uncommitted | 可能 | 可能 | 可能 |
| read committed | 不可能 | 可能 | 可能 |
| repeatable read | 不可能 | 不可能 | MySQL InnoDB 通常可以避免 |
| serializable | 不可能 | 不可能 | 不可能 |
查看和设置隔离级别:
select @@transaction_isolation;
set session transaction isolation level repeatable read;MySQL InnoDB 默认隔离级别是 repeatable read。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!