MySQL数据库
MySQL插入数据
insert into table_name(col_name, ...) values(value1, value2, ...)
如果插入所有列可以省略列名
insert into table_name values(value1, value2, ...)
插入多行
insert into table_name(col_name, ...) values(value1, value2, ...), (value11, value22, ...)
MySQL查询数据
查询语句
1
2
3
4
5
6
select
col_name1, col_name2, ...
from table_name
[where condition]
[order by [ASC | DESC]]
[limit number]
查询所有行和列
select * from table_name
查询特定行
select col_name1, col_name2, ... from table_name
查询满足条件的行
select * from where is_activate = True
对查询结果按属性排序
select * from table_name order by order_by [DESC]
对查询结果限制返回行数
select * from table_name limit 5
MySQL where 子句
where 子句
1
2
3
4
5
select *
from table_name
where condition;
condition 支持以下逻辑运算符
- =, !=, >, <, >=, <=
- 组合条件:and, or
- 模糊匹配条件(like): where col_name like ‘J%’; – 其中%可以匹配任意字符
- in 条件: WHERE country_code IN (‘US’, ‘CA’, ‘MX’); – 属性是否在一个集合中
- not 条件: 对运算结果非
- between条件:WHERE order_date BETWEEN ‘2023-01-01’ AND ‘2023-12-31’; – 判断属性是否介于两个设定值之间
- is null 条件:WHERE department IS NULL;– 判断属性是否是null
- is not null 条件:WHERE email IS NOT NULL; – 判断属性是否不是null,若不为空则条件满足
MySQL update 更新
update syntax 更新语法规则
1
2
3
4
5
update table_name
set col_name1 = value1, col_name2 = value2
[where condition]
更新使用子查询的值
1
2
3
4
5
6
7
UPDATE customers
SET total_purchases = (
SELECT SUM(amount)
FROM orders
WHERE orders.customer_id = customers.customer_id
)
WHERE customer_type = 'Premium';
MySQL delete 语句
delete 语法规则
1
2
3
delete
from table_name
[where condition];
无条件删除所有
1
DELETE FROM orders;
使用子查询删除符合条件的行
1
2
3
4
5
6
DELETE FROM customers
WHERE customer_id IN (
SELECT customer_id
FROM orders
WHERE order_date < '2023-01-01'
);
MySQL like 子句
语法规则
1
2
3
select *
from table_name
where col_name like '%_hhh';
like 子句通配符说明
- %通配符表示0个或多个任意字符, 例如’a%’,表示以a开头的任意字符串,包含a
- _通配符表示一个任意字符
MySQL union 操作符
描述
MySQL UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合,并去除重复的行。
UNION 操作符必须由两个或多个 SELECT 语句组成,每个 SELECT 语句的列数和对应位置的数据类型必须相同。
用于连接两个查询结果,要求查询结果必须有相同的属性,并且数据类型也必须一致,union会将两者合并到一张表中,并去除重复行。
语法格式
1
2
3
4
5
6
7
8
SELECT column1, column2, ...
FROM table1
WHERE condition1
UNION
SELECT column1, column2, ...
FROM table2
WHERE condition2
[ORDER BY column1, column2, ...];
union all 不会去除重复行
MySQL order by(排序) 语句
语法规则,默认使用升序(ASC)排序
1
2
3
select col_name1, col_name2, ...
from table_name
order by col_name1 [ASC, DESC], col_name2 [ASC, DESC], ...
简介语法,使用数字表示列的位置, 位置3表示按salary降序排序,相同则继续按位置1,first_name升序排序;
1
2
3
SELECT first_name, last_name, salary
FROM employees
ORDER BY 3 DESC, 1 ASC;
使用表达式排序
1
2
3
SELECT product_name, price * discount_rate AS discounted_price
FROM products
ORDER BY discounted_price DESC;
MySQL group by 语句
语法规则
1
2
3
4
select col_name1, aggregate_function(col_name2)
from table_name
[where condition]
group by col_name1;
例句说明,这里将以列customer_id进行分组求order_amount的和,最后展示customer_id,以及求和列total_amount所形成的表格
1
2
3
SELECT customer_id, SUM(order_amount) AS total_amount
FROM orders
GROUP BY customer_id;
注意事项
- group by 子句通常与聚合函数一起使用,因为分组后要对每个组进行聚合操作
- select 子句的列要么是分组列或者是聚合列
- 可以同时使用多个列进行分组,只需要在group by 子句中通过逗号连接分组的列即可
MySQL 连接的使用
语法规则
1
2
3
4
select col_name1, col_name2, ...
from table1
[inner | left | right] join table2
on condition
inner join
简要介绍:inner join 返回两个表中满足连接条件的匹配行, 只使用join关键字默认就是使用inner join
1
2
3
SELECT orders.order_id, customers.customer_name
FROM orders
INNER JOIN customers ON orders.customer_id = customers.customer_id;
left join
简要介绍: left join 返回左表中的所有行以及右表中满足连接条件的匹配行,若右表无匹配行,则返回NULL
right join
简要介绍: right join 的功能与left join 相似,只不过保留的是右表中的所有行和满足连接条件的坐标中的行,若左表中无匹配行,返回NULL
总结: inner join 类似于交集,必须保证左右两表都满足条件才会被搜索,left join 确保左表全部行被保留,满足条件的右表也会被保留,若无则返回NULL,right join 同理
MySQL 事务
MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你既需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!
在 MySQL 中,事务是一组SQL语句的执行,它们被视为一个单独的工作单元。
- 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
- 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
- 事务用来管理 insert、update、delete 语句
一般来说,事务是必须满足4个条件(ACID):原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
- 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
- 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
- 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
概述
一致性: 事务执行前后,数据库都满足预定义的规则和约束,事务的一致性是原子性,隔离性,持久性一同来维持的,缺一不可原子性: 要么全做,要么全部做隔离性: 并发事务互不干扰持久性: 做完了就不会丢失
数据库事务隔离性的不同级别
除了串行化(Serializable) 能提供完全的隔离保证外,其他三个隔离级别都允许某种程度的并发问题,只是为了性能而做的权衡。
隔离级别与并发问题的关系
首先明确三种并发问题:
| 问题 | 描述 | 例子 |
|---|---|---|
| 脏读(Dirty Read) | 读到别的事务未提交的数据 | A修改了数据但没提交,B读到了,A又回滚了 |
| 不可重复读(Non-repeatable Read) | 同一事务内,两次读同一行数据不一致 | A第一次读是100,B修改并提交,A第二次读变成200 |
| 幻读(Phantom Read) | 同一事务内,两次查询结果集数量不一致 | A第一次查有5条,B插入1条并提交,A第二次查有6条 |
四个隔离级别对比
1
2
3
4
5
6
7
8
隔离级别 脏读 不可重复读 幻读 性能
─────────────────────────────────────────────
读未提交 ✗ ✗ ✗ ⭐⭐⭐⭐⭐
读已提交 ✓ ✗ ✗ ⭐⭐⭐⭐
可重复读 ✓ ✓ ✗* ⭐⭐⭐
串行化 ✓ ✓ ✓ ⭐
─────────────────────────────────────────────
✓ = 防止 ✗ = 可能发生 ✗* = 部分防止
注:MySQL的InnoDB引擎在可重复读级别通过MVCC+间隙锁也能防止幻读
各级别详解
1️⃣ 读未提交(Read Uncommitted)
1
2
问题:什么都可能发生
使用场景:几乎不用,除非是统计类、对精度要求极低的数据
2️⃣ 读已提交(Read Committed)
1
2
3
问题:不可重复读、幻读
使用场景:Oracle默认级别,适合大多数OLTP场景
例子:用户查看订单状态,允许状态在查询间变化
3️⃣ 可重复读(Repeatable Read)
1
2
3
问题:理论上可能幻读(但MySQL InnoDB已解决)
使用场景:MySQL默认级别,适合需要一致视图的场景
例子:报表生成、需要多次读取相同数据的业务
4️⃣ 串行化(Serializable)
1
2
3
问题:无并发问题
代价:性能最差,并发度最低
使用场景:金融核心交易、库存扣减等对一致性要求极高的场景
实际选择策略
1
2
3
4
5
6
7
8
┌──────────────────────────────────────────────────┐
│ 如何选择合适的隔离级别? │
├──────────────────────────────────────────────────┤
│ 1. 默认用可重复读(MySQL)或读已提交(Oracle) │
│ 2. 只有真正需要时才升级到串行化 │
│ 3. 读多写少的场景可以降级到读已提交 │
│ 4. 统计、缓存类数据可以用读未提交 │
└──────────────────────────────────────────────────┘
一个直观的例子
假设两个事务同时操作账户余额:
1
2
事务A: 查询余额 → 计算利息 → 更新余额
事务B: 查询余额 → 转账 → 更新余额
| 隔离级别 | 可能发生的问题 |
|---|---|
| 读未提交 | A可能读到B未提交的转账结果,B回滚后A的数据就错了 |
| 读已提交 | A两次查询余额可能不一致(B在中间提交了转账) |
| 可重复读 | A在整个事务中看到一致的余额视图 |
| 串行化 | A和B必须一个等另一个完成,完全不会干扰 |
总结
隔离级别 = 一致性保证程度 vs 并发性能的权衡
- 串行化:100%安全,但性能最低
- 其他级别:允许某些并发问题,换取更高的并发性能
- 选择原则:在满足业务一致性要求的前提下,尽量选择更低的隔离级别
- 读已提交:每次查询都看当前最新已提交的数据
- 可重复读:整个事务期间都看事务开始时的快照
这就是为什么数据库不提供”一刀切”的串行化,而是给出多个级别让开发者根据业务场景选择。
文章参考菜鸟教程