MySql教程

mysql

本文主要是介绍mysql,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

* MySQL 的安装与配置

在解压文件包中添加文件 my.ini

[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8
[mysqld]
# 设置3306端口
port = 3306
# 设置mysql的安装目录
basedir=D:\mysql-8.0.19-winx64
# 设置 mysql数据库的数据的存放目录
# datadir=D:\mysql-8.0.19-winx64\data
# 允许最大连接数
max_connections=20
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB

然后可以设置环境变量 MYSQL_HOME 路径为压缩包的根路径,最后在path中加入即可(后面跟上/bin)
进行bin里面 mysqld --initialize-insecure 生成空的密码
或者 mysqld --initialize --console 初始化,后面有系统自动生成的密码

安装mysql服务
命令:mysqld install

若要删除mysql服务,可执行命令
mysqld --remove mysql

修改密码
alter user’root’@‘localhost’ identified with mysql_native_password by ‘新密码’;

* SQL 语言分类

  • DML(数据操作语言):添加、修改、删除、查询(CRUD)

  • DCL(数据控制语言):用户、权限、事务

  • DDL(数据定义语言):逻辑库、数据表、视图、索引

    # DDL 语言
    use test;
    # 创建数据表
    CREATE TABLE student(
    	id INT UNSIGNED PRIMARY KEY,
    	name VARCHAR(20) NOT NULL,
    	sex CHAR(1) NOT NULL,
    	birthday DATE NOT NULL,
    	tel CHAR(11) NOT NULL,
    	remark VARCHAR(200)
    );
    
    # 插入数据
    INSERT INTO student VALUES(1, "bright", "男", "2000-10-13", "18380743125", NULL);
    
    # 显示当前数据库所有数据表
    SHOW TABLES;
    
    # 删除 student表
    DROP TABLE student;
    
    # 显示student表各字段的结构
    DESC student;
    
    # 修改student表结构
    ALTER TABLE student
    ADD address VARCHAR(200) NOT NULL,
    ADD home_tel CHAR(11) NOT NULL;
    
    ALTER TABLE student
    MODIFY home_tel VARCHAR(20) NOT NULL
    
    # 修改字段的名称(将address字段改为home_address
    ALTER TABLE student
    CHANGE address home_address VARCHAR(20) NOT NULL;
    
    # 删除表中的字段
    ALTER TABLE student
    DROP home_address,
    DROP home_tel;
    
    # 唯一约束UNIQUE可以为NULL且表中字段不能重复
    CREATE TABLE t_teacher(
    	id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    	name VARCHAR(20) NOT NULL,
    	tel CHAR(11) NOT NULL UNIQUE,
    	married BOOLEAN NOT NULL DEFAULT FALSE
    );
    
    # 创建附表
    CREATE TABLE t_dept(
    	deptno INT UNSIGNED PRIMARY KEY,
    	dname VARCHAR(20) NOT NULL UNIQUE,
    	tel CHAR(4) UNIQUE
    );
    
    # 创建主表
    CREATE TABLE t_emp(
    	empno INT UNSIGNED PRIMARY KEY,
    	ename VARCHAR(20) NOT NULL,
    	sex ENUM("男", "女") NOT NULL,
    	deptno INT UNSIGNED NOT NULL,
    	hiredate DATE NOT NULL,
        # 外键约束
    	FOREIGN KEY(deptno) REFERENCES t_dept(deptno)
    );
    
    • 外键约束中的闭环问题:如果形成了外键闭环,则无法删除任何一张表的数据
      • 外键约束尽量不要使用,在删除数据当中,要先删除主表然后才能删除附表

* 范式

  • 第一范式:数据库的每一列都是不可分割的基本数据项,同一列中不能有多个值,也不能存在重复的属性。
    • 如属性班级中值:高三一班就不符合第一范式,两个属性,年级、班级符合第一范式
  • 第二范式:数据表中的每条记录必须是唯一的(要有主键列)
  • 第三范式:每列都与主键有直接关系,不存在传递依赖
    • 如家庭成员表中,只能有成员,不能把儿子女儿的属性加入了
    • 依照第三范式,数据可以拆分保存到不同的数据表中,彼此保持联系

* 索引

  • 目的:提高检索速度(底层用的二叉树)
  • 索引使用原则:
    • 数据量很大,而且经常被查询的数据表可以设置索引
    • 索引只添加在经常被用作检索条件的字段上面
    • 不要在大字段上创建索引
# 在创建表时为消息类型添加索引
CREATE TABLE t_message(
	id INT UNSIGNED PRIMARY KEY,
	content VARCHAR(200) NOT NULL,
	type ENUM("公告", "通告", "个人通知") NOT NULL,
	create_time TIMESTAMP NOT NULL,
    # 索引名: idx_type
	INDEX idx_type(type)
);

#对已存在的表添加索引
# 删除索引
DROP INDEX idx_type ON t_message;

# 在已存在的表中创建索引
CREATE INDEX idx_type ON t_message(type);

# 显示表中所有的索引, 主键也是索引
SHOW INDEX FROM t_message;

# 通过修改表的形式添加索引
ALTER TABLE t_message ADD INDEX idx_type(type);

* 数据库的查询

  • 查询语句的子句执行顺序

    • 词法分析与优化(读取SQL语句)–> FROM (选择数据来源) --> SELECT(选择输出内容)
  • 数据分页

    • 执行顺序 FROM --> SELECT --> LIMIT
    # SELECT ... FROM ... LIMIT 起始位置, 偏移量
    SELECT empno, ename FROM t_emp LIMIT 0,5;
    
    # 如果LIMIT 子句只有一个参数则表示偏移量, 起始值默认为0
    SELECT empno, ename FROM t_emp LIMIT 20; # 前20条数据
    
  • 结果集排序

    • 执行顺序 FROM --> SELECT --> ORDER BY --> LIMIT
    # SELECT ... FROM ... ORDER BY 字段名 DESC/ASC(默认);
    SELECT empno, ename FROM t_emp ORDER BY empno DESC;
    SELECT empno, ename FROM t_emp ORDER BY empno ASC LIMIT 0,5;
    # 对多个字段进行排序
    SELECT empno, ename, sal, hiredate FROM t_emp ORDER BY sal DESC, hiredate DESC;
    
  • 结果集中的重复记录

    • 使用DISTINCT的SELECT子句中只能查询到一列数据,如果查询多列,去重失效
    • DISTINCT 关键字只能在SELECT子句中使用一次且必须写在前面
    SELECT DISTINCT job FROM t_emp;
    # 会失效,内容不完全相同
    SELECT DISTINCT job, ename FROM t_emp;
    
  • 条件查询

    • WHERE子句的注意事项

      • 条件执行顺序是从左到右的,应该把索引条件或者筛选记录最多的条件写在最左侧
      • 执行顺序:FROM --> WHERE --> SELECT --> ORDER BY --> LIMIT
    • 比较运算符

      • comm IS NULL 若comm为空则返回 true
      • comm IS NOT NULL 若comm为空则返回 false
      • REGEXP(正则表达式)ename REGEXP “[A-Za-z]{4}” ename必须为4个字母
      • NOT 非关系 NOT deptno=20
      • XOR 异或关系 age > 18 XOR sex = “男” 只有一个为true,另一个为false才返回true
    # 条件:工龄超过20年且部门号为10且年薪超过15000的员工信息
    SELECT
    	empno, sal 
    FROM t_emp 
    WHERE deptno=10 
    # IFUNLL(comm, 0) 如果comm为null则返回0
    AND (sal + IFNULL(comm, 0)) * 12 >= 15000 
    # NOW() 返回当前时间, DATEDIFF 计算两个参数之间的天数
    AND DATEDIFF(NOW(),hiredate) / 365 >= 20;
    
    SELECT 
    	empno, ename, sal, deptno, hiredate
    FROM t_emp
    # deptno IN(10,20,30) 若 deptno 为10,20,30 则返回true
    WHERE deptno IN(10,20,30) AND job != "SALESMAN"
    AND hiredate < "1985-01-01";
    
    SELECT 
    	empno, ename, sal, deptno, comm
    FROM t_emp
    WHERE comm IS NOT NULL
    AND sal BETWEEN 1000 and 2000
    # ename 必须为2到4个的汉字
    AND ename REGEXP "^[\\u4e00-\\u9fa5]{2,4}$"
    # AND ename LIKE "%A%"; ename字段含有A
    
    SELECT 
    	empno, ename, sal, deptno, comm
    FROM t_emp
    WHERE NOT deptno IN(10, 30) # 查询30部门的信息
    XOR comm IS NOT NULL
    
  • 分组查询

    • 各种子句的执行顺序:
      • FROM --> WHERE --> GROUP BY --> SELECT --> ORDER BY --> LIMIT
    # ROUND 四舍五入函数
    SELECT deptno, ROUND(AVG(sal))
    FROM t_emp
    GROUP BY deptno
    ORDER BY deptno ASC;
    
    # 逐级分组
    SELECT deptno, job, COUNT(empno) "人数", ROUND(AVG(sal))
    FROM t_emp
    GROUP BY deptno, job
    ORDER BY deptno ASC
    
    SELECT deptno, COUNT(empno) "人数", 
    ROUND(AVG(sal)) "平均值", SUM(sal), MAX(sal) "最大值", MIN(sal) "最小值"
    FROM t_emp
    GROUP BY deptno
    # 对分组查询集再一次统计
    WITH ROLLUP
    
    • having 子句

      SELECT deptno
      FROM t_emp
      GROUP BY deptno
      HAVING AVG(sal) > 2000
      
      # 查询每个部门中,1982年以后入职的员工超过2个人的部门编号
      SELECT deptno
      FROM t_emp
      WHERE hiredate >= "1982-01-01"
      GROUP BY deptno
      HAVING COUNT(deptno) >= 2
      
      # 1是值select后的第一个查询属性
      SELECT deptno, COUNT(empno) "人数"
      FROM t_emp
      WHERE deptno IN(20, 30)
      GROUP BY 1;
      
  • 表连接查询

    • 表连接的分类
      • 内连接是结果集中只保留符合条件的记录(最常用)
      • 外连接不管是否符合条件,记录都会保留到结果集中
    # 内连接三种写法
    1. select ... from 表1 [INNER] JOIN 表2 ON 连接条件
    2. select ... from 表1 [INNER] JOIN 表2 where 连接条件
    3. select ... from 表1, 表2 where 连接条件
    
    # 查询每位员工的部门信息(内连接)
    SELECT e.empno, e.ename, d.dname
    # INNER 一般省略
    FROM t_emp e INNER JOIN t_dept d
    ON e.deptno = d.deptno
    
    # 查询每个员工的工号、姓名、部门名称、底薪、职位、工资等级(三表连接)
    SELECT e.empno, e.ename, d.dname, e.sal, e.job, s.grade
    FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno
    JOIN t_salgrade s ON e.sal BETWEEN s.losal AND s.hisal;
    
    # 查询与SCOTT相同部门的人
    SELECT ename
    FROM t_emp
    # 效率比较低,deptno=后面会执行很多次
    WHERE deptno = (SELECT deptno FROM t_emp WHERE ename="SCOTT")
    AND ename!="SCOTT";
    
    # 查询与SCOTT相同部门的人(对上面做的优化,提高查询的性能)
    SELECT e2.ename
    FROM t_emp e1 JOIN t_emp e2 ON e1.deptno=e2.deptno
    # 上面做完内连接后,条件是:e1=scott e2!=scott, 筛选结果在e2中
    WHERE e1.ename="SCOTT" AND e2.ename!="SCOTT";
    
    # 查询底薪超过公司平均底薪的员工信息(将查询到的结果当成表作为条件)
    SELECT e.deptno, e.ename, e.sal
    FROM t_emp e JOIN
    (SELECT AVG(sal) avg FROM t_emp) t
    ON e.sal > t.avg;
    
    # 查询RESEARCH部门的人数、最高底薪、最低底薪、平均底薪、平均工龄
    SELECT COUNT(empno) "人数", MAX(sal) "最高底薪",
    MIN(sal) "最低底薪", AVG(sal) "平均底薪",
    # FLOOR 向下取整函数  CEIL 向上取整函数
    FLOOR(AVG(DATEDIFF(NOW(),hiredate) / 365))
    FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno
    WHERE d.dname="RESEARCH"
    
    # 查询每种职业的最高工资、最低工资、平均工资、最高工资等级和最低工资等级
    SELECT 
    e.job,
    MAX(e.sal+IFNULL(e.comm,0)) "最高工资",
    MIN(e.sal+IFNULL(e.comm,0)) "最低工资",
    AVG(e.sal+IFNULL(e.comm,0)) "平均工资",
    MAX(s.grade) "最高工资等级",
    MIN(s.grade) "最低工资等级"
    FROM t_emp e JOIN t_salgrade s
    ON (e.sal+IFNULL(e.comm,0)) BETWEEN s.losal AND s.hisal
    GROUP BY e.job
    
    # 查询每个底薪超过部门平均底薪的员工信息
    SELECT e.empno, e.ename, e.sal
    FROM t_emp e JOIN 
    (SELECT deptno, AVG(sal) avg FROM t_emp GROUP BY deptno) t
    ON e.deptno=t.deptno AND e.sal > t.avg
    
    • 外连接

      • 左外连接就是保留左表所有的记录与右表做连接。如果右表有符合条件的记录就与左表连接,若没有符合条件的的记录则用NULL与左表连接,同理右外连接

      • 若某人是临时员工,他没有部门号,若根据内连接部门号查询,会漏掉该人信息

      • 外连接的注意事项:

        • 内连接只保留符合条件的记录,所有查询条件写在ON子句和WHERE的效果的一致的。但在外连接里,条件写在WHERE子句中,不合条件的记录会被过滤掉,而不是保留下来
      SELECT e.empno, e.ename, d.dname
      FROM t_emp e LEFT JOIN t_dept d
      ON e.deptno=d.deptno
      
      # 查询每个部门的名称和部门的人数
      SELECT d.dname, COUNT(e.deptno)
      FROM t_dept d LEFT JOIN t_emp e
      ON d.deptno=e.deptno
      GROUP BY d.deptno
      
      # UNION 关键字可以将多个查询语句的结果集合并
      # 查询每个部门的名称和部门的人数, 没有部门的用null来统计出来
      (SELECT d.dname, COUNT(*)
      FROM t_dept d RIGHT JOIN t_emp e
      ON d.deptno=e.deptno
      GROUP BY d.deptno
      ) UNION
      (SELECT d.dname, COUNT(e.deptno)
      FROM t_dept d LEFT JOIN t_emp e
      ON d.deptno=e.deptno
      GROUP BY d.deptno);
      
      # 查询每名员工的编号、姓名、部门、月薪、工资等级、工龄、上司编号、上司姓名。上司部门
      SELECT 
      	e.empno "员工号", e.ename "姓名", d.dname "部门名称",
      	e.sal + IFNULL(e.comm, 0) "月薪", s.grade "工资等级",
      	FLOOR(DATEDIFF(NOW(),e.hiredate) / 365) "工龄",
      	t.empno "上司编号", t.ename "上司姓名", t.dname "上司部门"
      FROM t_emp e LEFT JOIN t_dept d ON e.deptno=d.deptno
      LEFT JOIN t_salgrade s ON e.sal BETWEEN s.losal AND s.hisal
      LEFT JOIN
      (
      	SELECT e1.empno, e1.ename, d1.dname
      	FROM t_emp e1 JOIN t_dept d1
      	ON e1.deptno=d1.deptno
      ) t ON e.mgr=t.empno;
      
  • 子查询

    • 子查询是一种查询嵌套查询的语句
    • 写在where, select 后的子查询效率很低(不推荐使用)
    • 子查询写在from后面只执行一次(推荐使用)
    SELECT empno, ename, sal
    FROM t_emp
    WHERE sal >= (SELECT AVG(sal) FROM t_emp)
    
  • 单行子查询与多行子查询

    • 单行子查询的结果集只能有一条记录,多行子查询结果集有多行记录
      • 多行子查询只能出现在WHERE和FROM子句种
      • WHERE子句中,可以使用IN,ALL,EXISTS关键字来处理多行表达式结果集的条件判断
      • EXIESTS子句中只要存在就返回true
    # 查询FORD,MARTIN两个人所在部门的所有员工信息
    SELECT ename
    FROM t_emp
    WHERE deptno IN
    (SELECT deptno FROM t_emp WHERE ename IN("FORD","MARTIN"))
    AND ename NOT IN("FORD","MARTIN");
    
    # 查询比FORD和MARTIN底薪都高的员工信息 ALL都要满足
    SELECT ename, sal
    FROM t_emp
    WHERE sal >= ALL(SELECT sal FROM t_emp WHERE ename IN("FORD", "MARTIN"))
    AND ename NOT IN("FORD","MARTIN");
    
    # 查询至少比FORD和MARTIN高一个的员工信息 ANY满足一个即可
    SELECT ename, sal
    FROM t_emp
    WHERE sal >= ANY(SELECT sal FROM t_emp WHERE ename IN("FORD", "MARTIN"))
    AND ename NOT IN("FORD","MARTIN");
    
    # 查询工资等级是3级或者4级的员工信息
    SELECT empno, ename, sal
    FROM t_emp
    WHERE EXISTS(
    	SELECT grade FROM t_salgrade
    	WHERE sal BETWEEN losal AND hisal
    	AND grade IN(3,4)
    )
    

* INSERT

  • MySQL的INSERT语句的方言语法
    • 格式:INSERT [INTO] 表名 SET 字段1 = 值1,…
  • IGNORE关键字:让INSERT只插入数据库不存在的记录
    • 格式:INSERT [IGNORE] INTO 表名 …
# 向技术部添加一条员工记录(根据部门名称查询部门号然后再插入)
# 该子查询只能单行单列的
INSERT INTO t_emp
VALUES(8001, "刘娜", "SALESMAN", 8000, "1988-12-20", 2000, NULL, 
(SELECT deptno FROM t_dept WHERE dname="技术部"))

# MySQL的方言
INSERT [INTO] t_emp
SET empno=8002, ename="JACK", job="SALESMAN", mgr=8000, hiredate="1985-3-19", sal=2500, deptno=50

# INGORE的使用
INSERT IGNORE t_emp
SET empno=8002, ename="JACK", job="SALESMAN", mgr=8000, hiredate="1985-3-19", sal=2500, deptno=50

* UPDATE

UPDATE t_emp SET empno=empno+1, mgr=mgr+1
ORDER BY empno DESC;

# 把月收入前三名的员工的底薪减100元
UPDATE t_emp
SET sal = sal - 100
ORDER BY sal + IFNULL(comm,0) DESC
LIMIT 3;

# 把10部门中,工龄超过20年的员工,底薪增加200元
UPDATE t_emp
SET sal = sal + 200
WHERE deptno=10 AND (DATEDIFF(NOW(),hiredate) / 365) >=20;

# 把ALLEN调往RESEARCH部门,职务调整为ANALYST
UPDATE t_emp e, (SELECT deptno FROM t_dept WHERE dname="RESEARCH") t
SET e.deptno=t.deptno , job="ANALYZE"
WHERE e.ename="ALLEN"
# 表连接写法, 上面是子查询写在update中
UPDATE t_emp e JOIN t_dept d
SET e.deptno=d.deptno, job="ANALYZE"
WHERE e.ename="ALLEN" AND d.dname="RESEARCH";

# 把底薪低于公司平均底薪的员工,底薪增加150元
UPDATE t_emp e, (SELECT AVG(sal) avg FROM t_emp) t
SET sal=sal+150
WHERE e.sal < t.avg;

* DELETE

  • DELETE 语句是在事务机制下删除记录,删除记录之前,先把将要删除的记录保存到日志文件中,然后再删除记录。

  • 临时表是不能删除的

  • TRUNCATE 语句在事务机制之外删除记录,速度元超于DELETE语句

    • TRUNCATE TABLE 表名;
# 删除10部门中,工龄超过20年的员工记录
DELETE FROM t_emp
WHERE deptno=10 and (DATEDIFF(NOW(),hiredate) / 365) > 50;

# 删除20部门中工资最高的员工记录
DELETE FROM t_emp
WHERE deptno=20
ORDER BY sal + IFNULL(comm,0) DESC
LIMIT 1;

# 删除SALES部门和该部门的全部员工记录(表连接语句)
DELETE e, d # 最后执行删除结果集
FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno
WHERE d.dname="SALES";

# 删除每个低于部门平均底薪的员工记录
DELETE e
FROM t_emp e JOIN
(SELECT deptno, AVG(sal) avg_sal FROM t_emp GROUP BY deptno) t
ON e.deptno=t.deptno AND e.sal < t.avg_sal;

# 删除员工KING和他的直接下属的员工记录,用表连接实现
DELETE e1, e2
FROM t_emp e1 JOIN
t_emp e2 ON e1.empno=e2.mgr
WHERE e1.ename="KING";
#或者
DELETE e
FROM t_emp e JOIN
(SELECT empno FROM t_emp WHERE ename="KING") t
ON e.mgr=t.empno OR e.empno=t.empno;

# 删除SALES部门的员工以及没有部门的员工
DELETE e
FROM t_emp e LEFT JOIN
t_dept d ON e.deptno=d.deptno
WHERE d.dname="SALES" OR e.deptno IS NULL;

# 使用TRUNCATE语句删除表
TRUNCATE TABLE t_emp;

* MySQL 内置函数

  • 日期计算的注意事项
    • 两个日期不能直接加减,日期也不能与数字加减
      • 用日期偏移函数DATE_ADD()
        • 格式:DATE_ADD(日期,INTERVAL 偏移量 时间单位)
SELECT ABS(-100); # 100
SELECT ROUND(4.6288*100) / 100; # 4.63
SELECT FLOOR(9.9); # 9
SELECT CEIL(9.1); # 10
SELECT POW(2,3); # 8
SELECT LOG(2,8); # 3
SELECT LN(1); # 0
SELECT PI(); # 3.141593
SELECT SQRT(9); # 3
SELECT COS(RADIANS(60)); # 0.5

# 查询1981年上半年入职的员工人数
SELECT COUNT(empno) FROM t_emp
WHERE DATE_FORMAT(hiredate,"%Y") = 1981
AND DATE_FORMAT(hiredate,"%m") <= 6
SELECT DATE_FORMAT(DATE_ADD(NOW(),Interval 100 DAY),"%y/%m/%d"); # 21/09/27
  • 字符函数
    • LOWER,UPPER,LENGTH,CONCAT9(CONCAT(sal, “$”),INSIR(字符出现的位置)INSERT(插入、替换字符)REPLACE(替换字符)
SELECT INSERT("你好", 1, 0, "先生"); # 先生你好
SELECT LOWER(ename), UPPER(ename), LENGTH(ename),CONCAT("$", sal), INSTR(ename, "A")
FROM t_emp
SELECT INSERT("你好", 1, 1, "先生"); # 先生好
  • SUBSTR, SUBSTRING, LPAD(右侧填充字符), RPAD(右侧填充字符), TRIM(去除首尾空格)
SELECT TRIM("  hello world! "); # hello world!
SELECT LPAD(SUBSTRING("18380743125",8,4), 11, "*"); // *******3125
SELECT RPAD(SUBSTRING("18380743125",1,4), 11, "*"); // *******1838
SELECT RPAD(SUBSTRING("李晓娜", 1, 1),LENGTH("李晓娜") / 3,"*");
  • 条件函数

    • IFNULL(表达式, 值)
    • IF(表达式, 值1, 值2)
    # SALES部门开放礼品A,其余部门发放礼品B,打印每名员工获得的礼品
    SELECT 
    	e.empno, e.ename, d.dname,
    	IF(d.dname="SALES", "礼品A", "礼品B")
    FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno;
    # 复杂的判断
    
    SELECT
    	e.empno, e.ename,
    	CASE
    	WHEN d.dname="SALES" THEN "P1"
    	WHEN d.dname="ACCOUNTING" THEN "P2"
    	WHEN d.dname="RESEARCH" THEN "P3"
    END place
    FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno;
    

* 事务机制

  • 事务的ACID属性:原子性、一致性、隔离性、持久性

    • 原子性:一个事务的所有操作要么全部完成,要么全部失败。事务执行后,不允许停留在中间某个状态
    • 一致性:不管在任何给定的时间、并发事务有多少,事务必须保证运行结果的一致性
    • 隔离性:隔离性要求事务不受其他并发事务的影响,如同在给定的时间内,该事务是数据库唯一运行的事务,默认情况下A事务,只能看到日志中该事务的相关数据
    • 持久性:事务一旦提交,结果便是永久性的,即使宕机,仍然可以依靠事务日志完成数据的持久化
  • 事务的四个隔离级别

    • 1 级别:read uncommitted 功能:读取未提交数据
    • 2 级别:read committed 功能:读取已提交数据
    • 3 级别(默认):repeatable read 功能:重复读取(不受到已提交的影响, 要执行了SQL语句)
    • 4 级别:serializable 功能:序列化
      • 由于事务并发执行所带来的各种问题,前三种隔离级别只适用在某些业务场景中,但是序列化的隔离性,让事务逐一执行,就不会产生上述问题
    # 可以读取到未提交的临时数据
    SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    START TRANSACTION;
    SELECT empno, ename, sal FROM t_emp
    COMMIT;
    
    # 只能读到已提交后的数据
    SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
    START TRANSACTION;
    SELECT empno, ename, sal FROM t_emp
    COMMIT;
    
    SET SESSION TRANSACTION ISOLATION LEVEL repeatable read;
    START TRANSACTION;
    SELECT empno, ename, sal FROM t_emp
    COMMIT;
    
    # 较少使用,上一个事务执行完了,才会执行该事务
    SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    START TRANSACTION;
    SELECT empno, ename, sal FROM t_emp
    COMMIT;
    
  • 数据导出与备份的区别

    • 数据导出,导出的纯粹是业务数据

      • 数据导出分类:SQL文档(其中也包括了表结构)、文本文档(数据较多推荐)
      • mysqldump(用该命令需要将MySQL的bin目录加入环境变量中)用来把业务数据导出成SQL文件
        • 格式:mysqldump -uroot -p [no-data(加上这句只导出表结构,不加这句就是表结构跟数据都导出)] 逻辑库 > 路径
      mysqldump -uroot -p demo > E:\data\demo.sql(导出到的物理路径)
      然后输入密码即可
      
    • 数据导入

      • source命令用于导入SQL文件,包括创建数据库,写入记录等
       USE demo
       SOURCE E:/data/demo.sql;(导入的来源--物理路径)
      
    • 数据备份,备份的是数据文件、日志文件、索引文件等

这篇关于mysql的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!