数据库基础

文章目录

  • 一:安装Mysql 和 DataGrip的基本配置
    • 1.1:mysql
    • 1.2:DataGrip连接mysql
  • 二:DataGrip的基本使用
    • 2.1:显示所有数据库
    • 2.2:创建数据库
    • 2.3:创建表
    • 2.4:修改表结构
    • 2.5:在DataGrip中执行SQL语句
  • 三:数据库基本操作
    • 3.1:查看、创建、增、删、改
    • 3.2:查
    • 3.3:常用比较运算符
    • 3.4:常用逻辑运算符
    • 3.5:聚合函数
    • 3.6:分组查询
    • 3.7:执行顺序
  • 四:DCL
  • 五:约束条件
    • 5.1:概述
    • 5.2:约束演示
    • 5.3:外键约束
      • 5.3.1:介绍
      • 5.3.2:语法
      • 5.3.3:删除/更新行为
  • 六:多表查询
    • 6.1:多表关系
      • 6.1.1:一对多
      • 6.1.2:多对多
      • 6.1.3:一对一
    • 6.2:多表查询概述
      • 6.2.1:数据准备
      • 6.2.2:概述
      • 6.2.3:查询的分类
    • 6.3:内连接
    • 6.4:外连接
    • 6.5:自连接
      • 6.5.1:自连接查询
      • 6.5.2:联合查询
    • 6.6:子查询
      • 6.6.1:概述
      • 6.6.2:标量子查询
      • 6.6.3:列子查询
      • 6.6.4:行子查询
      • 6.6.5:表子查询
    • 6.7:多表查询

一:安装Mysql 和 DataGrip的基本配置

1.1:mysql

mysql 是一种数据库,DataGrip是一款数据库管理客户端工具,方便连接到数据库服务器,执行sql、创建表、创建索引等等一大堆功能。

MySQL和DataGrip 均可以去官网下载,但是后者只有30天试用期。
我这里给出了三个文件,可以一并下载了。

https://www.aliyundrive.com/s/JwHQLjq3PR7
提取码: ot16

安装mysql(建议直接默认安装路径) 和datagrip(无脑下一步,什么打勾的都不需要) 网上有很多的安装攻略,这就省略了。mysql要设置好环境变量。

安装完成之后通过如下指令进入mysql

mysql -uroot -p

数据库基础_第1张图片

 

1.2:DataGrip连接mysql

如下图:

数据库基础_第2张图片

配置以及驱动jar包下载完毕之后,就可以点击 “Test Connection” 就可以测试,是否可以连接MySQL,如果出现 “Successed”,就代表连接成功了。

数据库基础_第3张图片

 

二:DataGrip的基本使用

2.1:显示所有数据库

连接上了mysql服务之后,需要设置展示所有数据库。

数据库基础_第4张图片

 

2.2:创建数据库

数据库基础_第5张图片

注意:

以下两种方式都可以创建数据库
create database db01;
create schema db01;

 

2.3:创建表

在指定的数据库上面右键,选择new --> Table

数据库基础_第6张图片

数据库基础_第7张图片

 

2.4:修改表结构

在需要修改的表上,右键选择 “Modify Table…”

数据库基础_第8张图片

数据库基础_第9张图片

如果想增加字段,直接点击+号,录入字段信息,然后点击Execute即可。
如果想删除字段,直接点击-号,就可以删除字段,然后点击Execute即可。
如果想修改字段,双击对应的字段,修改字段信息,然后点击Execute即可。
如果要修改表名,或表的注释,直接在输入框修改,然后点击Execute即可。

 

2.5:在DataGrip中执行SQL语句

在指定的数据库上,右键,选择 New --> Query Console

数据库基础_第10张图片

然后就可以在打开的 Query Console控制台上编写SQL,并执行。

数据库基础_第11张图片

 

 

三:数据库基本操作

3.1:查看、创建、增、删、改

# 查看数据库
show databases;

# 创建数据库
create database test default charset utf8mb4;

# 删除数据库
drop database if exists test;
create database test default charset utf8mb4;

# 切换数据库
use test;

# 查看正在使用的数据库
select database();

# 查看当前数据库所有的表
show tables;

# 创建一个表
create table user_info(
    id int primary key auto_increment comment 'number',
    name varchar(50) comment 'name',
    age int comment 'age',
    gender varchar(1) comment 'sex'
) comment '用户信息表';

# 查看表的结构
desc user_info;

# 查看具体的表的内容
select * from user_info;



-- 给表增添字段(表的属性字段,都是用alter关键字)
# 给表添加字段
alter table user_info add school varchar(20);
# 指定位置插入字段并设置默认值
alter table user_info add age2 int default 18 after age;

# 给表修改字段
alter table user_info change school school2 varchar(30);

# 删除表的字段
alter table user_info drop school2;
alter table user_info drop age2;

# 更改表名
alter table user_info rename to user_info2;
alter table user_info2 rename to user_info;


-- 具体数据
# 增
insert into user_info (id, name, age, gender) values (1, 'xxx', 22, '男');
insert into user_info (id, name, age, gender) values (2, 'aaa', 18, '女');
insert into user_info (id, name, age, gender) values (3, 'bbb', 19, '女');
insert into user_info (id, name, age, gender) values (4, 'ccc', 20, '女');
insert into user_info (id, name, age, gender) values (5, 'ddd', 20, '女');

# 改
update user_info set name='yyy' where name='xxx';

# 查
select * from user_info;

# 删
delete from user_info where name='yyy';


-- 基础查询
# 查询所有
select * from user_info;

# 别名(as可省略)
select name as na from user_info;
select age '年龄' from user_info;

# 去重
select distinct age  as '年龄' from user_info;

# 模糊匹配like,%代表匹配任意字符
select * from user_info where age like '2%';

# 计数
select count(*) from user_info;

# 最大值
select max(age) from user_info;

# 分组计数
select gender, count(*) from user_info group by gender;

# 排序(默认升序asc,desc为降序)
select * from user_info order by age desc, id desc;

# 分页
select * from user_info limit 0, 3;

 

3.2:查

语法:

select 字段列表 from 表名 where 条件列表;

 

3.3:常用比较运算符

>	大于
>=	大于等于
<	小于
<=	小于等于
=	等于
<>!=	不等于
BETWEEN ... AND ...	在某个范围之内(含最小、最大值)
IN(...)in之后的列表中的值,多选一
LIKE 占位符	模糊匹配(_匹配单个字符, %匹配任意个字符)
IS NULLNULL

 

3.4:常用逻辑运算符

AND&&	并且   (多个条件同时成立)
OR||	或者   (多个条件任意一个成立)
NOT!, 不是

 

3.5:聚合函数

count	统计数量
max		最大值
min		最小值
avg		平均值
sum		求和

语法:
select 聚合函数(字段列表) from 表名;
null值是不参与所有聚合函数运算的。
select count(*) from emp;		# 统计的是总记录数
select count(idcard) from emp;		# 统计的是idcard字段不为Null的记录

 

3.6:分组查询

根据性别分组,统计男性员工和女性员工的数量
select gender, count(*) from emp group by gender;

 

3.7:执行顺序

数据库基础_第12张图片

where与having区别

执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组;而having是分组 之后对结果进行过滤。
判断条件不同:where不能对聚合函数进行判断,而having可以。

 

 

四:DCL

DCL英文全称是Data Control Language(数据控制语言),用来管理数据库用户、控制数据库的访问权限。

--- 账号管控 ---
创建用户和密码
create user 'test'@'localhost' identified by 'password';
修改账户密码
alter user 'test'@'localhost' identified with mysql_native_password by 'password2';
删除账号
drop user 'test'@'localhost';
查询权限
show grants for 'test'@'localhost';
授予权限,all为所有权限,select查询数据权限,insert插入数据,update修改数据,delete删除数据,alter修改表,drop删除数据库//视图,create创建数据库/grant all on test.* to 'test'@'localhost';
撤销权限,
revoke all on test.* from 'test'@'localhost';
多个权限之间,使用逗号分隔,授权时,数据库名和表名可以使用*进行通配,代表所有

--- 字符串函数 ---
select concat('hello', 'mysql');			# 两个字符串拼接
select lower('HELLO');						# 转换为小写
selcet upper('hello');						# 转换为大写
select lpad('01', 5, '-');					# 左填充
select rpad('01', 5, '-');					# 右填充
select trim('   hello,  mysql   ');			# 去掉头部和尾部的空格
select substring('hello mysql', 1, 7);		# 返回字符串的从1开始的5个长度的字符串

--- 数值函数 ---
select ceil(3.1);	# 4	向上取整
select floor(3.1);	# 3	向下取整
select mod(9, 3);	# 0	余数
select rand();		# 0-1随机数
select round(3.141593, 3);		# 3.142		四舍五入保留三位小数

--- 日期函数 ---
select curdate()	# 当前日期
select curtime()	# 当前时间
select now()		# 返回当前日期和时间
select year(date)	# 获取指定date年份,~~ month,day
select date_add(now(), interval 70 year);		# 增加指定的时间间隔
select datediff('2021-10-01', '2021-12-01');	# 获取两个日期相差的天数

--- 流程函数 ---
if(value, t, f)				# value为true则返回t否则返回f
ifnull(value1, value2)		# value1不为空返回value1,否则返回value2
case when value1 then res1 when value2 then res2 else default end
select name, workaddress, (case when workaddress = '北京' then '一线城市' when workaddress = '上海' then '一线城市'
    else '二线城市' end) as '工作地址' from emp;

 
 

五:约束条件

5.1:概述

概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据。
目的:保证数据库中数据的正确性、有效性、完整性。

分类:

约束 描述 关键字
非空约束 限制该字段的数据不能为null NOT NULL
唯一约束 保证该字段的所有数据都是唯一、不重复的 UNIQUE
主键约束 主键是一行数据的唯一标识,要求非空且唯一 PRIMARY KEY
默认约束 保存数据时,,如果未指定该字段的值,则采用默认值 DEFAULT
检查约束(8.0.16版本之后) 保证字段值满足某一个条件 CHECK
外键约束 用来让两张表的数据之间建立连接,保证数据的一致性和完整性 FOREIGN KEY

注意:约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束。

 

5.2:约束演示

根据需求完成表结构的创建。
需求如下:

字段名 字段含义 字段类型 约束条件 约束关键字
id ID唯一标识 int 主键,并且自动增长 PRIMARY KEY, AUTO_INCREMENT
name 姓名 varchar(10) 不为空,并且唯一 NOT NULL, UNIQUE
age 年龄 int 大于0,并且小于等于120 CHECK
status 状态 char(1) 如果没有指定该值,默认为1 DEFAULT
gender 性别 char(1) / /

对应的建表语句为:

create table tb_user(
    id int auto_increment primary key comment 'ID唯一标识',
    name varchar(10) not null unique comment '姓名',
    age int check ( age>0 && age<= 120 ) comment '年龄',
    status char(1) default '1' comment '状态',
    gender char(1) comment '性别'
);

上面,我们是通过编写SQL语句的形式来完成约束的指定,那加入我们是通过图形化界面来创建表结构 时,又该如何来指定约束呢? 只需要在创建表的时候,根据我们的需要选择对应的约束即可。

数据库基础_第13张图片

 

5.3:外键约束

5.3.1:介绍

外键:用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性。

先来看个例子:
数据库基础_第14张图片

左侧的emp表是员工表,里面存储员工的基本信息,包含员工的ID、姓名、年龄、职位、薪资、入职日 期、上级主管ID、部门ID,在员工的信息中存储的是部门的ID dept_id,而这个部门的ID是关联的部门表dept的主键id,那emp表的dept_id就是外键,关联的是另一张表的主键。

准备数据:

drop table if exists dept;
create table dept(
    id int auto_increment comment 'ID' primary key,
    name varchar(50) not null comment '部门名称'
) comment '部门表';

insert into dept (id, name) values (1, '研发部'),
                                   (2, '市场部'),
                                   (3, '财务部'),
                                   (4, '销售部'),
                                   (5, '总经办');



drop table if exists emp;
create table emp(
    id int auto_increment comment 'ID' primary key,
    name varchar(50) not null comment '姓名',
    age int comment '年龄',
    job varchar(20) comment '职位',
    salary int comment '薪资',
    entrydate date comment '入职时间',
    managerid int comment '直属领导ID',
    dept_id int comment '部门ID'
) comment '员工表';

insert into emp (id, name, age, job, salary, entrydate, managerid, dept_id)
    values (1, '金庸', 66, '总裁', 20000, '2000-01-01', null, 5),
           (2, '张无忌', 20,'项目经理',12500, '2005-12-05', 1,1),
           (3, '杨逍', 33, '开发', 8400,'2000-11-03', 2,1),
           (4, '韦一笑', 48, '开发',11000, '2002-02-05', 2,1),
           (5, '常遇春', 43, '开发',10500, '2004-09-07', 3,1),
           (6, '小昭', 19, '程序员鼓励师',6600, '2004-10-12', 2,1);
           

运行指令:

select * from emp;
select * from dept;

得到下图;

数据库基础_第15张图片
数据库基础_第16张图片

接下来,我们可以做一个测试,删除id为1的部门信息。

数据库基础_第17张图片

结果,我们看到删除成功,而删除成功之后,部门表不存在id为1的部门,而在emp表中还有很多的员 工,关联的为id为1的部门,此时就出现了数据的不完整性。而要想解决这个问题就得通过数据库的外键约束。

 

5.3.2:语法

添加外键

可以在创建表的时候,添加外键,也可以在创建表之后添加外键约束。

create table 表名(
	字段名 数据类型,
	...
	constraint 外键名称 foreign key (外键字段名) references 主表(主表列名)
);


alter table 表名 add constraint 外键名称 foreign key (外键字段名) references 主表(主表列名);

案例:
为emp表的dept_id字段添加外键约束,关联dept表的主键id。

alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);

数据库基础_第18张图片

添加了外键约束之后,我们再到dept表(父表)删除id为1的记录,然后看一下会发生什么现象。 此时将会报错,不能删除或更新父表记录,因为存在外键约束。

删除外键

alter table 表名 drop foreign key 外键名称;

案例:
删除emp表的外键fk_emp_dept_id

alter table emp drop foreign key fk_emp_dept_id;

 

5.3.3:删除/更新行为

添加了外键之后,再删除父表数据时产生的约束行为,我们就称之为删除/更新行为。
具体有以下几种:

行为 说明
NO ACTION 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。(与RESTRICT 一致)默认行为
RESTRICT 当在父表中删除/更新对应记录时,首先检查记录是否有对应外键,如果有则不允许删除/更新。(与 NO ACTION 一致)默认行为
CASCADE 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有,则也删除/更新外键在子表中的记录。
SET NULL 当在父表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null(这就要求该外键允许取null)。
SET DEFAULT 父表有变更时,子表将外键列设置成一个默认的值 (Innodb不支持)

具体语法为:

ALTER TABLE 表名  ADD CONSTRAINT 外键名称  FOREIGN KEY (外键字段)	REFERENCES 主表名 (主表字段名)	ON UPDATE CASCADE ON DELETE CASCADE;

案例:
CASCADE

alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id) on update cascade on delete cascade ;

SET NULL

alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id) on update set null on delete set null ;

 
 

六:多表查询

上面也有DQL语句,也就是数据查询语句,但是之前的查询都是单表查询,而接下来的则是多表查询操作。

6.1:多表关系

项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结 构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种:

  • 一对多(多对一)
  • 多对多
  • 一对一

 

6.1.1:一对多

案例: 部门 与 员工的关系

关系: 一个部门对应多个员工,一个员工对应一个部门
实现: 在多的一方建立外键,指向一的一方的主键

数据库基础_第19张图片

 

6.1.2:多对多

案例: 学生 与 课程的关系

关系: 一个学生可以选修多门课程,一门课程也可以供多个学生选择
实现: 建立第三张中间表,中间表至少包含两个外键,分别关联两方主键

数据库基础_第20张图片

-- 多对多脚本
create table student(
    id int auto_increment primary key comment '主键ID',
    name varchar(10) comment '姓名',
    no varchar(10) comment '学号'
) comment '学生表';
insert into student values (null, '黛绮丝', '2000100101'),
                           (null, '谢逊', '2000100102'),
                           (null, '殷天正', '2000100103'),
                           (null, '韦一笑', '2000100104');

create table course(
    id int auto_increment primary key comment '主键ID',
    name varchar(10) comment '课程名称'
) comment '课程表';
insert into course values (null, 'java'),
                          (null, 'php'),
                          (null, 'mysql'),
                          (null, 'hadoop');

create table student_course(
    id int auto_increment primary key comment '主键',
    studentid int not null comment '学生ID',
    courseid int not null comment '课程ID',
    constraint fk_courseid foreign key (courseid) references course(id),
    constraint fk_studentid foreign key (studentid) references student(id)
) comment '学生课程中间表';
insert into student_course values (null, 1, 1),
                                  (null, 1, 2),
                                  (null, 1, 3),
                                  (null, 2, 1),
                                  (null, 2, 4);

select * from student_course;
select * from student;
select * from course;

 

6.1.3:一对一

案例: 用户 与 用户详情的关系

关系: 一对一关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率
实现: 在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE)

数据库基础_第21张图片

-- 一对多
drop table if exists tb_user;
create table tb_user(
    id int auto_increment primary key comment '主键ID',
    name varchar(10) comment '姓名',
    age int comment '年龄',
    gender char(1) comment '1:男, 2:女',
    phone char(11) comment '手机号'
) comment '用户基本信息表'

create table tb_user_edu(
    id int auto_increment primary key comment '主键ID',
    degree varchar(20) comment '学历',
    major varchar(50) comment '专业',
    primaryschool varchar(50) comment '小学',
    middleschool varchar(50) comment '中学',
    university varchar(50) comment '大学',
    userid int unique comment '用户ID',
    constraint fk_userid foreign key (userid) references tb_user(id)
) comment '用户教育信息表';

insert into tb_user(id, name, age, gender, phone) values (null, '黄渤', 45, '1', '18800001111'),
                                                         (null, '冰冰', 35, '2', '18800002222'),
                                                         (null, '马云', 55, '2', '18800008888'),
                                                         (null, '李彦宏', 50, '1', 18800009999);
insert into tb_user_edu(id, degree, major, primaryschool, middleschool, university, userid) values
    (null,'本科','舞蹈','静安区第一小学','静安区第一中学','北京舞蹈学院',1),
    (null,'硕士','表演','朝阳区第一小学','朝阳区第一中学','北京电影学院',2),
    (null,'本科','英语','杭州市第一小学','杭州市第一中学','杭州师范大学',3),
    (null,'本科','应用数学','阳泉第一小学','阳泉区第一中学','清华大学',4);
    

 

6.2:多表查询概述

6.2.1:数据准备

删除之前的emp,dept的测试数据,然后执行如下脚本,创建emp表和dept表并插入测试数据。

-- 创建dept表,并插入数据
drop table if exists dept;
create table dept(
	id int auto_increment comment 'ID' primary key,
	name varchar(50) not null comment '部门名称'
)comment '部门表';
INSERT INTO dept (id, name) VALUES
							(1, '研发部'),
							(2, '市场部'),
							(3, '财务部'),
							(4, '销售部'),
							(5, '总经办'),
							(6, '人事部');

-- 创建emp表,并插入数据
drop table if exists emp;
create table emp(
	id int auto_increment comment 'ID' primary key,
	name varchar(50) not null comment '姓名',
	age int comment '年龄',
	job varchar(20) comment '职位',
	salary int comment '薪资',
	entrydate date comment '入职时间',
	managerid int comment '直属领导ID',
	dept_id int comment '部门ID'
	)comment '员工表';

-- 添加外键
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);

-- 出入数据
INSERT INTO emp (id, name, age, job,salary, entrydate, managerid, dept_id) VALUES
                                                                (1, '金庸', 66, '总裁',20000, '2000-01-01', null,5),
                                                                (2, '张无忌', 20, '项目经理',12500, '2005-12-05', 1,1),
                                                                (3, '杨逍', 33, '开发', 8400,'2000-11-03', 2,1),
                                                                (4, '韦一笑', 48, '开发',11000, '2002-02-05', 2,1),
                                                                (5, '常遇春', 43, '开发',10500, '2004-09-07', 3,1),
                                                                (6, '小昭', 19, '程序员鼓励师',6600, '2004-10-12', 2,1),
                                                                (7, '灭绝', 60, '财务总监',8500, '2002-09-12', 1,3),
                                                                (8, '周芷若', 19, '会计',48000, '2006-06-02', 7,3),
                                                                (9, '丁敏君', 23, '出纳',5250, '2009-05-13', 7,3),
                                                                (10, '赵敏', 20, '市场部总监',12500, '2004-10-12', 1,2),
                                                                (11, '鹿杖客', 56, '职员',3750, '2006-10-03', 10,2),
                                                                (12, '鹤笔翁', 19, '职员',3750, '2007-05-09', 10,2),
                                                                (13, '方东白', 19, '职员',5500, '2009-02-12', 10,2),
                                                                (14, '张三丰', 88, '销售总监',14000, '2004-10-12', 1,4),
                                                                (15, '俞莲舟', 38, '销售',4600, '2004-10-12', 14,4),
                                                                (16, '宋远桥', 40, '销售',4600, '2004-10-12', 14,4),
                                                                (17, '陈友谅', 42, null,2000, '2011-10-12', 1,null);

 

6.2.2:概述

多表查询就是从多张表中查询数据。

原来查询单表数据,select * from emp;
那么我们要执行多表查询,就只需要使用逗号分隔多张表即可,如:select * from emp, dept;
执行结果如下:

数据库基础_第22张图片

此时,我们看到查询结果中包含了大量的结果集,总共102条记录,而这其实就是员工表emp所有的记录与部门表dept所有记录的所有组合情况,这种现象称之为笛卡尔积。

补充下:说下笛卡尔积是啥
数据库基础_第23张图片

而在多表查询中,我们是需要消除笛卡尔积的,只保留两张表关联部分的数据。

sql语句为:select * from emp, dept where emp.dept_id = dept.id;

数据库基础_第24张图片

而由于id为17的员工,没有dept_id字段值,所以在多表查询时,根据连接查询的条件并没有查询到。

 

6.2.3:查询的分类

  • 连接查询
    • 内连接:相当于A、B的交集部分
    • 外连接
    • 左外连接:查询左表所有数据,以及两张表交集部分数据
    • 右外连接:查询右表所有数据,以及两张表交集部分数据
    • 自连接:当前表与自身的连接查询,自连接必须使用表别名
  • 子查询

 

6.3:内连接

内连接的语法分为两种:

  • 隐式内连接 select 字段列表 from 表1, 表2 where 条件 ...;
  • 显示内连接 select 字段列表 from 表1 [inner] join 表2 on 连接条件 ...;

案例:
1、查询每一个员工的姓名,及关联的部门的名称(隐式内连接实现)
表结构:emp, dept
连接条件:emp.dept_id = dept.id

select emp.name, dept.name from emp, dept where emp.dept_id = dept.id;

# 为每一张表起别名,简化sql编写
select e.name,d.name from emp e , dept d where e.dept_id = d.id;

数据库基础_第25张图片

2、查询每一个员工的姓名,及关联的部门的名称(显示内连接实现)
表结构:emp, dept
连接条件:emp.dept_id = dept.id

select emp.name, dept.name from emp inner join dept on emp.dept_id = dept.id;

# 起别名,as可以省略
select e.name, d.name from emp as e inner join dept as d on e.dept_id = d.id;

数据库基础_第26张图片

注意:一旦为表起了别名,就不能再使用表名来指定对应的字段了,此时只能够使用别名来指定字段。

 

6.4:外连接

外连接分为两种,分别是:左外连接,右外连接

语法结构:

select 字段列表 from1 left [outer] join2 on 条件 ...;
select 字段列表 from1 right [outer] join2 on 条件 ...;

案例:
1、查询emp表的所有数据,和对应的部门信息
由于需求中提到要查询emp的所有数据,所以是不能内连接查询的,需要考虑使用外连接查询。

表结构:emp, dept
连接条件:emp.dept_id = dept.id

select e.*, d.name from emp e left outer join dept d on e.dept_id = d.id;
select e.*, d.name from emp e left join dept d on e.dept_id = d.id;

数据库基础_第27张图片
 

2、查询dept表的所有数据,和对应的员工信息(右外连接)

select d.*, e.* from emp e right outer join test.dept d on d.id = e.dept_id;

数据库基础_第28张图片

注意事项:
左外连接和右外连接是可以相互替换的,只需要调整在连接查询时SQL中,表结构的先后顺 序就可以了。而我们在日常开发使用时,更偏向于左外连接

 

6.5:自连接

6.5.1:自连接查询

自连接查询,顾名思义,就是自己连接自己,也就是把一张表连接查询多次。
语法:

select 字段列表 from 表A 别名A join 表A 别名B on 条件 ...;

而对于自连接查询,可以是内连接查询,也可以是外连接查询。

案例:
1、查询员工及其所属领导的名字
表结构:emp

select a.name, b.name from emp a, emp b where a.managerid = b.id;

2、查询所有员工emp及其领导的名字emp,如果员工没有领导,也需要查询出来
表结构:emp a, emp b

select a.name '员工', b.name '领导' from emp a left join emp b on a.managerid = b.id;

注意事项:在自连接查询中,必须要为表起别名,要不然我们不清楚所指定的条件,返回的字段到底是哪一张表的字段。

 

6.5.2:联合查询

对于union查询,就是把多次查询的结果合并起来,形成一个新的查询结果集。

语法结构:

select 字段列表 from 表A ...
union [all]
select 字段列表 from 表B ...;

前提条件:

  • 对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致。
  • union all 会将全部的数据直接合并在一起,union 会对合并之后的数据去重。

案例:
1、将薪资低于5000的员工和年龄大于50岁的员工全部查询出来。
当前对于这个需求,我们可以直接使用多条件查询,使用逻辑运算符or连接即可。这里也可以通过union/union all来联合查询。

select * from emp where salary < 5000 or age > 50;
select * from emp where salary < 5000 union select * from emp where age > 50;
select * from emp where salary < 5000 union all select * from emp where age > 50;

数据库基础_第29张图片

当我们使用union all的时候,查询出来的结果,仅仅是进行简单的合并,并没有去重。而使用union 查询出来的结果会对查询出来的结果进行去重处理。

注意:
如果多条查询语句查询出来的结果,字段数量不一致,在进行union/union all联合查询时,将会出错。如:

数据库基础_第30张图片

 

6.6:子查询

6.6.1:概述

概念:
sql语句中嵌套select语句,称为嵌套查询,又称为子查询。

select * from t1 where column1 = (select column1 from t2);

子查询外部的语句可以是insert/update/delete/select的任何一个。

 
分类:

根据子查询结果不同,分为:

  • 标量子查询(子查询结果为单个值)
  • 列子查询(子查询结果为一列)
  • 行子查询(子查询结果为一行)
  • 表子查询(子查询结果为多行多列)

根据子查询位置,分为:

  • where之后
  • from之后
  • select之后

 

6.6.2:标量子查询

子查询返回的结果是单个值(数字,字符串,日期等),最简单的形式,这种子查询称为标量子查询。
常用的操作符:= , <> , > , >= , < , <=

案例:
1、查询销售部的所有员工信息。
完成这个需求的时候,我们可以分为两步:
查询销售部部门

select id from dept where name = '销售部';

根据销售部部门ID,查询员工信息。

select * from emp where dept_id = (select id from dept where name = '销售部');

2、查询在”方东白“入职之后的员工信息。
完成这个需求时,我们可以将需求分解为两步:
查询方东白的入职时间

select entrydate from emp where name = '方东白';

查询指定入职日期之后入职的员工信息

select * from emp where entrydate > (select entrydate from emp where name='方东白';)

 

6.6.3:列子查询

子查询返回的结果是一列(可以是多列),这种子查询成为列子查询
常用操作符:IN, NOT IN, ANY, SOME, ALL

操作符 描述
IN 在指定的集合范围之内,多选一
NOT IN 不在指定的集合范围之内
ANY 子查询返回列表中,有任意一个满足即可
SOME 与ANY等同,使用SOME的地方都可以使用ANY
ALL 子查询返回列表的所有值都必须满足

案例:
1、查询销售部和市场部的所有员工信息,可分为以下两步:
查询销售部和市场部的部门ID

select id from dept where name = '销售部' or name = '市场部';

根据部门ID,查询员工信息

select * from emp where dept_id in (select id from dept where name = '销售部' or name = '市场部');

2、查询比财务部所有人工资都高的员工信息
查询所有财务部人员工资

select id from dept where name = '财务部';
select salary from emp where dept_id = (select id from dept where name = '财务部');

比财务部所有人工资都要高的员工信息

select * from emp where salary > all (select salary from emp where dept_id = (select id from dept where name = '财务部'));

 

6.6.4:行子查询

子查询返回的结果是一行(可以是多行),这种子查询称为行子查询。
常用操作符:=, <>, IN, NOT IN

案例:
1、查询与张无忌的薪资及直属领导相同的员工信息。
查询张无忌的薪资及直属领导

select salary, managerid from emp where name = '张无忌';

查询与张无忌的薪资及直属领导相同的员工信息

select * from emp where (salary, managerid) = (select salary, managerid from emp where name = '张无忌');

 

6.6.5:表子查询

子查询返回的结果是多行多列,这种子查询称为表子查询。
常用操作符:IN

案例:
1、查询与鹿杖客,宋远桥的职位和薪资相同的员工信息
查询鹿杖客,宋远桥的职位和薪资

select job, salary from emp where name = '鹿杖客' or name = '宋远桥';

查询与鹿杖客,宋远桥的职位和薪资相同的员工信息

select * from emp where (job, salary) in (select job, salary from emp where name = '鹿杖客' or name = '宋远桥');

2、查询入职日期是"2006-01-01"之后的员工信息,及其部门信息
分解为两步执行:
入职日期是"2006-01-01"之后的员工信息

select * from emp where entrydate > '2006-01-01';

查询这部分员工,对应的部门信息

select e.*, d.* from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.dept_id = d.id;

 

6.7:多表查询

数据环境准备

create table salgrade(
    grade int,
    losal int,
    hisal int
) comment '薪资等级表';
insert into salgrade values (1,0,3000);
insert into salgrade values (2,3001,5000);
insert into salgrade values (3,5001,8000);
insert into salgrade values (4,8001,10000);
insert into salgrade values (5,10001,15000);
insert into salgrade values (6,15001,20000);
insert into salgrade values (7,20001,25000);
insert into salgrade values (8,25001,30000);

在这个案例中,我们主要运用上面所讲解的多表查询的语法,完成以下的12个需求即可,而这里主要涉及到的表就三张:emp员工表,dept部门表,salgrade薪资等级表。

1)查询员工的姓名,年龄,职位,部门信息(隐式内连接)

select e.name, e.age, e.job, d.name from emp e, dept d where e.dept_id = d.id;

2)查询年龄小于30岁的员工的姓名,年龄,职位,部门信息(显式内连接)

select e.name, e.age, e.job, d.name from emp e inner join dept d on e.dept_id = d.id where e.age < 30;

3)查询所有员工的部门ID,部门名称

select distinct d.id, d.name from emp e, dept d where e.dept_id = d.id;

4)查询所有年龄大于40岁的员工,及其归属的部门名称,如果员工没有分配部门,也需要展示出来(外连接)

select e.*, d.name from emp e left join dept d on e.dept_id = d.id where e.age > 40;

5)查询所有员工的工资等级
连接条件:emp.salary >= salgrade.losal and emp.salary <= salgrade.hisal

方式一:
select e.* , s.grade , s.losal, s.hisal from emp e , salgrade s where e.salary >= s.losal and e.salary <= s.hisal;

方式二:
select e.* , s.grade , s.losal, s.hisal from emp e , salgrade s where e.salary between s.losal and s.hisal;

6)查询 “研发部” 所有员工的信息及 工资等

select e.* , s.grade from emp e , dept d , salgrade s where e.dept_id = d.id and (
    e.salary between s.losal and s.hisal ) and d.name = '研发部';

7)查询 “研发部” 员工的平均工资

select avg(e.salary) from emp e, dept d where e.dept_id = d.id and d.name = '研发部';

8)查询工资比”灭绝“高的员工信息

select * from emp where salary > ( select salary from emp where name = '灭绝' );

9)查询比平均薪资高的员工信息

select * from emp where salary > ( select avg(salary) from emp );

10)查询低于本部门平均工资的员工信息
①:查询指定部门平均薪资

select avg(e1.salary) from emp e1 where e1.dept_id = 1;
select avg(e1.salary) from emp e1 where e1.dept_id = 2;

②:查询低于本部门平均工资的员工信息

select * from emp e2 where e2.salary < ( select avg(e1.salary) from emp e1 where e1.dept_id = e2.dept_id);

11)查询所有的部门信息,并统计部门的员工人数

select d.id, d.name , ( select count(*) from emp e where e.dept_id = d.id ) '人数' from dept d;

12)查询所有学生的选课情况,展示出学生名称,学号,课程表。

select distinct s.name, s.no, c.name from student s, student_course sc, course c where s.id = sc.studentid or c.id = sc.courseid;

你可能感兴趣的:(数据库,数据库,mysql,datagrip)