首页 > 数据库 >Day02.MYSQL高级语法

Day02.MYSQL高级语法

时间:2023-03-05 18:14:38浏览次数:63  
标签:insert 事务 -- Day02 查询 语法 values MYSQL id

MYSQL基础语法

回顾

MySQL管理数据库

创建数据库

CREATE DATABASE IF NOT EXISTS 数据库名;

删除数据库

DROP DATABASE 数据库名;

表的管理

查看所有表

use 数据库名; 选中一个数据库
show tables;

创建表:student(整数id,字符串name,整数age)

CREATE TABLE sutdent (id int, name varchar(20), age int);

查看一个表结构

desc 表名;

查看创建表的sql语句

SHOW CREATE TABLE 表名;

修改表结构

ALTER TABLE 表名 ...

向学生表中添加1列remark varchar(100)

ALTER TABLE student ADD remark varchar(100)

删除学生表列remark

ALTER TABLE student DROP remark;

修改表student名字为student1

REANME TABLE sutdent TO student1;

删除表

DROP TABLE 表名;

管理数据:数据增删改DML

插入数据

INSERT INTO 表名 (字段名1, 字段名2..) VALUES (值1, 值2...);

修改数据

UPDATE 表名 SET 字段名=新的值 WHERE 条件;

删除表中的所有数据

DELETE FROM 表名;
1.排序:
select * from 表名 order by 字段名 asc(升序默认的)/desc(降序),字段名 asc(升序默认的)/desc(降序),..
2.聚合函数:
count(*) 根据列统计行数
sum(字段名)求某一列和值
max(字段名)某一列最大值
min(字段名)某一列最小值
avg(字段名)某一列平均值
3.分组:按照哪列分组,那么那一列的字段值相同就被分为一组
select * from 表名 where 条件 group by 字段名 having 条件
4.分页查询
select * from 表名 limit 起始索引,每页显示的行数;
	起始索引 从0开始,对应第一行
5.约束:
	1)主键约束:字段名 类型 primary key auto_increment
		特点:唯一  非空
	2)唯一约束:字段名 类型 unique
	3)非空约束:字段名 类型 not null
	4)默认值约束:字段名 类型 default 默认值 
	5)外键约束:约束外键,在多表中具有外键。
		【constraint 外键约束名】 foreign key(外键对应的字段名) references 主表(主键);
	6)多表关系:
		1)一对多:将一方的主键作为多方的外键
		2)多对多:创建从表(中间表)维护两张主表的关系,在从表中至少要有两列来自于主表的主键作为外键
		3)一对一:将任意一方的主键作为另一方的外键
		

今日重点

1.约束
2.多表查询(最为重要)
3.事务(mysql如何控制事务)

第一部分(约束和表设计)

1、DQL查询语句-limit语句(掌握)

目标

能够掌握limit语句的使用

讲解

作用:

LIMIT限制的意思,所以LIMIT`的作用就是限制查询记录的条数。

LIMIT语句格式:

select * from 表名 limit  offset, row_count;
mysql中limit的用法:返回前几条或者中间某几行数据
-- 1 表示分页查询的索引,对应数据表是第二行数据,4表示每页显示4条数据
select * from 表名 limit 1,4。
1表示索引,注意这里的索引从0开始。对应表中第一行数据
4表示查询记录数。
上述就表示从第2条记录开始查询,一共查询4条,即到第5条。

具体步骤:

准备数据:

CREATE TABLE student3 (
  id int,
  name varchar(20),
  age int,
  sex varchar(5),
  address varchar(100),
  math int,
  english int
);

INSERT INTO student3(id,NAME,age,sex,address,math,english) VALUES (1,'马云',55,'男','杭州',66,78),(2,'马化腾',45,'女','深圳',98,87),(3,'马景涛',55,'男','香港',56,77),(4,'柳岩',20,'女','湖南',76,65),(5,'柳青',20,'男','湖南',86,NULL),(6,'刘德华',57,'男','香港',99,99),(7,'马德',22,'女','香港',99,99),(8,'德玛西亚',18,'男','南京',56,65);
  • 查询学生表中数据,跳过前面1条,显示4条
我们可以认为跳过前面1条,取4条数据
SELECT * FROM student3 LIMIT 1,4;

LIMIT的使用场景:分页

比如我们登录京东,淘宝,返回的商品信息可能有几万条,不是一次全部显示出来。是一页显示固定的条数。假设我们一每页显示5条记录的方式来分页。

假设我们一每页显示5条记录的方式来分页,SQL语句如下:

-- 每页显示5条
-- 第一页: LIMIT 0,5;	跳过0条,显示5条
-- 第二页: LIMIT 5,5;  跳过5条,显示5条
-- 第三页: LIMIT 10,5; 跳过10条,显示5条
SELECT * FROM student3 LIMIT 0,5;
SELECT * FROM student3 LIMIT 5,5;
SELECT * FROM student3 LIMIT 10,5;

注意

  • 如果第一个参数是0可以简写:
    SELECT * FROM student3 LIMIT 0,5;
    SELECT * FROM student3 LIMIT 5;
  • LIMIT 10,5; -- 不够5条,有多少显示多少

小结

  1. LIMIT语句的使用格式?

    SELECT 字段 FROM 表名 LIMIT 索引, 显示条数;
    索引:从0开始,一直变化
    显示条数:每页显示的行数,固定不变的
    
  2. SELECT 字段名(5) FROM 表名(1) WHERE 条件(2) GROUP BY 分组列名(3) HAVING 条件(4) ORDER BY 排序列名(6) LIMIT 跳过行数, 返回行数(7);
    执行顺序:1234567
    

2、数据库约束的概述

目标

能够说出数据库约束的作用

讲解

数据库约束的作用

​ 对表中的数据进行进一步的限制,保证数据的正确性有效性完整性

约束种类

  • PRIMARY KEY: 主键约束
  • UNIQUE: 唯一约束
  • NOT NULL: 非空约束
  • DEFAULT: 默认值 了解
  • FOREIGN KEY: 外键约束

小结

  1. 数据库约束的作用?
    对表中的数据进行进一步的限制,保证数据的正确性有效性完整性

3、主键约束(掌握)

目标

  1. 能够说出主键约束的作用
  2. 能够添加主键

讲解

主键的作用

用来唯一标识一条记录

为什么需要主键约束

有些记录的 name,age,score 字段的值都一样时,那么就没法区分这些数据,造成数据库的记录不唯一,这样就不方便管理数据。

每张表都应该有一个主键,并且每张表只能有一个主键。

哪个字段作为表的主键

​ 通常不用业务字段作为主键,单独给每张表设计一个id的字段,把id作为主键。主键是给数据库和程序使用的,不是给最终的客户使用的。所以主键有没有含义没有关系,只要不重复,非空就行。

创建主键

主键:PRIMARY KEY
主键的特点

  • 主键必须包含唯一的值
  • 主键列不能包含NULL值

创建主键方式

  1. 在创建表的时候给字段添加主键

    字段名 字段类型 PRIMARY KEY
    
  2. 在已有表中添加主键(了解)

    ALTER TABLE 表名 ADD PRIMARY KEY(字段名);
    

具体操作:

  • 创建表学生表st5, 包含字段(id, name, age)将id做为主键
CREATE TABLE st5 (
	id INT PRIMARY KEY, -- id是主键
	NAME VARCHAR(20),
	age INT
);

  • 添加数据
INSERT INTO st5 (id, NAME,age) VALUES (1, '唐伯虎',20);
INSERT INTO st5 (id, NAME,age) VALUES (2, '周文宾',24);
INSERT INTO st5 (id, NAME,age) VALUES (3, '祝枝山',22);
INSERT INTO st5 (id, NAME,age) VALUES (4, '文征明',26);
  • 插入重复的主键值
-- 主键是唯一的不能重复:Duplicate entry '1' for key 'PRIMARY'
INSERT INTO st5 (id, NAME,age) VALUES (1, '文征明2',30);
  • 插入NULL的主键值
-- 主键是不能为空的:Column 'id' cannot be null
INSERT INTO st5 (id, NAME,age) VALUES (NULL, '文征明3',18);

小结

  1. 说出主键约束的作用?唯一,区分一条记录

  2. 主键的特点?唯一,不能为NULL

  3. 添加主键?
    字段名 字段类型 PRIMARY KEY

    ALTER TABLE 表名 ADD PRIMARY KEY(字段名);

4、主键自增

目标

能够设置主键为自动增长

讲解

​ 主键如果让我们自己添加很有可能重复,我们通常希望在每次插入新记录时,数据库自动生成主键字段的值

字段名 字段类型 PRIMARY KEY AUTO_INCREMENT

AUTO_INCREMENT 表示自动增长(字段类型必须是整数类型)

具体操作:

  • 创建学生表st6, 包含字段(id, name, age)将id做为主键并自动增长
CREATE TABLE st6 (
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20),
	age INT
);
  • 插入数据
-- 主键默认从1开始自动增长
INSERT INTO st6 (NAME, age) VALUES ('唐僧', 22);
INSERT INTO st6 (NAME, age) VALUES ('孙悟空', 26);
INSERT INTO st6 (NAME, age) VALUES ('猪八戒', 25);
INSERT INTO st6 (NAME, age) VALUES ('沙僧', 20);

DELETE和TRUNCATE的区别

  • DELETE 删除表中的数据,但不重置AUTO_INCREMENT的值。
  • TRUNCATE 摧毁表,重建表,AUTO_INCREMENT重置为1

小结

  1. 设置主键为自动增长格式?
    字段名 数据类型 PRIMARY KEY AUTO_INCREMENT

5、唯一约束

目标

  1. 能够说出唯一约束的作用
  2. 能够添加唯一约束

讲解

唯一约束的作用

在这张表中这个字段的值不能重复

唯一约束的基本格式

字段名 字段类型 UNIQUE

具体步骤:

  • 创建学生表st7, 包含字段(id, name),name这一列设置唯一约束,不能出现同名的学生
CREATE TABLE st7 (
	id INT,
	NAME VARCHAR(20) UNIQUE
);
  • 添加一些学生
INSERT INTO st7 VALUES (1, '貂蝉');
INSERT INTO st7 VALUES (2, '西施');
INSERT INTO st7 VALUES (3, '王昭君');
INSERT INTO st7 VALUES (4, '杨玉环');

-- 插入相同的名字出现name重复: Duplicate entry '貂蝉' for key 'name'
INSERT INTO st7 VALUES (5, '貂蝉');

-- 出现多个null的时候会怎样?因为null是没有值,所以不存在重复的问题
INSERT INTO st3 VALUES (5, NULL);
INSERT INTO st3 VALUES (6, NULL);

小结

  1. 说出唯一约束的作用?让这个字段的值不能重复,多个null不算重复
  2. 添加唯一约束格式?字段名 字段类型 UNIQUE

6、非空约束

目标

  1. 能够说出非空约束的作用
  2. 能够添加非空约束

讲解

非空约束的作用

这个字段必须设置值,不能是NULL

非空约束的基本语法格式

字段名 字段类型 NOT NULL

具体操作:

  • 创建表学生表st8, 包含字段(id,name,gender)其中name不能为NULL
CREATE TABLE st8 (
	id INT,
	NAME VARCHAR(20) NOT NULL,
	gender CHAR(2)
);
  • 添加一些完整的记录
INSERT INTO st8 VALUES (1, '郭富城', '男');
INSERT INTO st8 VALUES (2, '黎明', '男');
INSERT INTO st8 VALUES (3, '张学友', '男');
INSERT INTO st8 VALUES (4, '刘德华', '男');

-- 姓名不赋值出现姓名不能为null: Column 'name' cannot be null
INSERT INTO st8 VALUES (5, NULL, '男');

小结

1.非空约束的格式:

​ 字段名 数据类型 NOT NULL

2.问题:
主键约束和唯一约束并且非空的区别:
id primary key 主键约束 可以实现主键自增,一般数据表只有id是主键约束
name unique not null 唯一并且非空 不能实现主键自增 数据表中很多字段都可以是唯一 非空

7、默认值(了解)

目标

  1. 能够说出默认值的作用
  2. 能够给字段添加默认值

讲解

默认值的作用

往表中添加数据时,如果不指定这个字段的数据,就使用默认值

默认值格式

字段名 字段类型 DEFAULT 默认值

具体步骤:

  • 创建一个学生表 st9,包含字段(id,name,address), 地址默认值是广州
CREATE TABLE st9 (
	id INT,
	NAME VARCHAR(20),
	address VARCHAR(50) DEFAULT '广州'
);
  • 添加一条记录,使用默认地址
INSERT INTO st9 (id, NAME) VALUES (1, '刘德华');

  • 添加一条记录,不使用默认地址
INSERT INTO st9 VALUES (2, '张学友', '香港'); 

小结

  1. 说出默认值的作用?不添加这个字段,就会使用默认值
  2. 给字段添加默认值格式? 字段名 字段类型 DEFAULT 默认值

8、表关系的概念和外键约束

在真实的开发中,一个项目中的数据,一般都会保存在同一个数据库中,但是不同的数据需要保存在不同的数据表中。这时不能把所有的数据都保存在同一张表中。

那么在设计保存数据的数据表时,我们就要根据具体的数据进行分析,然后把同一类数据保存在同一张表中,不同的数据进行分表处理。

数据之间必然会有一定的联系,我们把不同的数据保存在不同的数据表中之后,同时还要在数据表中维护这些数据之间的关系。这时就会导致表和表之间必然会有一定的联系。这时要求设计表的人员,就需要考虑不同表之间的具体关系。

在数据库中,表总共存在三种关系,这三种关系如下描述:真实的数据表之间的关系:

多对多关系、一对多(多对一)、一对一(极少)。(一对一关系就是我们之前学习的Map集合的key-value关系)

多对多(掌握)

例如:程序员和项目的关系、老师和学生,学生和课程,顾客和商品的关系等

分析:

程序员和项目:

一个程序员可以参与多个项目的开发,一个项目可以由多个程序员来开发。这种关系就称为多对多关系。

当我们把数据之间的关系分析清楚之后,一般我们需要通过E(Entity)-R(relation)图来展示。 实体 关系 图

一个Java对象,可以对应数据库中的一张表,而Java中类的属性,可以对应表中的字段。

而在E-R图中:

一张表,可以称为一个实体,使用矩形表示,每个实体的属性(字段,表的列),使用椭圆表示。

表和表之间的关系,使用菱形表示。

实体(程序员):编号、姓名、薪资。

实体(项目):编号、名称。

程序员和项目存在关系:一个程序员可以开发多个项目,一个项目可以被多个程序员开发。

说明:如果两张表是多对多的关系,需要创建第三张表,并在第三张表中增加两列,引入其他两张表的主键作为自己的外键。

关系图总结:

创建表的sql语句:

-- 创建程序员表
create table coder(
	id int primary key auto_increment,
	name varchar(50),
	salary double
);
-- 创建项目表
create table project(
	id int primary key auto_increment,
	name varchar(50)
);
-- 创建中间关系表
create table coder_project(
	coder_id int,
	project_id int
);


-- 添加测试数据
insert into coder values(1,'张三',12000);
insert into coder values(2,'李四',15000);
insert into coder values(3,'王五',18000);

insert into project values(1,'QQ项目');
insert into project values(2,'微信项目');

insert into coder_project values(1,1);
insert into coder_project values(1,2);
insert into coder_project values(2,1);
insert into coder_project values(2,2);
insert into coder_project values(3,2);

小结:

1.多对多关系,需要创建第三张表来维护两张主表的关系。在中间表中起码要有两列来自于主表的主键。

外键约束(掌握)

创建第三张关系表即中间表,来维护程序员表和项目表之间的关系。

使用中间表的目的是维护两表多对多的关系:

1 中间表插入的数据 必须在多对多的主表中存在。

2 如果主表的记录在中间表维护了关系,就不能随意删除。如果可以删除,中间表就找不到对应的数据了,这样就没有意义了。

上述是中间表存在的意义,可是我们这里所创建的中间表并没有起到上述的作用,而是存在缺点的:

缺点1: 我们是可以向中间表插入不存在的项目编号和程序员编号的。

说明:在程序员和项目表中是不存在编号是30和20的,但是这里依然可以插入不存在的编号。这样做是不可以的,失去了中间表的意义。

缺点2 : 如果中间表存在程序员的编号, 我们是可以删除程序员表对应的记录的。

在中间表中是存在编号为1的程序员的:

可是我们却可以删除程序员表coder中的编号为1的程序员:

编号为1的程序员张三已经被我们删除,但是在中间表coder_project中仍然还存在编号为1的程序员,这样对于中间表没有意义了。

说明:

创建第三张表的语句:

create table coder_project(

   coder_id int ,--这个外键来自于coder表中的主键

   project_id int--这个外键来自于project表中的主键

);

我们在创建第三张关系表时,表中的每一列,都是在使用其他两张表中的列,这时我们需要对第三张表中的列进行相应的约束。

当前第三张表中的列由于都是引用其他表中的列,我们把第三张表中的这些列称为引用其他表的外键约束。

给某个表中的某一列添加外键约束:

简化语法:

foreign key( 当前表中的列名 )  references 被引用表名(被引用表的列名);
foreign key( coder_id )  references coder(id);

注意:一般在开发中,被引用表的列名都是被引用表中的主键。

举例:

constraint [外键约束名称] foreign key(当前表中的列名) references  被引用表名(被引用表的列名)
举例:constraint coder_project_id foreign key(coder_id) references coder(id);

关键字解释
constraint: 添加约束,可以不写
foreign key(当前表中的列名): 将某个字段作为外键
references 被引用表名(被引用表的列名) : 外键引用主表的主键

给第三张表添加外键约束有两种方式:

第一种方式:给已经存在的表添加外键约束:

-- 来自于程序员表
alter table coder_project add constraint c_id_fk foreign key(coder_id) references coder(id);
-- 来自于项目表
alter table coder_project add constraint p_id_fk foreign key(project_id) references project(id);

第二种方式:创建表时就添加外键约束:

create table coder_project(
	coder_id int,
	project_id int,
    constraint c_id_fk foreign key(coder_id) references coder(id),
    constraint p_id_fk foreign key(project_id) references project(id)
);

了解完如何给第三张表添加外键约束以后,我们就开始给上述创建好的第三张表添加外键约束。

在添加外键约束之前,由于刚才已经修改了表中的数据,所以我们先清空三张表,然后在添加外键约束。

操作步骤:

1、清空上述三张表:

2、增加外键约束:

3、添加完外键约束以后,就会在可视化工具中的架构设计器上查看表之间的关系

先选中表

然后点击右下角:

最后的表关系如下:

3、向三张表中分别插入数据:

-- 插入数据

insert into coder values(null,'张三',12000);
insert into coder values(null,'李四',15000);
insert into coder values(null,'王五',18000);

insert into project values(null,'QQ项目');
insert into project values(null,'微信项目');

insert into coder_project values(1,1);
insert into coder_project values(1,2);
insert into coder_project values(2,1);
insert into coder_project values(2,2);
insert into coder_project values(3,1);

4、测试外键约束是否起到作用:

A:执行以下语句:

B:执行以下语句:

再次执行上述语句的时候,发现报错了,而数据库表中的数据都没有改变,说明外键约束起到了作用。

小结:

1.为何引入外键约束?

让表的数据有效性,正确性。提高查询效率。

2.添加外键约束语法:

constraint 外键约束名 foreign key(当前表的字段名) references 主表(主键);

3.有了外键约束,那么要求添加数据需要先添加主表,然后添加从表。

4.有了外键约束,那么要求删除数据需要先删除从表,然后再删除主表。

外键的级联(掌握)

在修改和删除主表的主键时,同时更新或删除从表的外键值,称为级联操作
ON UPDATE CASCADE -- 级联更新,主键发生更新时,外键也会更新
ON DELETE CASCADE -- 级联删除,主键发生删除时,外键也会删除

具体操作:

  • 删除三张表coder、coder_project、project表
  • 重新创建三张表,添加级联更新和级联删除
-- 创建程序员表
create table coder(
	id int primary key auto_increment,
	name varchar(50),
	salary double
);
-- 创建项目表
create table project(
	id int primary key auto_increment,
	name varchar(50)
);
create table coder_project(
	coder_id int,
	project_id int,
    -- 添加外键约束,并且添加级联更新和级联删除
    constraint c_id_fk foreign key(coder_id) references coder(id) ON UPDATE CASCADE ON DELETE CASCADE,
    constraint p_id_fk foreign key(project_id) references project(id) ON UPDATE CASCADE ON DELETE CASCADE
);

再次添加数据到三张表:

-- 添加测试数据
insert into coder values(1,'张三',12000);
insert into coder values(2,'李四',15000);
insert into coder values(3,'王五',18000);

insert into project values(1,'QQ项目');
insert into project values(2,'微信项目');

insert into coder_project values(1,1);
insert into coder_project values(1,2);
insert into coder_project values(2,1);
insert into coder_project values(2,2);
insert into coder_project values(3,2);

需求1:修改主表coder表的id为3变为4.

需求2:删除主表coder表的id是4的行数据。

小结:

级联更新:ON UPDATE CASCADE 主键修改后,外键也会跟着修改

级联删除:ON DELETE CASCADE 主键删除后,外键对应的数据也会删除

一对多(掌握)

一对多的关系表:其中也有2个实体,但是其中A实体中的数据可以对应另外B实体中的多个数据,反过来B实体中的多个数据只能对应A实体中的一个数据。

例如:作者和小说关系,班级和学生,部门和员工,客户和订单

分析:

作者和小说:

一个作者可以写多部小说,但每一部小说,只能对应具体的一个作者。

具体的关系如下图所示:

注意:如果是一对多的关系,那么设计表的时候需要在多的一方增加一列,引入一的一方的主键作为自己的外键。

一对一

一对一关系表在实际开发中使用的并不多,其中也是2个实体,其中A实体中的数据只能对应B实体中的一个数据,同时B实体中的数据也只能对应A实体中的一个数据。例如:人和身份证对应关系,老公和老婆的对应关系。

而一对一在建表的时候,可以在任意一方的表中添加另外一方的主键作为外键即可。

建表原理如下图所示:

小结:

1.多对多:创建第三张表维护两张主表的关系,在第三张表中起码要有两列来自于两张主表的主键

2.一对多:在多方增加一列,来自于一方的主键作为外键

3.一对一:在任意一方将另一方的主键作为外键

9、表设计案例(练习)

目标

设计学生成绩管理系统数据表(按照给定需求设计即可)

1、每个教师可以教多门课程

2、每个课程由一个老师负责

3、每门课程可以由多个学生选修

4、每个学生可以选修多门课程

5、学生选修课程要有成绩

讲解

具体操作:

1)分析:

​ 当我们拿到一个需求之后,首先应该分析这个需求中到底有多少名词,或者是当前这个需求中可以抽象出具体几个E-R图中的实体对象。

分析需求中存在的实体: 实体使用矩形表示。

学生、课程、老师。

当分析清楚具体的实体之后,接着要分析实体具备哪些属性?属性使用椭圆形表示。

学生:学号、姓名等。

课程:课程编号、课程名称等。

老师:工号、姓名等。

最后就要考虑实体和实体之间的关系问题:

老师和课程之间:一对多关系。一个老师可以教授多门课程,一个课程只能由一个老师负责。

学生和课程之间:多对多关系。每个学生可以选修多门课程,每门课程可以被多个学生来选修。

2)关于设计学生成绩管理系统的数据表的E-R图如下所示:

3)创建表sql语句:

画完E-R图之后,接下来我们就根据E-R图来创建具体的数据库表了。

学生选课管理系统的表创建:

思考:先创建哪张表?

不能先创建课程表,因为课程表需要有教师的工号,也不能创建中间表,因为中间表需要课程表和学生表的id,所以我们可以创建表的顺序如下:

-- 1、教师表

-- 2、课程表

-- 3、学生表

-- 4、学生课程表(中间关系表要有成绩属性)

创建表的语句如下:

-- 1、教师表
create table teacher(
	id int primary key auto_increment,
	name varchar(50)
);
-- 2、课程表
create table course(
	id int primary key auto_increment,
	name varchar(50),
	teacher_id int,
	foreign key(teacher_id) references teacher(id)
);
-- 3、学生表
create table student(
	id int primary key auto_increment,
	name varchar(50)
);
-- 4、学生课程表(中间关系表要有成绩属性)
create table studentcourse(
	student_id int,
	course_id int,
	score double,
	foreign key(student_id) references student(id),
	foreign key(course_id) references course(id)
);

创建表之后的结构:

作业:多表练习

一对多关系练习

以下案例是我们JavaWeb课程最后的小项目.我们拿出其中一部分需求,根据需求来设计数据库表之间的关系

一个旅游线路分类中有多条旅游线路 , 一条旅游线路属于某一个分类 . 旅游线路表是多表 ,可以在多表上添加一个外键来执行分类表中的主键.

具体操作:
  • 创建旅游线路分类表
CREATE TABLE tab_category (
   cid INT PRIMARY KEY AUTO_INCREMENT, -- 旅游线路分类主键
   cname VARCHAR(100) NOT NULL UNIQUE -- 旅游线路分类名称
);
  • 添加旅游线路分类数据
INSERT INTO tab_category (cname) VALUES ('周边游'), ('出境游'), ('国内游'), ('港澳游');
  • 创建旅游线路表
CREATE TABLE tab_route (
   rid INT PRIMARY KEY AUTO_INCREMENT, -- 旅游线路主键
   rname VARCHAR(100) NOT NULL UNIQUE, -- 旅游线路名称
   price DOUBLE NOT NULL,  -- 价格
   cid INT NOT NULL, -- 所属分类
   CONSTRAINT ro_cid_ref_cate_id FOREIGN KEY(cid) REFERENCES tab_category(cid)
);
  • 添加旅游线路测试数据(自行添加)

多对多关系练习

一个用户可以收藏多个线路,一个线路可以被多个用户收藏 ,所以用户和线路之间是多对多的关系.对于多对多的关系我们需要增加一张中间表来维护他们之间的关系

具体操作:
  • 创建用户表
CREATE TABLE tab_user (
   uid INT PRIMARY KEY AUTO_INCREMENT, -- 用户id
   username VARCHAR(100) NOT NULL UNIQUE -- 用户名
);
  • 添加用户数据
INSERT INTO tab_user VALUES
(NULL, '老王'),
(NULL, '小王');
  • 创建收藏表
CREATE TABLE tab_favorite (
   fid INT PRIMARY KEY AUTO_INCREMENT, -- 收藏主键
   rid INT NOT NULL, -- 旅游线路id
   DATE DATE NOT NULL, -- 收藏时间
   uid INT NOT NULL -- 用户id
);

注意 : 可以自己尝试着给收藏表添加外键约束

  • 增加收藏表测试数据(自行添加)

第二部分(多表查询)

1、多表查询介绍(掌握)

目标

了解什么是多表查询,及多表查询的两种方式

讲解

什么是多表查询

同时查询多张表获取到需要的数据
比如:我们想查询水果的对应价格,需要将水果表和价格表同时进行查询

一种水果一种价格。

一种价格多种水果。

价格和水果属于一对多。

将一方即价格的主键作为多方即水果的外键。

多表查询的分类

1550291804592

小结

什么是多表查询?通过查询多张表获取我们想要的数据

2、笛卡尔积现象

目标

能够说出什么是笛卡尔积,以及如何消除笛卡尔积

讲解

准备数据

有两张表,一张是水果表fruit,一张是价格表price。

分析:

一种水果一种价格。

一个价格对应多种水果。

价格和水果是1对多

价格是1 水果是多

表设计原则:将价格的主键作为水果的外键

建表:

-- 价格 1
create table price( 
   id int primary key auto_increment,
   price double
);
-- 水果 n
create table fruit(
  id int primary key auto_increment,
  name varchar(20) not null,
  price_id int,
  foreign key(price_id) references price(id)
);
insert into price values(1,2.30);
insert into price values(2,3.50);
insert into price values(4,null);

insert into fruit values(1,'苹果',1);
insert into fruit values(2,'橘子',2);
insert into fruit values(3,'香蕉',null);
-- 一种水果有一个价格 一个价格对应多种水果
-- 价格 1 水果 n 水果将价格主键作为外键

什么是笛卡尔积现象

需求:查询两张表中关于水果的信息,要显示水果名称和水果价格。

具体操作:

多表查询语法:select * from fruit,price;

查询结果:

产生上述查询结果的原因:

说明:

fruit表中的每一条记录,都和price表中的每一条进行匹配连接。所得到的最终结果是:fruit表中的条目数乘以price表中的数据的条目数。

将fruit表的每行记录和price表的每行记录组合的结果就是笛卡尔积。

笛卡尔积问题:把多张表放在一起,同时去查询,会得到一个结果,而这结果并不是我们想要的数据,这个结果称为笛卡尔积。

笛卡尔积缺点:查询到的结果冗余了,里面有很多错误的数据,需要过滤。

举例:上述的笛卡尔积结果中只有两行结果是正确的:

1 苹果 1 1 2.3

2 橘子 2 2 3.5

笛卡尔积的数据,对程序是没有意义的, 我们需要对笛卡尔积中的数据再次进行过滤。

对于多表查询操作,需要过滤出满足条件的数据,需要把多个表进行连接,连接之后需要加上过滤的条件。

如何清除笛卡尔积现象的影响

解决上述查询的方案:在查询两张表的同时添加条件进行过滤,比如fruit表的id和必须和price表的id相同。

小结

  1. 能够说出什么是笛卡尔积?
    左表的每条记录和右表的每条记录会组合起来

  2. 如何消除笛卡尔积
    只查询满足要求的数据,通常都是外键等于主键

  3. 给表起别名:

    -- 别名写法:表名 as 别名  这里as可以省略
    select * from fruit as f,price as p where f.price_id = p.id;
    

3、内连接

目标

能够掌握内连接的使用

讲解

什么是内连接

用左边表的记录去匹配右边表的记录,如果符合条件的则显示。内连接查询的结果:两表的公共部分。

隐式内连接

隐式内连接:看不到JOIN关键字,条件使用WHERE指定

语法:
select 列名 , 列名 .... from 表名1,表名2,.... where 表名1.列名 = 表名2.列名;
select * from fruit,price where fruit.price_id = price.id;

说明:在产生两张表的笛卡尔积的数据后,通过条件筛选出正确的结果。

显示内连接(掌握)

显示内连接:使用INNER JOIN ... ON语句, 可以省略INNER

语法:
select * from 表名1  inner join 表名2 inner join 表名3 inner join 表名4 ..... on 多个条件;
或者
select * from 表名1  join 表名2 on 条件 

具体操作:

  • 使用显示内连接解决上述笛卡尔积问题

说明:显示的内连接,一般称为标准的内连接,有inner join,查询到的数据为两个表经过on条件过滤后的笛卡尔积。

  • 应用

查询苹果的信息,显示苹果id,名字,和价格。

1.确定查询哪些表

2.确定表连接条件,水果表.price_id = 价格表.id 的数据才是有效的

3.确定查询条件,我们查询的是苹果的信息,水果表.name='苹果'

4.确定查询字段,查询苹果的信息,显示苹果id,名字,和价格

5.我们发现写表名有点长,可以给表取别名,显示的字段名也使用别名

-- 1.确定查询哪些表
select * from fruit f inner join price p;
-- 2.确定表连接条件
select * from fruit f inner join price p on f.price_id = p.id;
-- 3.确定查询条件,我们查询的是苹果的信息,水果表.name='苹果'
select * from fruit f inner join price p on f.price_id = p.id where f.name='苹果';
-- 4. 确定查询哪些列
select f.id,f.name,p.id,p.price from fruit f inner join price p on f.price_id = p.id where f.name='苹果';

小结

  1. 什么是隐式内连接和显示内连接?
    隐式内连接:看不到JOIN:select 列名 , 列名 .... from 表名1,表名2 where 表名1.列名 = 表名2.列名;
    显示内连接:看得到JOIN:select * from 表名1 inner join 表名2 on 条件;
  2. 内连接查询步骤?
    1.确定查询几张表
    2.确定表连接条件
    3.根据需要在操作

4、左外连接

目标

能够掌握左外连接查询

讲解

左外连接原理如下所示:

左外连接可以理解为:用左边表去右边表中查询对应记录,不管是否找到,都将显示左边表中全部记录。

举例:上述案例中虽然右表没有香蕉对应的价格,也要把他查询出来。

左外连接:使用LEFT OUTER JOIN ... ONOUTER可以省略

select * from 表1 left outer join 表2 on 条件;
把left 关键字之前的表,是定义为左侧。 left关键字之后的表,定义右侧。
查询的内容,以左侧的表为主,如果左侧有数据,右侧没有对应的数据,仍然会把左侧数据进行显示。

具体操作:

  • 不管能否查到水果对应的价格,都要把水果显示出来。

分析:香蕉是没有价格的,但是由于香蕉位于左边的表中,所以即使香蕉的价格是null,也会将香蕉的信息显示出来。

小结

  1. 掌握左外连接查询格式?

    select * from 表1 left outer join 表2 on 条件;
    -- 表1看作为左表,表2看做为右表
    
  2. 左外连接查询特点?
    在满足要求的基础上保证左表的数据全部显示

5、右外连接

目标

能够掌握右外连接查询

讲解

右外连接原理如下所示:

用右边表去左边表查询对应记录,不管是否找到,右边表全部记录都将显示。

举例:上述案例中不管在左方表能否找到右方价格对应的水果,都要把右方的价格显示出来。

右外连接:使用RIGHT OUTER JOIN ... ONOUTER可以省略

语法:select * from 表1 right outer join 表2 on 条件;
说明:如果右侧有数据,左侧没匹配到,把右侧的数据显示出来。
right之前的是左侧,right之后的是右侧。

具体操作:

  • 需求:不管能否查到价格对应的水果,都要把价格显示出来。

分析:在price表中id为4到fruit表中查询是没有对应水果描述的,但是使用右外连接也会将price表中的价格查询出来。

注意:其实关于左外连接和右外连接只记住一种就可以,只需将表的前后位置换一下就可以达到互换。

需求:使用左外连接达到上述右外连接的效果。

小结

  1. 掌握右外连接查询格式?

    select * from 表1 right outer join 表2 on 条件;
    
  2. 右外连接查询特点?
    在满足要求的基础上,保证右表的数据全部显示.

  3. 其实对于左右外连接我们只需要掌握一种,即可,因为左右外可以互换。

    -- 右外连接:查询right右边表以及两张表的公共部分
    -- 需求:不管能否查到价格对应的水果,都要把价格显示出来。
    -- 在right右边的表2是右表,以右表为主
    select * from fruit f right outer join price p
    on f.price_id = p.id;
    
    -- 需求:使用左外连接使用上述功能:
    -- 不管能否查到价格对应的水果,都要把价格显示出来。
    select * from price p left outer join  fruit f 
    on f.price_id = p.id;
    

6、子查询

目标

能够掌握子查询的概念

能够理解子查询的三种情况

讲解

准备数据:

-- 创建部门表 1
CREATE TABLE dept (
  id INT PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR(20)
);

INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');

-- 创建员工表 n
CREATE TABLE emp (
  id INT PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR(10),
  gender CHAR(1),   -- 性别
  salary DOUBLE,   -- 工资
  join_date DATE,  -- 入职日期
  dept_id INT,
  foreign key(dept_id) references dept(id)
);

INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'2013-02-24',1);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'2010-12-02',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'2008-08-08',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'2015-10-07',3);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'2011-03-14',1);

image-20200802103333568

什么是子查询

一条查询语句结果作为另一条查询语法一部分。
SELECT 查询字段 FROM 表 WHERE 条件;
举例:
SELECT * FROM employee WHERE salary=(SELECT MAX(salary) FROM employee);


说明:子查询需要放在()中

子查询结果的三种情况

  1. 子查询的结果是单行单列的时候
  2. 子查询的结果是多行单列的时候
  3. 子查询的结果是多行多列

小结

  1. 什么是子查询?
    一个查询的结果作为另一个查询语句的一部分
  2. 子查询结果的三种情况?
    单行单列
    多行单列
    多行多列

7、子查询的结果是单行单列的时候

目标

能够掌握子查询的结果是单行单列的查询

讲解

子查询结果是单列,在WHERE后面作为条件
SELECT 查询字段 FROM 表 WHERE 字段=(子查询);

  1. 查询工资最高的员工是谁?

    1. 查询最高工资是多少
    SELECT MAX(salary) FROM emp;
    

    2.根据最高工资到员工表查询到对应的员工信息

      SELECT * FROM emp WHERE salary=(SELECT MAX(salary) FROM emp);
    

  2. 查询工资小于平均工资的员工有哪些?

    1. 查询平均工资是多少
    SELECT AVG(salary) FROM emp;
    

    ​ 2.到员工表查询小于平均的员工信息

    SELECT * FROM emp WHERE salary < (SELECT AVG(salary) FROM emp);
    

小结

子查询的结果是单行单列时父查询如何处理?
SELECT 查询字段 FROM 表 WHERE 字段=(子查询);

通常作为父查询的条件

8、子查询结果是多行单列的时候

目标

能够掌握子查询的结果是多行单列的查询

讲解

子查询结果是多行单列,结果集类似于一个数组,在WHERE后面作为条件,父查询使用IN运算符

SELECT 查询字段 FROM 表 WHERE 字段 IN (子查询);
-- in表示在数值中
  1. 查询工资大于5000的员工,来自于哪些部门的名字

    1. 先查询大于5000的员工所在的部门id
    SELECT dept_id FROM emp WHERE salary > 5000;
    

    1. 再查询在这些部门id中部门的名字
    SELECT dept.name FROM dept WHERE dept.id IN (SELECT dept_id FROM emp WHERE salary > 5000);
    

  2. 查询开发部与财务部所有的员工信息

    1. 先查询开发部与财务部的id
    SELECT id FROM dept WHERE NAME IN('开发部','财务部');
    

    1. 再查询在这些部门id中有哪些员工
    SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME IN('开发部','财务部'));
    

小结

1.子查询的结果是多行单列时父查询如何处理?
放在父查询的条件位置,使用in

2.in用法:in(值1,值2,....) 只要满足一个即可,或者的关系

9、子查询的结果是多行多列

目标

能够掌握子查询的结果是多行多列的查询

讲解

子查询结果是多列,在FROM后面作为

SELECT 查询字段 FROM (子查询) 表别名 WHERE 条件;

注意:子查询作为表需要取别名,使用as,可以省略。否则这张表没用名称无法访问表中的字段

  • 查询出2011年以后入职的员工信息,包括部门名称

    1. 在员工表中查询2011-1-1以后入职的员工
    SELECT * FROM emp WHERE join_date > '2011-1-1';
    

    1. 查询所有的部门信息,与上面的虚拟表中的信息组合,找出所有部门id等于dept_id
    SELECT * FROM dept d, (SELECT * FROM emp WHERE join_date > '2011-1-1') e WHERE e.dept_id = d.id;
    

使用表连接:

SELECT d.*, e.* FROM dept d INNER JOIN emp e ON d.id = e.dept_id WHERE e.join_date > '2011-1-1';

小结

三种子查询情况:单行单列,多行单列,多行多列
单行单列:作为父查询的条件
多行单列:作为父查询的条件,通常使用 IN
多行多列:作为父查询的一张表(虚拟表),起别名

10、多表查询案例(子查询)

​ 我们在公司开发中,根据不同的业务需求往往需要通过2张及以上的表中去查询需要的数据。所以我们有必要学习2张及以上的表的查询。其实不管是几张表的查询,都是有规律可循的。

准备数据

重新新建一个数据库,然后在新建的数据库中创建如下数据表,并插入数据:

teacher 教师表

student 学生表

cource 课程表

studentcource 选课表 学生和课程的关系表

create table teacher (
  id int(11) primary key auto_increment,
  name varchar(20) not null unique
 );
create table student (
  id int(11)  primary key auto_increment,
  name varchar(20) NOT NULL unique,
  city varchar(40) NOT NULL,
  age int 
) ;
create table course(
  id int(11)  primary key auto_increment,
  name varchar(20) not null unique,
  teacher_id int(11) not null,
  foreign key(teacher_id) references teacher (id)
);

create table studentcourse (
   student_id int NOT NULL,
   course_id int NOT NULL,
   score double NOT NULL,
   foreign key (student_id) references student (id),
   foreign key (course_id) references course (id)
);

insert into teacher values(null,'关羽');
insert into teacher values(null,'张飞');
insert into teacher values(null,'赵云');

insert into student values(null,'小王','北京',20);
insert into student values(null,'小李','上海',18);
insert into student values(null,'小周','北京',22);
insert into student values(null,'小刘','北京',21);
insert into student values(null,'小张','上海',22);
insert into student values(null,'小赵','北京',17);
insert into student values(null,'小蒋','上海',23);
insert into student values(null,'小韩','北京',25);
insert into student values(null,'小魏','上海',18);
insert into student values(null,'小明','广州',20);

insert into course values(null,'语文',1);
insert into course values(null,'数学',1);
insert into course values(null,'生物',2);
insert into course values(null,'化学',2);
insert into course values(null,'物理',2);
insert into course values(null,'英语',3);

insert into studentcourse values(1,1,80);
insert into studentcourse values(1,2,90);
insert into studentcourse values(1,3,85);
insert into studentcourse values(1,4,78);
insert into studentcourse values(2,2,53);
insert into studentcourse values(2,3,77);
insert into studentcourse values(2,5,80);
insert into studentcourse values(3,1,71);
insert into studentcourse values(3,2,70);
insert into studentcourse values(3,4,80);
insert into studentcourse values(3,5,65);
insert into studentcourse values(3,6,75);
insert into studentcourse values(4,2,90);
insert into studentcourse values(4,3,80);
insert into studentcourse values(4,4,70);
insert into studentcourse values(4,6,95);
insert into studentcourse values(5,1,60);
insert into studentcourse values(5,2,70);
insert into studentcourse values(5,5,80);
insert into studentcourse values(5,6,69);
insert into studentcourse values(6,1,76);
insert into studentcourse values(6,2,88);
insert into studentcourse values(6,3,87);
insert into studentcourse values(7,4,80);
insert into studentcourse values(8,2,71);
insert into studentcourse values(8,3,58);
insert into studentcourse values(8,5,68);
insert into studentcourse values(9,2,88);
insert into studentcourse values(10,1,77);
insert into studentcourse values(10,2,76);
insert into studentcourse values(10,3,80);
insert into studentcourse values(10,4,85);
insert into studentcourse values(10,5,83);

分析4张表的关系:

练习1

目标

查询获得最高分的学生信息。

讲解

具体操作:

分析:

1)在中间表中找最高分;

2)在中间表中找最高分对应的学生编号;

3)在学生表中根据学生编号找学生信息;

练习2

目标

查询编号是2的课程比编号是1的课程最高成绩高的学生信息。

讲解

具体操作:

课程编号和对应的成绩的部分数据:

分析:

1)在中间表中 找编号是1的课程的最高成绩;

2)在中间表中 找编号是2的成绩 > 编号1最高成绩 的学生id;

3)在学生表中 根据学生的编号 找对应的学生信息;

Sql语句如下所示:

-- 需求2:查询编号2课程 比 编号1课程最高成绩高学生信息:
-- 2.1 在中间表 找编号1课程的最高成绩
select max(score)
from studentcourse 
where course_id=1;
-- 2.2 在中间表找 编号2的成绩 > 编号1最高成绩 的学生id
select student_id
from studentcourse
where course_id=2 and score>(select max(score)
							 from studentcourse 
							 where course_id=1);
-- 2.3 在学生表 根据编号 找对应的学生信息
select *
from student
where id in (select student_id
			 from studentcourse
			 where course_id=2 and score>(select max(score)
										  from studentcourse 
										  where course_id=1));

查询结果:

练习3

目标

查询编号是2的课程比编号是1的课程最高成绩高的学生姓名和成绩。

讲解

具体操作:

分析:

1)在中间表中 找编号是1的课程的最高成绩;

2)在中间表中 找编号是2的成绩 > 编号1最高成绩 的学生id和成绩;

3)将上述查询出来的内容作为临时表 和 学生表关联, 查询姓名和成绩

-- 需求3:查询编号2课程比编号1课程最高成绩高学生姓名和成绩 (临时表)		
-- 2.1 在中间表 找编号1课程的最高成绩
select max(score)
from studentcourse 
where course_id=1;
-- 2.2 在中间表 编号2的成绩 > 编号1最高成绩 的学生id,成绩
select student_id,score
from studentcourse
where course_id=2 and score>(select max(score)
							 from studentcourse 
							 where course_id=1);
-- 2.3 将上述查询出来的内容作为临时表 和 学生表关联, 查询姓名和成绩
select student.name, temp.score
from student, (select student_id,score
			   from studentcourse
			   where course_id=2 and score>(select max(score)
										    from studentcourse 
										    where course_id=1)) as temp
where student.id=temp.student_id;

练习4

目标

查询每个同学的学号、姓名、选课数、总成绩。

讲解

分析:

1)、在中间表中查询每个学生的选课数和总成绩,遇到每个,分组,按照学生学号进行分组;

2)、由于还得显示学号和姓名,并且姓名在student表中,所以我们将上述结果作为临时表和学生表关联。

目的是查找临时表和student表中学号相等时查找学号,姓名,选课数,总成绩。

-- 2、查询所有同学的学号、姓名、选课数、总成绩
-- 2.1 在中间表 查询每个学生的选课数和总成绩
select student_id,count(*),sum(score)
from studentcourse
group by student_id;
-- 2.2 将2.1的结果作为临时表和学生表关联,
-- 目的: 显示 学号、姓名、选课数、总成绩
select student.id,student.name,temp.cou,temp.sumScore
from student,(select student_id,count(*) as cou,sum(score) as sumScore
			  from studentcourse
			  group by student_id) as temp
where student.id=temp.student_id;

注意:

如果我们想使用聚合函数作为查找的结果,并且聚合函数存在子查询语句中,那么我们不能直接将聚合函数写在select后面,我们此时应该给聚合函数取别名。

11、 多表查询案例(连接查询)

​ 我们在公司开发中,根据不同的业务需求往往需要通过2张及以上的表中去查询需要的数据。所以我们有必要学习2张及以上的表的查询。其实不管是几张表的查询,都是有规律可循的。

1.准备数据

-- 部门表
CREATE TABLE dept (
  id INT PRIMARY KEY PRIMARY KEY, -- 部门id
  dname VARCHAR(50), -- 部门名称
  loc VARCHAR(50) -- 部门位置
);

-- 添加4个部门
INSERT INTO dept(id,dname,loc) VALUES 
(10,'教研部','北京'),
(20,'学工部','上海'),
(30,'销售部','广州'),
(40,'财务部','深圳');

-- 职务表,职务名称,职务描述
CREATE TABLE job (
  id INT PRIMARY KEY,
  jname VARCHAR(20),
  description VARCHAR(50)
);

-- 添加4个职务
INSERT INTO job (id, jname, description) VALUES
(1, '董事长', '管理整个公司,接单'),
(2, '经理', '管理部门员工'),
(3, '销售员', '向客人推销产品'),
(4, '文员', '使用办公软件');

-- 员工表
CREATE TABLE emp (
  id INT PRIMARY KEY, -- 员工id
  ename VARCHAR(50), -- 员工姓名
  job_id INT, -- 职务id
  mgr INT , -- 上级领导
  joindate DATE, -- 入职日期
  salary DECIMAL(7,2), -- 工资
  bonus DECIMAL(7,2), -- 奖金
  dept_id INT, -- 所在部门编号
  CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job (id),
  CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY (dept_id) REFERENCES dept (id)
);

-- 添加员工
INSERT INTO emp(id,ename,job_id,mgr,joindate,salary,bonus,dept_id) VALUES 
(1001,'孙悟空',4,1004,'2000-12-17','8000.00',NULL,20),
(1002,'卢俊义',3,1006,'2001-02-20','16000.00','3000.00',30),
(1003,'林冲',3,1006,'2001-02-22','12500.00','5000.00',30),
(1004,'唐僧',2,1009,'2001-04-02','29750.00',NULL,20),
(1005,'李逵',4,1006,'2001-09-28','12500.00','14000.00',30),
(1006,'宋江',2,1009,'2001-05-01','28500.00',NULL,30),
(1007,'刘备',2,1009,'2001-09-01','24500.00',NULL,10),
(1008,'猪八戒',4,1004,'2007-04-19','30000.00',NULL,20),
(1009,'罗贯中',1,NULL,'2001-11-17','50000.00',NULL,10),
(1010,'吴用',3,1006,'2001-09-08','15000.00','0.00',30),
(1011,'沙僧',4,1004,'2007-05-23','11000.00',NULL,20),
(1012,'李逵',4,1006,'2001-12-03','9500.00',NULL,30),
(1013,'小白龙',4,1004,'2001-12-03','30000.00',NULL,20),
(1014,'关羽',4,1007,'2002-01-23','13000.00',NULL,10);

-- 工资等级表
CREATE TABLE salarygrade (
  grade INT PRIMARY KEY,
  losalary INT, -- 最低薪资
  hisalary INT -- 最高薪资
);

-- 添加5个工资等级
INSERT INTO salarygrade(grade,losalary,hisalary) VALUES 
(1,7000,12000),
(2,12010,14000),
(3,14010,20000),
(4,20010,30000),
(5,30010,99990);

分析4张表的关系:通过4张表可以查出一个员工的所有信息

image-20200727092438331

说明:一个部门有多种职务,例如销售部有经理和销售员。一种职务可以在多个部门,例如文员可以在学工部和教研部。

2 练习

1.1 练习1

查询所有员工信息。显示员工编号,员工姓名,工资,职务名称,职务描述。

image-20200727093014584

具体操作:
1.确定要查询哪些表:emp e, job j

SELECT * FROM emp e INNER JOIN job j;

2.确定表连接条件: e.job_id=j.id

SELECT * FROM emp e INNER JOIN job j ON e.job_id=j.id;


3.确定查询字段:员工编号,员工姓名,工资,职务名称,职务描述

SELECT e.id, e.ename, e.salary, j.jname, j.description FROM emp e INNER JOIN job j ON e.job_id=j.id;

1.2 练习2

查询所有员工信息。显示员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置

具体操作:

  1. 确定要查询哪些表,emp e, job j, dept d

    image-20200727093902316

SELECT * FROM emp e INNER JOIN job j INNER JOIN dept d;


  2. 确定表连接条件 e.job_id=j.id and e.dept_id=d.id
SELECT * FROM emp e INNER JOIN job j INNER JOIN dept d ON e.job_id=j.id AND e.dept_id=d.id;


  3. 确定查询字段:员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
SELECT e.id, e.ename, e.salary, j.jname, j.description, d.dname, d.loc FROM emp e INNER JOIN job j INNER JOIN dept d ON e.job_id=j.id AND e.dept_id=d.id;

或者:
SELECT e.id,e.ename,e.salary,j.jname,j.description,d.dname,d.loc
FROM emp e INNER JOIN job j ON e.job_id = j.id INNER JOIN dept d on e.dept_id = d.id;

1.3 练习3

查询所有员工信息。显示员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级。

image-20200727204121609

具体操作:
1. 确定要查询哪些表,emp e, job j, dept d, salarygrade s

SELECT * FROM emp e INNER JOIN job j INNER JOIN dept d INNER JOIN salarygrade s;


  2. 确定表连接条件 e.job_id=j.id and e.dept_id=d.id and e.salary between s.losalary and s.hisalary
SELECT * FROM emp e INNER JOIN job j INNER JOIN dept d INNER JOIN salarygrade s ON e.job_id=j.id AND e.dept_id=d.id AND e.salary BETWEEN s.losalary AND s.hisalary;


  3. 确定查询字段:员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
SELECT e.ename, e.salary, j.jname, j.description, d.dname, d.loc, s.grade FROM emp e INNER JOIN job j INNER JOIN dept d INNER JOIN salarygrade s ON e.job_id=j.id AND e.dept_id=d.id AND e.salary BETWEEN s.losalary AND s.hisalary;

1.3.1 多表查询规律总结
  1. 不管我们查询几张表,表连接查询会产出笛卡尔积,我们需要消除笛卡尔积,拿到正确的数据。我们需要找到表与表之间通过哪个字段关联起来的(通常是外键=主键
  2. 消除笛卡尔积规律:2张表需要1个条件,3张表需要2个条件,4张表需要3个条件。(条件数量=表的数量-1),每张表都要参与进来
  3. 多表连接查询步骤:
    3.1. 确定要查询哪些表
    3.2. 确定表连接条件
    3.3. 确定查询字段

1.4 练习4

查询经理的信息。显示员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级

具体操作:
1. 确定要查询哪些表,emp e, job j, dept d, salarygrade s

SELECT * FROM emp e INNER JOIN job j INNER JOIN dept d INNER JOIN salarygrade s;


  2. 确定表连接条件 e.job_id=j.id and e.dept_id=d.id and e.salary between s.losalary and s.hisalary
SELECT * FROM emp e INNER JOIN job j INNER JOIN dept d INNER JOIN salarygrade s ON e.job_id=j.id AND e.dept_id=d.id AND e.salary BETWEEN s.losalary AND s.hisalary;


额外条件:只需要查询经理的信息(j.jname='经理')

  3. 确定查询字段:员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
SELECT e.ename, e.salary, j.jname, j.description, d.dname, d.loc, s.grade FROM emp e INNER JOIN job j INNER JOIN dept d INNER JOIN salarygrade s ON e.job_id=j.id AND e.dept_id=d.id AND e.salary BETWEEN s.losalary AND s.hisalary AND j.jname='经理';

1.5 练习5

查询出每个部门的部门编号、部门名称、部门位置、部门人数

具体操作:
1. 去员工表中找到每个部门的人数和部门id

SELECT dept_id, COUNT(*) FROM emp GROUP BY dept_id;

  2. 再和部门表连接查询
SELECT * FROM dept d INNER JOIN (SELECT dept_id, COUNT(*) FROM emp GROUP BY dept_id) e ON e.dept_id=d.id;


  3. 显示对应的字段
SELECT d.id, d.dname, d.loc, e.total 部门人数 FROM dept d INNER JOIN (SELECT dept_id, COUNT(*) total FROM emp GROUP BY dept_id) e ON e.dept_id=d.id;


最终效果:

学习总结

  1. 能够使用内连接进行多表查询

    select 列名 from 左表,右表 where 条件
    select 列名 from 左表 inner join 右表 on 条件
    
  2. 能够使用左外连接和右外连接进行多表查询

    select 列名 from 左表 left join 右表 on 条件
    
    select 列名 from 左表 right join 右表 on 条件
    
  3. 能够使用子查询进行多表查询

    1. 单行单列:父查询使用比较运算符
    2. 多行单列:父查询使用in
    3. 多行多列:将查询结果做成一张虚拟表,再次查询
  4. 能够理解多表查询的规律

    1563360456604

第三部分(事务)

1、事务的概念

目标

能够理解事务的概念

讲解

事务的应用场景说明

关于事务在实际中的应用场景:

假设我在淘宝买了一部手机,然后当我付完款,钱已经从我的账户中扣除。正当此时,淘宝转账系统宕机了,那么此时淘宝还没有收到钱,而我的账户的钱已经减少了,这样就会导致我作为买家钱已经付过,而卖家还没有收到钱,他们不会发货物给我。这样做显然是不合理。实际生活中是如果淘宝出问题,作为用户的账户中钱是不应该减少的。这样用户就不会损失钱。

还有种情况,就是当我付完款之后,卖家看到我付款成功,然后直接发货了,我如果有权限操作,我可以撤销,这样就会导致我的钱没有减少,但是卖家已经发货,同样这种问题在实际生活中也是不允许出现的。

关于上述两种情况,使用数据库中的事务可以解决。具体解决方案如下图所示:

说明:在数据库中查询不会涉及到使用事务,都是增删改。

什么是事务

​ 在实际的业务开发中,有些业务操作要多次访问数据库。一个业务要发送多条SQL语句给数据库执行。需要将多次访问数据库的操作视为一个整体来执行,要么所有的SQL语句全部执行成功。如果其中有一条SQL语句失败,就进行事务的回滚,所有的SQL语句全部执行失败。

简而言之,事务指的是逻辑上的一组操作,组成这组操作的各个单元要么全都成功,要么全都失败。

事务作用:保证在一个事务中多次操作数据库表中数据时,要么全都成功,要么全都失败。

小结

什么是事务?多条SQL组合再一起完成某个功能.

2、手动提交事务

目标

能够使用手动的方式提交事务

讲解

MYSQL中可以有两种方式进行事务的操作:

  1. 手动提交事务:先开启,再提交
  2. 自动提交事务(默认的):即执行一条sql语句提交一次事务。

事务有关的SQL语句:

SQL语句 描述
start transaction; 开启手动控制事务
commit; 提交事务
rollback; 回滚事务

手动提交事务使用步骤

​ 第1种情况:开启事务 -> 执行SQL语句 -> 成功 -> 提交事务
​ 第2种情况:开启事务 -> 执行SQL语句 -> 失败 -> 回滚事务

准备数据:

# 创建一个表:账户表.
create database day04_db; 
# 使用数据库
use day04_db;
# 创建账号表
create table account(
	id int primary key auto_increment,
	name varchar(20),
	money double
);
# 初始化数据
insert into account values (null,'a',1000);
insert into account values (null,'b',1000);

案例演示1:需求:演示提交事务,a给b转账100元。


案例演示2:演示回滚事务,a给b转账100元。(失败)

注意:

事务是如何处理正常情况的呢?

a=1000 b=1000

开启事务(start transaction;)

update account set money = money -100 where name='a';

update account set money = money +100 where name='b';

提交事务(commit;) (事务提交之后,sql语句对数据库产生的操作才会被永久的保存)

事务是如何处理异常情况的呢?

a=1000 b=1000

开启事务(start transaction;)

update t_account set money = money -100 where name='a'; a=900

出现异常

update t_account set money = money +100 where name='b';

事务的回滚(rollback;)(撤销已经成功执行的sql语句,回到开启事务之前的状态)

a=1000 b=1000;

注意:只要提交事务,那么数据就会长久保存了,就不能回滚事务了。即提交或者回滚事务都是代表结束当前事务的操作。

小结

  1. 如何开启事务: start transaction;
  2. 如何提交事务: commit; 永久性改变
  3. 如何回滚事务: rollback; 回到开启事务最初的状态

3、自动提交事务

目标

了解自动提交事务

能够关闭自动提交事务

讲解

​ MySQL的每一条DML(增删改)语句都是一个单独的事务,每条语句都会自动开启一个事务,执行完毕自动提交事务,MySQL默认开始自动提交事务。自动提交,通过修改mysql全局变量“autocommit”进行控制。

1.通过以下命令可以查看当前autocommit模式:

show variables like '%commit%';

2.设置自动提交的参数为OFF:

set autocommit = 0;  -- 0:OFF  1:ON

小结

1)MySql默认自动提交。即执行一条sql语句提交一次事务。

2)设置autocommit为off状态,只是临时性的,下次重新连接mysql,autocommit依然变为on状态。

3)如果设置autocommit为off状态,那么当我们执行一条sql语句,就不会自动提交事务,重新启动可视化工具,数据并没有改变。

4)如果设置autocommit为on状态,如果我们先执行 start transaction; 然后在执行修改数据库的语句:

update account set money = money-100 where name='a';

update account set money = money+100 where name='b';

那么此时就表示上述修改数据库的sql语句都在同一个事务中,此时必须手动提交事务,即commit;

换句话说,如果我们手动开启事务 start transaction; 那么此时mysql就不会自动提交事务,必须手动提交事务。

5)如果设置autocommit为on状态,如果我们不执行 start transaction; 直接执行修改数据库的语句:

update account set money = money-100 where name='a';

update account set money = money+100 where name='b';

那么此时mysql就会自动提交事务。即上述每条sql语句就是一个事务。

课堂代码演示:

-- 自动提交事务:每条sql语句就是一个事务,那么执行一条sql语句就会提交一次事务
-- mysql数据库就是自动提交事务
-- a给b转账100元
update account set money=money-100 where name='a';
update account set money=money+100 where name='b';

-- 查看mysql是否自动提交事务
-- autocommit的值是on表示自动提交事务,值是off表示关闭自动提交事务
show variables like '%commit%';
-- 我们可以使用命令临时设置mysql变为手动提交事务,即将自动提交事务关闭
-- 下次重新连接mysql依然是自动提交事务
set autocommit = 0; -- 0 表示关闭自动提交事务 1表示开启自动事务
update account set money=money-100 where name='a'

4、原理

1562228567293

原理说明

  1. 一个用户登录成功以后,服务器会创建一个临时日志文件。日志文件用来保存用户事务状态。
  2. 如果没有使用事务,则所有的操作直接写到数据库中,不会使用日志文件。
  3. 如果开启事务,将所有的写操作写到日志文件中。
  4. 如果这时用户提交了事务,则将日志文件中所有的操作写到数据库中。
  5. 如果用户回滚事务,则日志文件会被清空,不会影响到数据库的操作。

事务操作小结

说出事务原理?
开启事务后,SQL语句会放在临时的日志文件中,如果提交事务,将日志文件中SQL的结果放在数据库中

如果回滚事务清空日志文件.

事务的操作 MySQL操作事务的语句
手动开启事务 start transaction
手动提交事务 commit
手动回滚事务 rollback
查询事务的自动提交情况 show variables like '%commit%';
设置事务的手动提交方式 set autocommit = 0 -- 关闭自动提交

5、事务的四大特性(ACID)(面试)

目标

了解事务的四大特性

讲解

数据库的事务必须具备ACID特性,ACID是指 Atomicity(原子性)、Consistensy(一致性)、Isolation(隔离性)和Durability(持久性)的英文缩写。

1、隔离性(Isolation)

多个用户并发的访问数据库时,一个用户的事务不能被其他用户的事务干扰,多个并发的事务之间要相互隔离。

一个事务的成功或者失败对于其他的事务是没有影响。2个事务应该相互独立。

举例:

a 给b转账 -----》叫做事务A

c 给d 转账 -----》叫做事务B

事务A和事务B之间不会相互影响。

2、持久性(Durability)

指一个事务一旦被提交,它对数据库的改变将是永久性的,哪怕数据库发生异常,重启之后数据亦然存在。

举例:

a=1000、b=1000转账

开启事务

a-100

b+100

提交

结果: a 900 b 1100

即使事务提交以后再发生异常,a和b的数据依然不会变。a就是900 b就是1100。

3、原子性(Atomicity)

原子性是指事务包装的一组sql(一组业务逻辑)是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

4、一致性(Consistency)

一个事务在执行之前和执行之后 数据库都必须处于一致性状态。

如果事务成功的完成,那么数据库的所有变化将生效。

如果事务执行出现错误,那么数据库的所有变化将会被回滚(撤销),返回到原始状态。

事务的成功与失败,最终数据库的数据都是符合实际生活的业务逻辑。一致性绝大多数依赖业务逻辑和原子性。

举例1: a=1000、b=1000 转账 100

a - 100

b + 100

结果: a + b = 2000

如果a转账失败了,那么b也得失败。不能因为a失败了,a依然是1000.但是b却成功了,b却变成了1100.那么结果是2100了,这样是不符合事务的一致性的。

小结

事务四个特性?
原子性
一致性
隔离性
持久性

事务特性 含义
一致性(Consistency) 事务前后数据的完整性必须保持一致
原子性(Atomicity) 事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
隔离性(Isolation) 是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离,不能相互影响。
持久性(Durability) 指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

6、事务的并发访问引发的三个问题(面试)

目标

能够理解并发访问的三个问题

讲解

事务在操作时的理想状态:多个事务之间互不影响,如果隔离级别设置不当就可能引发并发访问问题。

并发访问的问题 含义
脏读 一个事务读取到了另一个事务中尚未提交的数据。最严重,杜绝发生。
不可重复读 一个事务中两次读取的数据内容不一致,要求的是一个事务中多次读取时数据是不一致的,这是事务update时引发的问题
幻读(虚读) 一个事务内读取到了别的事务插入或者删除的数据,导致前后读取记录行数不同。这是insert或delete时引发的问题

1.脏读:指一个事务读取了另外一个事务未提交的数据。(非常危险)

​ 脏读具体解释如下图所示:注意脏读的前提是没有事务的隔离性。

说明:事务a首先执行转账操作,然后事务a还没有提交数据的情况下,事务b读取了数据库的数据。紧接着事务a执行回滚操作,导致事务b读取的结果和数据库的实际数据是不一样的。

一个事务读取了另一个事务未提交的数据叫做脏读。

举例:

a 转账 给b 100,未提交

b 查询账户多了100

a 回滚

b 查询账户那100不见了。

一个事务读取了另一个事务没有提交的数据,非常严重,必须避免脏读。

2.不可重复读:在一个事务内多次读取表中的数据,多次读取的结果不同。

说明:事务b首先读取数据库的数据,然后事务a对数据修改并提交。之后事务b对数据库再次进行读取。这时发现在事务b中2次读取的结果不一致。

一个事务内读取了另一个事务提交的数据。这个叫做不可重复读。

不可重复读和脏读的区别:

脏读:强调的是读取了未提交的数据。

不可重复读:一个事务内2次读取,其中一次读取了另一个事务提交了的数据。

例如: 银行想查询A账户的余额,第一次查询的结果是200元,A向账户中又存了100元。此时,银行再次查询的结果变成了300元。两次查询的结果不一致,银行就会很困惑,以哪次为准。

和脏读不同的是:脏读读取的是前一事务未提交的数据,不可重复度 读取的是前一事务已提交的事务。

很多人认为这有啥好困惑的,肯定是以后面的结果为准了。我们需要考虑这样一种情况,查询A账户的余额,一个打印到控制台,一个输出到硬盘上,同一个事务中只是顺序不同,两次查询结果不一致,到底以哪个为准,你会不会困惑呢?

当前事务查询A账户的余额为100元,另外一个事务更新余额为300元并提交,导致当前事务使用同一查询结果却变成了300元。

3.幻读(虚读):一个事务内读取到了别的事务插入或者删除的数据,导致前后读取记录行数不同

说明:事务b首先读取数据的数量,然后事务a添加了一条数据,并且提交了。接着事务b再次读取了数据的数量。2次读取不一致。

同一个事务内,2次读取的数据的数量不一致,叫做幻读或者虚读。

虚读(幻读)和不可重复读的区别:

不可重复读:强调的是数据内容的不一致。另一个事务是update操作。

虚读(幻读):强调的数据的数量(记录数)的不一致。另一个事务是insert或者delete操作。

注意:

指在一个事务中 读取 另一个事务 插入或删除 数据记录,导致当前事务读取数据的记录数前后不一致。

一个事务读取另一个事务已经提交的数据,强调的是记录数的变化,常用sql类型为 insert和 delete。

小结

  1. 能够理解并发访问的三个问题
    赃读:一个事务读取另一个事务还没有提交的数据,一定避免。
    不可重复读:一个事务读取多次数据内容不一样,主要是update语句。事务已经提交了。 可以发生的。
    幻读:一个事务读取多次数量不一样,主要是delete或者insert语句。事务已经提交了。可以发生的。

7、事务的隔离级别

目标

能够说出mysql的四种隔离级别

讲解

1、通过以上问题演示,我们发现如果不考虑事务的隔离性,会遇到脏读、不可重复读和虚读等问题。所以在数据库中我们要对上述三种问题进行解决。MySQL数据库规范规定了4种隔离级别,分别用于描述两个事务并发的所有情况。

上面的级别最低,下面的级别最高。“是”表示会出现这种问题,“否”表示不会出现这种问题。

级别 名字 隔离级别 脏读 不可重复读 幻读 数据库默认隔离级别
1 读未提交 read uncommitted
2 读已提交 read committed Oracle和SQL Server
3 可重复读 repeatable read MySQL
4 串行化 serializable

2、安全和性能对比

安全性:serializable > repeatable read > read committed > read uncommitted

性能 : serializable < repeatable read < read committed < read uncommitted

3、注意:其实三个问题,开发中最严重的问题就是脏读,这个问题一定要避免,而关于不可重复读和虚读其实只是感官上的错误,并不是逻辑上的错误。就是数据的时效性,所以这种问题并不属于很严重的错误。如果对于数据的时效性要求不是很高的情况下,我们是可以接受不可重复读和虚读的情况发生的。

小结

能够说出mysql的四种隔离级别
读未提交:read uncommitted
读已提交:read committed 可以避免脏读
可重复读:repeatable read mysql默认的,可以避免脏读 和不可重复读
串行化:serializable

8、脏读的演示(课下不用演示)

目标

  1. 能够设置mysql的隔离级别
  2. 能够解决赃读

讲解

查询和设置隔离级别

  1. 查询全局事务隔离级别

    show variables like '%isolation%';
    -- 或
    select @@tx_isolation;
    

  2. 设置事务隔离级别,需要退出MSQL再进入MYSQL才能看到隔离级别的变化

    set global transaction isolation level 隔离级别;
    -- 如:
    set global transaction isolation level read uncommitted;
    set global transaction isolation level repeatable read;
    

3.注意,mysql5.6后如果将隔离级别设置uncommitted,那么修改数据会报错,

image-20210717105819743

所以我们在演示的时候,针对当前会话设置如下:

# 设置session级别的BINLOG  
SET SESSION binlog_format = 'MIXED' ;

上述命令只是当前会话有效,重新连接失效,通过如下命令可以查看:

#查看binlog方式      
select @@binlog_format;

脏读的演示

脏读:一个事务读取到了另一个事务中尚未提交的数据。

  1. 打开一个窗口,设置为A窗口,登录MySQL,设置全局的隔离级别为最低

    -- 设置窗口名字A
    title A
    -- 登录mysql数据库
    mysql -u root -p
    1234
    -- 设置事务隔离级别
    set global transaction isolation level read uncommitted;
    

注意:设置事务隔离级别,需要重新打开一个窗口才能看到隔离级别的变化.

2.重新打开一个新的窗口,设置为B窗口,登录mysql

-- 设置窗口名字B
title B;
-- 登录mysql数据库
mysql -u root -p
1234
-- 查询隔离级别
select @@tx_isolation;

3.AB窗口都开启事务

use day05_db;
start transaction;

4.A窗口更新2个人的账户数据,未提交

update account set money=money-500 where id=1;
update account set money=money+500 where id=2;

5.B窗口查询账户

select * from account;

6.A窗口回滚

rollback;

7.B窗口查询账户,钱没了

脏读非常危险的,比如张三向李四购买商品,张三开启事务,向李四账号转入500块,然后打电话给李四说钱已经转了。李四一查询钱到账了,发货给张三。张三收到货后回滚事务,李四的再查看钱没了。

解决脏读的问题:将全局的隔离级别进行提升

  1. 在A窗口设置全局的隔离级别为read committed

    set global transaction isolation level read committed;
    

  2. B窗口退出MySQL,B窗口再进入MySQL

  3. AB窗口同时开启事务

  4. A更新2个人的账户,未提交

    update account set money=money-500 where id=1;
    update account set money=money+500 where id=2;
    

  5. B窗口查询账户

  6. A窗口commit提交事务

  7. B窗口查看账户

结论:read committed的方式可以避免脏读的发生

小结

  1. 查询全局事务隔离级别?
    show variables like '%isolation%';
    select @@tx_isolation;

  2. 设置全局事务隔离级别?
    set global transaction isolation level 隔离级别字符串;

    set global transaction isolation level repeatable read;
    
  3. 如何解决赃读?
    将隔离级别设置为:read committed

标签:insert,事务,--,Day02,查询,语法,values,MYSQL,id
From: https://www.cnblogs.com/-turing/p/17181165.html

相关文章

  • Day03.mysql高级_函数和索引
    day03-mysql高级学习网站:索引高级:https://www.bilibili.com/video/BV1MS4y1T7uJ?from=search&seid=5032261320934971179&spm_id_from=333.337.0.0hashmap:https://www.......
  • Day01.MYSQL基础语法
    1.web阶段学习方法和特点1.特点:se注重原理,web阶段注重应用,框架ssm注重思想2.数据库:sql语句是独立的。inta=10;intb=20;intc=a+b;3.课堂为主,作业为辅web开始:断奶教......
  • MySQL中三级模式和二级映像指的是什么?
    MySQL中三级模式和二级映像指的是什么?更新时间:2022-06-09来源:黑马程序员浏览量:2354美国国家标准学会(AmericanNationalStandardsInstitute,ANSI)所属的标准计划......
  • MySQL Workbench 8.0 点击Server Status面板Could not acquire management access for
    转载自:MySQLWorkbench8.0点击ServerStatus面板Couldnotacquiremanagementaccessforadministration报错问题解决Win10安装MySQLWorkbench8.0后连接MySQL服务......
  • python操作mysql
    1、mysql查询操作:#!/usr/bin/python#-*-coding:UTF-8-*-importMySQLdb#打开数据库连接db=MySQLdb.connect("localhost","root","111111","analysis2")#使用cursor......
  • mysql主从数据库状态检测(php)
    实例:<?php/***检测多个主从数据库是否挂掉*建立从数据库$slave_db的二维数组,内容包含每个从服务器的配置数据*/header("Content-Type:text/html;charset=utf-8");set......
  • MySQL数据库备份恢复
    拓扑图:推荐步骤:使用MySQLdump对数据库数据库中表一个数据库多个表所有数据库进行备份模拟数据丢失恢复备份的数据 配置MySQL数据库开启二进制日志功能配置二进制日志切割......
  • MySQL基本命令操作
    目录创建数据库删除数据库数据表的创建与管理删除数据表修改字段数据类型添加字段字段更名删除字段表数据管理插入数据查询数据模糊匹配排序与分组HAVING子句查询聚合函数......
  • php基本语法和数据类型、变量销毁
    1、PHP基本语法:HTML和php混合使用;一个语句以;(分号)结束;如何定义一个变量,和变量的使用;php中定义一个变量要以$符号开头:$a=34;变量的数据类型不是固定不变的,根据赋值的变化而......
  • php 检测mysql表是否存在
    pdo:<?php$dsn='mysql:dbname=test;host=127.0.0.1';$user='root';$password='';try{$pdo=newPDO($dsn,$user,$password);}catch(PDOException$e){......