MySQL (3) 操作语言

255 阅读6分钟

1. 数据操作语言

概念: 数据操作语言(DML),负责操作数据,如INSERT、DELETE、UPDATE等语句。

2. 事务机制

概念: 事务是一组不可分割的业务关系,在SQL中指的是一组不可拆分的DML语句,这组语句要么都成功,要么都失败。

  • 事务主要用于处理操作量大,复杂度高的数据,用来维护数据库的完整性。
  • 事物的关键字是提交和回滚,COMMITROLLBACK
  • 事务是必须满足4个条件(ACID): 、Consistency(稳定性)、Isolation(隔离性)、Durability(可靠性)
    • Atomicity(原子性):一组事务,要么成功,要么回滚。
    • Consistency(稳定性):有非法数据(外键约束之类),事务回滚。
    • Isolation(隔离性):事务独立运行,但如果一个事务处理后的结果影响了其他事物,则会回滚。
    • Durability(可靠性):软硬件崩溃后,数据库会利用日志文件重构修改,可靠性和高速度不可兼得。

3. 事务隔离级别

概念: 事务隔离级别,就是一个事务对数据库的修改与并行的另一个事务的隔离程度,即当我操作数据库的时候,允许你做什么,当两个并发事务同时访问数据库表相同的行时,不同的数据隔离级别会发生不同的并发现象:

  • READ UNCOMMITTED 隔离级别,读取未提交的数据,可能出现脏读现象:
    • 案例:公司发工资了,领导写了一张通知发给财务,上面说明给四哥发1000元奖金,此时四哥正好在财务部门调戏财务小妹,发现了1000元奖金的事情,非常高兴,回家了。可是不幸的是,领导突然发现四哥的出勤有问题,于是迅速回滚了事务,补发了第二张通知,修改了奖金为-1000元后,将事务提交,最后四哥需要扣除1000元。
    • 总结:T1读取了已经被T2更新但还没有被T2提交的字段,之后,若T2回滚,T1读取的内容就是临时且无效的脏数据。
    • 设置:SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
  • READ COMMITTED 隔离级别:只能读取已提交的数据,避免脏读,但是会发生不可重复读的现象:
    • 案例:四哥拿着工资卡去消费,POS机读取到卡里确实有1000元,而此时四嫂也正好在网上淘宝,把四哥工资卡花掉999元,并在四哥消费之前付了款(提交了事务),然后四哥输入密码结账扣款,结果POS机提示余额不足,扣款失败,WTF?四哥十分纳闷,明明卡里有钱啊?
    • 总结:T1读取了一个字段,然后T2更新了该字段,之后,T1再次读取同一个字段,值就不同了。
    • 设置:SET TRANSACTION ISOLATION LEVEL READ COMMITTED 
  • REPEATABLE READ 隔离级别:允许重复读取,避免脏读和不可重复读,但是会发生幻读:
    • 案例:四嫂时常查看四哥的银行卡消费记录,有一天,她查询(SELECT)到四哥当月的总消费金额为80元,而四哥此时正好在外面胡吃海塞,并消费1000元,即新增(INSERT)了一条1000元的消费记录,并提交了事务,随后四嫂将四哥当月消费的明细打印到A4纸上,却发现消费总额为1080元,四嫂很诧异,以为出现了幻觉,幻读就这样产生了。
    • 总结:T1从一个表中读取了一个字段,然后T2在该表中插入了一些新的行,之后,如果T1再次读取同一个表,就会多出几行。
    • 设置:SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
  • SERIALIZABLE 序列化读取:一个事务执行完毕再执行下一个:
    • 总结:SERIALIZABLE 是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读。
    • 设置:SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

ORACLE支持 READ COMMITTEDSERIALIZABLE 这两种事务隔离级别,默认为 READ COMMITTED,mysql支持全部四种事务隔离级别,默认使用的是 REPEATABLE READ

4. 数据操作语句

概念:

  • 增加:INSERT INTO 表名 (字段列表) VALUES (值列表)
    • 值列表必须和字段列表的个数、顺序和类型都对应。
    • 按表正确的顺序插入全部字段的值时,可以省略字段列表。
    • 如果想要批量插入,可以在一条语句中,直接用逗号分隔多组值列表。
  • 删除:DELETE FROM 表名 WHERE 条件
    • 如果不指定删除条件,表示全部删除。
  • 修改:UPDATE 表名 SET 字段名=值, 字段名=值... WHERE 条件

源码: ddl/数据操作语句.sql

DROP TABLE IF EXISTS `ACCOUNT`;
CREATE TABLE `ACCOUNT`
(
    `ID`          INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `USERNAME`    VARCHAR(50)  NOT NULL DEFAULT '' COMMENT '帐号',
    `PASSWORD`    VARCHAR(50)  NOT NULL DEFAULT '' COMMENT '密码',
    `CREATE_DATE` DATE COMMENT '注册日期',
    PRIMARY KEY (`ID`)
) ENGINE = INNODB
  DEFAULT CHARSET = UTF8MB4;

TRUNCATE TABLE `ACCOUNT`;

INSERT INTO `ACCOUNT` (`USERNAME`, `PASSWORD`, `CREATE_DATE`)
VALUES ('COMMIT', 'COMMIT', NOW());
COMMIT;

INSERT INTO `ACCOUNT` (`USERNAME`, `PASSWORD`, `CREATE_DATE`)
VALUES ('ROLLBACK', 'ROLLBACK', NOW());
ROLLBACK;

INSERT INTO `ACCOUNT`
VALUES (5, 'ADMIN', 'ADMIN', NOW());
COMMIT;

INSERT INTO `ACCOUNT` (`USERNAME`, `PASSWORD`, `CREATE_DATE`)
VALUES ('U001', 'P001', NOW()),
       ('U002', 'P002', NOW()),
       ('U003', 'P003', NOW()),
       ('U004', 'P004', NOW()),
       ('U005', 'P005', NOW());
COMMIT;

DELETE FROM `ACCOUNT` WHERE `USERNAME` = 'ROLLBACK';
COMMIT;

UPDATE `ACCOUNT` SET `PASSWORD` = 'PPP' WHERE `USERNAME` like 'U%';
COMMIT;

5. 数据导入导出

5.1 利用DOS导出

概念: mysqldump -h主机地址 -u帐号 -p 数据库名 [表名] > 文件路径

  • -p 后面不能加密码。
  • 文件路径需要使用绝对路径,一直到写到xxx.sql。
  • 命令末尾不要添加分号。
  • 如果只想导出一个表,在数据库名后面指定表名。
  • -p 和数据库名之间添加 --default-character-set=utf8mb4 可以指定编码。
  • -p 和数据库名之间添加 -d,代表删除数据,只导出表结构。

5.2 利用DOS导入

概念: 进入到mysql命令下:source 文件路径

5.3 利用IDEA导出

流程:

  1. 在指定的表上右键,选择 Dump Data to File(s)
  2. 勾选 ADD TABLE DEFINITION(SQL),否则没有表结构。
  3. 如果想要生成一个单独的SQL,勾选 SINGLE FILE
  4. 再次右键,选择 Dump Data to File(s)
  5. 选择 SQL INSERT,选择路径,成功导出文件。

5.4 利用IDEA导入

流程:

  1. 在指定的数据库上右键,选择 Run SQL Script
  2. 找到你要导入的SQL文件,点击OK。