第二章(数据库和表的基本操作)
1.数据库的基本操作
1.创建数据库的基本语法格式:
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name [create_option];
IF NOT EXISTS:可选项
create_option:可选项,用于设置所创建的数据库的特征
eg:创建数据库itcast
字符集为utf8mb4。
CREATE DATABASE IF NOT EXISTS itcast CHARACTER SET utf8mb4;
2.查看数据库
SHOW DATABASES
SHOW {DATABASES | SCHEMAS} [LIKE 'pattern' | WHERE expr];
3.查看数据库创建
SHOW CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name;
4.使用USE语句选择某个数据库为后续操作的默认数据库。
USE <数据库名>
eg:
USE itcast;
5.查看当前选择的是哪个数据库
SELECT DATABASE();
6.如果后续想修改数据库的特征,可以使用ALTER DATABASE语句实现
ALTER {DATABASE | SCHEMA} [db_name] alter_option;
7.删除数据库的基本语法格式
ALTER {DATABASE | SCHEMA} db_name alter_option;
eg:
DROP DATABASE IF EXISTS itcast;
2.数值类型
整数类型 5种(5种int),浮点数类型 2,定点数类型 1,BIT类型
MySQL中的字符串类型分为CHAR、VARCHAR、TEXT等多种类型
3.数据表的基本操作(重点,简答有查看语句)
1.查看数据表的SQL有3种
使用SHOW TABLES语句查看数据表(查看表名)
SHOW TABLES LIKE 'pattern' \| WHERE expr;
;
用SHOW CREATE TABLE查看数据表创建语句
SHOW CREATE TABLE tbl_name;
;
使用DESCRIBE语句查看数据表结构信息(字段具体属性)
DESCRIBE 数据表名;
;
2.实现数据表结构的修改
(1)将数据库ems中的数据表 tb_dept的名称修改为dept
ALTER TABLE tb_dept RENAME dept;
(2)数据表中的表选项字符集、校对集及存储引擎也可以通过ALTER TABLE语句进行修改
修改数据表dept 的字符集:
ALTER TABLE dept CHARACTER SET=gbk;
(3)修改字段名
RENAME COLUMN 仅可以修改字段名,
CHANGE子句不仅可以修改字段名称,还可以重新定义字段的属性(数据类型、约束、排列位置)
eg(1):以将部门表dept中的字段名loc改为local_name为例
ALTER TABLE dept RENAME COLUMN loc TO local_name ;
eg(2):
ALTER TABLE 表名
CHANGE 旧字段名 新字段名 新数据类型 [新约束] [FIRST|AFTER 列名];
(4)修改字段数据类型
MODIFY 仅可以对字段的数据类型 和排列位置 重新定义,而CHANGE不仅 可以对字段的数据类型和排列位置重新定义,还可以修改字段名称
eg:以将部门表dept中字段dname的数据类型由VARCHAR(14)修改为CHAR(16)为例
ALTER TABLE dept MODIFY dname CHAR(16);
(5)修改字段排列位置
注意要写两遍字段名
将部门表dept中字段local_name的位置修改为数据表的第一个字段
ALTER TABLE dept CHANGE local_name local_name CHAR(20) FIRST;
将部门表dept中字段deptno修改到字段dname后面
ALTER TABLE dept MODIFY deptno INT AFTER dname;
(6)添加字段
ALTER TABLE dept ADD id INT FIRST;
(7)删除字段
ALTER TABLE dept DROP id;
(8)删除数据表
部门表dept的删除:
DROP TABLE IF EXISTS dept;
4.约束
常见的约束有非空约束、唯一约束、主键约束、外键约束和默认值约束,其中FOREIGN KEY约束涉及到多表操作,将在第5章进行讲解。
非空约束
NOT NULL
eg: 将数据表tb_dept01中的dname字段添加非空约束
ALTER TABLE tb_dept01 MODIFY dname VARCHAR(14) NOT NULL;
eg: 修改数据表时使用CHANGE删除非空约束
ALTER TABLE tb_dept01 CHANGE COLUMN dname dname varchar(14);
唯一约束
UNIQUE
修改数据表时使用ADD添加唯一约束
为数据表tb_emp01中的email字段添加唯一约束
ALTER TABLE tb_emp01 ADD UNIQUE(email) ;
使用DROP删除唯一约束
将数据表tb_emp01中的empno字段唯一约束删除
ALTER TABLE tb_emp01 DROP index empno;
主键约束:为了快速查找到表中的某条记录
PRIMARY KEY
修改数据表时使用ADD给字段添加主键约束为数据表tb_dept01中的deptno字段添加主键约束
ALTER TABLE tb_dept01 ADD PRIMARY KEY(deptno);
使用DROP删除数据表tb_dept01中的主键约束
ALTER TABLE tb_dept01 DROP PRIMARY KEY;
默认值约束
DEFAULT
修改数据表时使用MODIFY添加默认值约束
修改数据表tb_emp02时为字段sal添加默认值约束,默认值为0.00
ALTER TABLE tb_emp02 MODIFY sal DECIMAL(7,2) DEFAULT 0.00;
使用CHANGE删除默认值约束
修改数据表tb_emp02时删除字段sal的默认值约束
ALTER TABLE tb_emp02 CHANGE sal sal DECIMAL(7,2);
5.自动增长
AUTO_INCREMENT
四个特点
一表一个键自增,插空给值自动升; 手动插大会跳号,删除不改旧水坑。
CREATE TABLE tb_emp03(
empno INT PRIMARY KEY AUTO_INCREMENT,
deptname VARCHAR(14) NOT NULL,
job VARCHAR(13)
);
注意
数据类型
1.关键区别
| DECIMAL | Float/Double | |
|---|---|---|
| 小数位数 | 你指定 (M,D) 中的 D | 自动决定,由精度限制 |
| 有效数字 | M 位 | Float约7位,Double约15位 |
| 控制权 | 完全可控 | 不可控 |
2.定点数
定点数(精确小数):DECIMAL(M,D) ------ 考试考过!FLOAT/DOUBLE是浮点数(近似)
3.二进制与大文本类型
固定长度二进制:BINARY | 大文本:TEXT | 大二进制:BLOB
BINARY --- 固定长度二进制
hash BINARY(16) -- 存储固定长度的哈希值
类似 CHAR,但存的是二进制数据
TEXT --- 大文本
content TEXT -- 最大 65535 字符(约64KB)
long_content MEDIUMTEXT -- 最大 16MB
huge_content LONGTEXT -- 最大 4GB
特点:
-
存大段文字(文章、评论、日志)
-
不能设默认值
-
查询效率比 VARCHAR 低(会溢出存储)
BLOB --- 大二进制
avatar BLOB -- 存图片、音频、视频
file_data MEDIUMBLOB -- 最大 16MB
特点:
-
存二进制数据(图片、文件等)
-
通常不建议直接存文件在数据库
第六章:索引和视图
索引
介绍:
索引类似于书籍的目录,如果想要快速访问数据表中的特定信息 ,可以建立索引加快数据查询效率。使用数据库时,不仅需要提高对数据的查询效率,也需要考虑数据的安全问题。在MySQL中可以创建一种叫视图的虚拟表 ,让使用视图的用户只能访问被允许访问的结果集 ,从而提高数据的安全性 。除了安全性,视图还具备简化查询语句和逻辑数据独立性等优点
虽然索引可以提高数据的查询速度,但索引会占用一定的磁盘空间,并且在创建和维护索引时,其消耗的时间是随着数据量的增加而增加的。
3种创建索引的方式,分别是创建数据表的同时 创建索引、在已有的数据表上 创建索引、修改数据表的同时创建索引。
创建数据表的同时创建索引
(1)创建数据表时创建单列索引
CREATE TABLE dept_index(
id INT,
deptno INT ,
dname VARCHAR(20),
introduction VARCHAR(200),
address GEOMETRY NOT NULL SRID 4326,
PRIMARY KEY(id), -- 创建主键索引
UNIQUE INDEX (deptno), -- 创建唯一性索引
INDEX (dname), -- 创建普通索引
FULLTEXT (introduction),-- 创建全文索引
SPATIAL INDEX (address) -- 创建空间索引
) ;
显示创建数据表index_normal的语句
SHOW CREATE TABLE dept_index\G
(2)创建复合索引
注意:
复合索引中,多个字段的设置顺序要准守"最左前缀原则",也就是在创建索引时 ,把使用频繁最高的字段放在索引字段列表的最左边,次频繁使用的字段放在设计索引字段列表的第二位,以此类推
创建数据表index_multi,在数据表中的id和name字段上建立索引名为multi的普通索引
CREATE TABLE index_multi(
id INT NOT NULL,
name VARCHAR(20) NOT NULL,
score FLOAT,
INDEX multi(id,name)
);
在已有的数据表上创建索引
CREATE INDEX
(1)创建数据表时创建单列索引
在数据表dept_index02中的id字段上,建立一个名称为unique_id的唯一性索引
CREATE UNIQUE INDEX unique_id ON dept_index02(id);
(2)创建复合索引
在dept_index02表中的deptno字段和dname字段上,创建一个名称为multi_index的复合索引
CREATE INDEX multi_index ON dept_index02(deptno,dname);
修改数据表的同时创建索引。
使用ALTER TABLE语句在修改数据表的同时创建索引
(1)创建数据表时创建单列索引
在数据表dept_index03中的id字段上,创建名称为index_id的唯一性索引
ALTER TABLE dept_index03 ADD UNIQUE INDEX index_id(id);
需要注意的是,创建唯一性索引时,需要确保数据表中的数据不存在重复的值,否则会出错
(2)创建复合索引
在dept_index03表中的deptno字段和dname字段上,创建一个名称为multi_index的复合唯一性索引
ALTER TABLE dept_index03 ADD UNIQUE INDEX multi_index(deptno,dname);
查看数据表中已经创建的索引的信息
除了使用SHOW CREATE TABLE语句在数据表的创建语句中查看,还可以通过如下语法格式的语句进行查看。
SHOW {INDEXES|INDEX|KEYS} FROM 数据表名;
通过EXPLAIN关键字分析SQL语句的执行情况
EXPLAIN可以分析的语句有SELECT、UPDATE、DELETE、INSERT和REPLACE。
eg: 使用EXPLAIN关键字查看查询语句的执行情况
EXPLAIN SELECT id FROM ems.dept_index WHERE id=1 \G
删除索引
使用ALTER TABLE 语句或DROP INDEX语句删除索引
ALTER TABLE 表名 DROP INDEX 索引名;
DROP INDEX 索引名 ON 数据表名;
eg: 通过ALTER TABLE语句删除数据表dept_index中名称为introduction的全文索引
ALTER TABLE dept_index DROP INDEX introduction;
eg: 删除数据表dept_index中名称为dname的索引
DROP INDEX dname ON dept_index;
视图
视图是一种虚拟存在 的表,并不在数据库中实际存在,它的数据依赖于真实存在的数据表。通过视图不仅可以看到其依赖数据表中的数据,还可以像操作数据表一样crud
创建视图(AS)
CREATE [OR REPLACE] VIEW 视图名 [(字段列表)] AS select_statement
(1)OR REPLACE:可选参数,表示若数据库中已经存在这个名称的视图就替换原有的视图,若不存在则创建视图;
(2)视图名:表示要创建的视图名称,该名称在数据库中必须是唯一的,不能与其他数据表或视图同名;
(3)select_statement :指一个完整的SELECT语句 ,表示从某个数据表或视图中查出满足条件的记录,将这些记录导入视图中。
视图的基本表可以是一张数据表,也可以是多张数据表
基于单表创建视图
将员工工号empno、员工姓名ename、职位job和部门编号deptno查询出来创建视图view_emp
CREATE VIEW view_emp AS SELECT empno,ename,job,deptno FROM emp;
创建一个新的视图view_emp2,视图view_emp2中包含的字段和视图view_emp相同,但视图view_emp2中字段名称和员工表中字段名称不一致【修改字段名称】
CREATE VIEW view_emp2 (e_no,e_name,e_job,e_deptno)
AS
SELECT empno,ename,job,deptno FROM emp;
基于多表创建视图
视图中需要使用ems数据库中员工编号empno、员工姓名ename、职位job、部门编号deptno和部门名称dname的信息。
下面根据需求创建视图view_emp_dept
CREATE VIEW view_emp_dept(e_no,e_name,e_job,e_deptno,e_deptname)
AS
SELECT e.empno,e.ename,e.job,e.deptno,d.dname
FROM emp e LEFT JOIN dept d ON e.deptno=d.deptno;
查看
查看视图的字段信息
使用DESCRIBE 语句可以查看视图 的字段名 、字段类型等字段信息
DESCRIBE 视图名;
或
DESC 视图名;
视图的状态信息
使用SHOW TABLE STATUS 语句可以查看视图和数据表 的状态信息
SHOW TABLE STATUS LIKE '视图名';
LIKE表示后面匹配的是字符串,'视图名'表示要查看的视图的名称,视图名称需要使用单引号包裹起来。
视图的创建语句
使用SHOW CREATE VIEW语句可以查看创建视图时的定义语句
SHOW CREATE VIEW 视图名;
修改视图
修改视图 = 修改视图的 SELECT 定义
(1)使用CREATE OR REPLACE VIEW语句修改视图
要求被修改的视图 在数据库中已经存在,如果视图不存在,那么将创建一个新的视图
CREATE OR REPLACE VIEW 视图名 AS SELECT语句
eg: 在视图view_emp_dept原有的基础上新增员工上级工号的字段,
CREATE OR REPLACE VIEW view_emp_dept(e_no,e_name,e_job,e_mgr,e_deptno,e_deptname)
AS
SELECT e.empno,e.ename,e.job,e.mgr,e.deptno,d.dname
FROM emp e LEFT JOIN dept d ON e.deptno=d.deptno;
(2)使用ALTER语句修改视图
ALTER VIEW <视图名> AS <SELECT语句>
eg: 使用ALTER语句将视图view_emp_dept中的部门编号字段进行删除
ALTER VIEW view_emp_dept (e_no,e_name,e_job,e_mgr,e_deptname)
AS
SELECT e.empno,e.ename,e.job,e.mgr,d.dname
FROM emp e LEFT JOIN dept d ON e.deptno=d.deptno;
删除视图
删除一个或多个视图可以使用DROP VIEW语句
DROP VIEW view_name [,view_name1,…];
视图数据操作(有查询)
添加数据
向基本表添加数据可以使用INSERT语句
通过视图向数据表中添加数据的方式与直接向数据表中添加数据的格式一样
eg:
INSERT INTO view_dept VALUES(50, '人力资源部');
修改数据
通过视图修改基本表的数据,可以使用UPDATE语句
eg:
使用UPDATE语句,通过视图将研究院的部门名称修改为研究中心
UPDATE view_dept SET d_name='研究中心' WHERE d_name='研究院';
删除数据
通过视图删除基本表的数据,可以使用DELETE语句。
eg: 通过视图view_dept删除部门表dept中部门名称为人力资源部的记录
DELETE FROM view_dept WHERE d_name='人力资源部';
4:单表查询
顺序
SELECT 字段 FROM 表名 WHERE 条件 GROUP BY 字段 HAVING 条件 ORDER BY 字段 LIMIT 行数;
-
WHERE筛选行 -
HAVING筛选组
SELECT语句
SELECT [DISTINCT] *|{select_expr1, select_expr2, …} FROM 数据表名
[WHERE 条件表达式1]
[GROUP BY 字段名 [HAVING 条件表达式2]]
[ORDER BY 字段名 [ASC|DESC]]s
[LIMIT [OFFSET] 记录数]
简单查询
查询所有字段的方式有两种
1.列出所有字段名称进行查询,字段的顺序是可以改变的
SELECT 字段名1,字段名2,… FROM 数据表名;
2.使用通配符*进行查询
SELECT * FROM 数据表名;
3.查询时将结果中的重复值去除
数据表的字段如果没有设置唯一约束,查询时用DISTINCT关键字
SELECT DISTINCT 字段名 FROM 数据表名;
注意:DISTINCT关键字可以作用于多个字段,但是只有这些字段的值都相同才被认为是重复记录
SELECT DISTINCT 字段名1,字段名2,… FROM 表名;
4.指定部分字段查询
SELECT 字段名1,字段名2,… FROM 数据表名;
条件查询
带比较运算符的查询
比较运算符:使用比较运算符对数据进行过滤
BETWEEN ... AND(连续值范围查询)
SELECT 列名 FROM 表名 WHERE 列名 BETWEEN 下界 AND 上界;
-- 查询薪水在 2000 到 3000 之间的员工(包含2000和3000)
SELECT * FROM emp WHERE sal BETWEEN 2000 AND 3000;
IN(离散值集合查询)【逗号分隔】
SELECT 列名 FROM 表名 WHERE 列名 IN (值1, 值2, ...);
-- 查询部门号为 10, 20, 30 的员工
SELECT * FROM emp WHERE deptno IN (10, 20, 30);
<>等价!=
查询员工表中,所属部门编号不是30的员工信息
SELECT * FROM emp WHERE deptno<>30;
=运算符:
=运算符用于比较运算符左右两边的操作数,如果操作数的字段类型为字符串 ,需要使用单引号 对操作数进行包裹。WHERE子句的条件表达式中,字符串以不区分大小写的方式进比较运算
查询员工表emp中员工张三的信息
SELECT * FROM emp WHERE ename='张三';
IS NULL:
当操作数为NULL时,不能使用运算符=、<>、!=进行比较,这是因为NULL代表未指定或不可预知的值。如果需要判断数据是否为NULL的时候,可以使用IS NULL进行比较
查询员工表中,直属上级编号为NULL的员工信息
SELECT * FROM emp WHERE mgr IS NULL;
LIKE:对数据进行模糊查询,用于比较两个操作数是否匹配
SELECT *|{字段名1,字段名2,…}
FROM 数据表名
WHERE 值 [NOT] LIKE 匹配的字符串;
通配符:% 匹配任意长度字符串(包括空),_ 匹配单个字符(如果要匹配多个字符,需要使用多个_通配符)
(1)查询员工表中,姓名以"一"结尾的员工信息
SELECT * FROM emp WHERE ename LIKE '%一';
(2)查询员工表中,姓名以"萧"开头以"一"结尾的员工信息
SELECT * FROM emp WHERE ename LIKE '萧%一';
(3)查询员工表中,姓名包含字符"十"的员工信息
SELECT * FROM emp WHERE ename LIKE '%十%';
(4)查询员工表中,姓名长度为3,并且以字符"一"结尾的员工信息
# 两个下划线是连在一起写的
SELECT * FROM emp WHERE ename LIKE '__一';
# 注意:如果要匹配的普通字符串中也包含了%和_,就需要使用右斜线(\)进行转义,例如,“\%”匹配字符“%”,“\_”匹配字符“_”
带逻辑运算符的查询
NOT等价!
查询员工表中,部门编号不是10和30的员工信息
SELECT * FROM emp WHERE deptno NOT IN(10,30);
AND:连接两个或者多个查询条件
查询员工表中职位为经理,并且所属部门编号为20的员工信息
SELECT * FROM emp WHERE job='经理' AND deptno=20;
OR: 连接多个查询条件,只要满足任意一个查询条件,对应的数据就会被查询出来
查询员工表中,员工职位为经理或者所属部门编号为10的员工信息
SELECT * FROM emp WHERE job='经理' OR deptno=10;
注意:
OR关键字和AND关键字也可以一起使用,需要注意的是,AND的优先级高于OR
【当两者在一起使用时,应该先运算AND两边的条件表达式,再运算OR两边的条件表达式】
查询emp表中,员工姓名为刘一,或者员工姓名为李四并且部门编号为30的员工信息
SELECT * FROM emp WHERE ename='刘一' or ename='李四' AND deptno=30;
高级查询
聚合
聚合操作:通过聚合函数实现,统计某个字段的最大值、最小值、平均值等,像这样对一组值执行计算,并将计算后的值返回的数据统计操作
SELECT [字段名1,字段名2,…,字段名n}] 聚合函数 FROM 数据表名;
COUNT( 字段的名称 )函数 :计有多少行
检索数据表行中的值的计数, COUNT(*) 可以统计数据表中记录的总条数
(1)查询员工表中有多少个员工的记录。在查询时可以使用COUNT()函数进行统计
SELECT COUNT(*) FROM emp;
(2)查询员工表中,奖金不为NULL的员工个数
SELECT COUNT(COMM) FROM emp;
SUM()函数: 计这些行的数值加起来是多少
查询员工表中员工奖金的总和
SELECT SUM(COMM) FROM emp;
**AVG()函数:**统计该字段中所有值的平均值,并且计算时会忽略字段中的NULL值
查询员工表中员工的平均奖金。查询时可以使用AVG()函数进行统计
SELECT AVG(COMM) FROM emp;
查询所有员工的平均奖金。查询时可以调用AVG()函数和IFNULL()函数进行统计,先调用IFNULL()函数将COMM字段中所有的NULL值转换为0,再调用AVG()函数统计平均值【因为 AVG() 忽略 NULL 会导致"人数少算"】
SELECT AVG(IFNULL(COMM,0)) FROM emp;
MAX()函数: 计算指定字段中的最大值
MIN()函数: 计算指定字段中的最小值
分组查询
数据进行统计时,需要按照一定的类别进行统计
使用GROUP BY 根据指定的字段对结果集进行分组,如果某些记录的指定字段具有相同的值 ,那么分组后被合并为一条数据
单独使用GROUP BY分组:根据指定的字段合并数据行
查询员工表的部门编号有哪几种
SELECT deptno FROM emp GROUP BY deptno;
GROUP BY和聚合函数一起使用【通常】:分组查询时要进行统计汇总
统计员工表各部门的薪资总和或平均薪资,可以使用GROUP BY和聚合函数AVG()、SUM()
SELECT deptno,AVG(sal),SUM(sal) FROM emp GROUP BY deptno;
GROUP BY和HAVING关键字一起使用 :用于对分组后的结果 进行条件过滤
注意(考点)
WHERE 用于过滤原始表的行(在分组前)【此时聚合函数(如 AVG、SUM、COUNT)还没有计算出结果,因此 WHERE 子句中不能直接使用聚合函数。】
HAVING 用于过滤分组后的结果。
这里要对聚合结果进行筛选应使用 HAVING,而不是 WHERE
查询员工表中平均工资小于3000的部门编号及这些部门的平均工资
#错的
SELECT deptno,AVG(sal) AS a FROM emp WHERE a < 3000 GROUP BY deptno;
# 对的
SELECT deptno,AVG(sal) FROM emp GROUP BY deptno HAVING AVG(sal)<3000;
排序查询
如果想要对查询结果按指定的方式排序,可以使用ORDER BY 对查询结果进行排序
SELECT *|{ 字段名1,字段名2,…}
FROM 表名
ORDER BY 字段名1 [ASC | DESC],字段名2 [ASC | DESC]…;
ASC表示从小到大,DESC表示从大到小;ORDER BY默认对查询结果按照ASC方式进行排序。
排序时,如果字段的值中包含NULL,NULL会被当做最小值进行排序
eg:查询员工表中,部门编号为30的员工信息,查询出的结果根据员工工资升序排列
SELECT * from emp WHERE deptno=30 ORDER BY sal DESC;
限量查询
LIMIT
SELECT 字段名1,字段名2,…
FROM 数据表名
LIMIT [OFFSET,] 记录数;
LIMIT 5 |
返回第 1~5 行 |
|---|---|
LIMIT 0, 5 |
同上 |
LIMIT 5, 10 |
跳过前5行,返回第6~15行 |
LIMIT 10 OFFSET 5 |
同上(更易读) |
查询员工表中,工资最高的前5名的员工信息
SELECT * FROM emp ORDER BY sal DESC LIMIT 5;
查询员工表中,工资前2~5名的员工信息】【第一个参数表示逃过几行,第二个表示取接下来开始后的几行】
SELECT * FROM emp ORDER BY sal DESC LIMIT 1,4;
设置别名(AS)
# AS为可选项
SELECT * FROM 数据表名 [AS] 别名;
查询员工信息时,为emp数据表起一个别名e
SELECT * FROM emp e WHERE e.deptno=30;
5:多表操作
多表查询
连接查询包括交叉连接查询、内连接查询、外连接查询、复合条件连接查询
交叉连接(CROSS JOIN) :查询返回的结果是被连接的两张数据表中所有数据行的笛卡尔积
表 A:员工表 (2 行) 表 B:部门表 (3 行) 得到的结果集是 2 × 3 = 6 行,
SELECT <字段名> FROM <数据表名1> CROSS JOIN <数据表名2> ;
或
SELECT <字段名> FROM <数据表名1>, <数据表名2> ;
内连接(INNER JOIN)查询:仅筛选出两张表中相互匹配的记录
# INNER JOIN用于连接2张数据表,其中INNER可以省略;ON用于指定查询的匹配条件
SELECT 查询字段 FROM 数据表1 [INNER] JOIN 数据表2 ON 匹配条件;
查询已经分配了部门(部门号不为NULL)的员工的信息,员工信息只需要显示员工姓名和对应部门的名称
SELECT ename,dname FROM emp e JOIN dept d ON e.deptno=d.deptno;
自连接 :解决"同一张表内,行与行之间进行比较或组合"的问题
查询员工王五所在部门的所有员工信息
SELECT e1.* FROM emp e1 JOIN emp e2 ON e1.deptno=e2.deptno
WHERE e2.ename='王五';
外连接查询:
左连接(LEFT JOIN)查询和右连接(RIGHT JOIN)查询
(1)LEFT JOIN:返回左表中的所有记录和右表中符合连接条件的记录。右表会有null
(2)RIGHT JOIN:返回右表中的所有记录和左表中符合连接条件的记录。左表会有null
查询所有部门名称 及部门对应员工的姓名 。因为需要查询出所有部门的名称,查询时可以使用左连接查询 ,将部门表 作为查询中的左表
SELECT d.dname,e.ename FROM dept d LEFT JOIN emp e ON e.deptno=d.deptno;
查询所有员工姓名 及对应部门的名称 ,没有分配部门的员工也需要查询出来 。因为需要查询出所有员工的名称,查询时可以使用右连接查询,将员工表 作为查询中的右表
SELECT d.dname,e.ename FROM dept d RIGHT JOIN emp e ON e.deptno=d.deptno;
总结
左连接是保留左边的表,右连接保留右边的表
复合条件连接查询
复合条件连接查询
在连接查询 的过程中,通过添加过滤条件限制执行结果
查询所有员工信息,员工信息包含员工所在部门的名称,并且按员工的工资降序排序。
SELECT e.*,d.dname FROM emp e LEFT JOIN dept d ON e.deptno=d.deptno
ORDER BY e.sal DESC;
子查询
当某个语句执行所需要的过滤条件是另外一个SELECT语句的结果时,可以使用子查询;
通常在WHERE 子句中结合操作符一起使用,操作符可以是IN、EXISTS、ANY、ALL、比较运算符
IN :需要内层子查询语句返回的结果是一个数据列
# 查询工资大于2900的员工所属部门
SELECT * FROM dept WHERE deptno IN(SELECT deptno FROM emp WHERE sal>2900);
EXISTS:(考点)
判断子查询的结果集是否为空【判空】
注意:
使用EXISTS关键字结合子查询进行查询时,会先执行外层查询语句 ,再根据EXISTS关键字后面子查询的查询结果,判断是否保留外层语句查询出的记录
# 查询工资大于2900的员工所在的部门信息
SELECT * FROM dept WHERE EXISTS
(SELECT * FROM emp WHERE emp.deptno=dept.deptno AND emp.sal>2900);
使用EXISTS关键字结合子查询,和使用IN关键字结合子查询的结果一致,但在表数据不同时,这两种方式的性能也不同
当外表数据量比较大,内表数据量比较小的时候,适合使用IN关键字结合子查询进行查询;反之【根据他们的性质理解】
ANY
表示任意一个,必须和比较操作符一起使用,例如ANY和>结合起来使用,表示大于任意一个
例如"值1>ANY(子查询)",比较值1是否大于 子查询返回的结果集中任意一个结果。
# 查询部门编号为10的员工信息,要求查询到的员工信息中,工资都高于部门编号为20的部门中的最低工资;
# 查询时可以先使用子查询语句查询出部门编号为20的部门中所有员工工资,接着查询部门编号为10的部门中所有员工信息,最后使用ANY连接两者的工资进行比较
SELECT * FROM emp WHERE deptno=10 AND
sal>ANY(SELECT sal FROM emp WHERE deptno=20);
注意:
一般情况下,表连接查询都可以用子查询替换,但反过来却不一定适用。子查询相对比较灵活、方便、形式多样,适合作为查询的筛选条件,而表连接查询更适合查看连接表的数据。
ALL
在 MySQL 中,ALL 关键字通常与比较运算符(=、>、<、>=、<=、<>)一起使用,放在子查询前面,表示**"大于子查询返回的** 所有值"、"小于所有值"等
-- 查询工资比所有部门10的员工都高的员工
SELECT ename, sal FROM emp
WHERE sal > ALL (SELECT sal FROM emp WHERE deptno = 10);
# 等价于:
sal > (SELECT MAX(sal) FROM emp WHERE deptno = 10)
外键约束
外键是数据表中的一个特殊字段,它引用另一张数据表中的一列或多列,被引用的列应该具有主键约束或唯一性约束
主键所在的数据表就是主表 ,外键所在的数据表就是从表
为从表添加外键约束
ALTER TABLE 从表名 ADD CONSTRAINT [外键名称] FOREIGN KEY(外键字段名)
REFERENCES 主表名(主键字段名);
删除外键约束
ALTER TABLE表名DROP FOREIGN KEY 外键名;