概览
- 多表查询
- 事务
- 约束
多表查询
-
笛卡尔积
- 有两个集合A,B .取这两个集合的所有组成情况。
- 要完成多表查询,需要消除无用的数据
-
隐式内连接:使用where条件消除无用数据
- 举例
# 查询所有员工信息和对应的部门信息 SELECT * FROM emp,dept WHERE emp.`dept_id` = dept.`id`; # 查询员工表的名称,性别。部门表的名称 SELECT emp.name,emp.gender,dept.name FROM emp,dept WHERE emp.`dept_id` = dept.`id`; SELECT t1.name, # 员工表的姓名 t1.gender,# 员工表的性别 t2.name # 部门表的名称 FROM emp t1, dept t2 WHERE t1.`dept_id` = t2.`id`;
- 举例
-
显式内连接:
- 举例
# select 字段列表 from 表名1 [inner] join 表名2 on 条件 SELECT * FROM emp INNER JOIN dept ON emp.`dept_id` = dept.`id`; SELECT * FROM emp JOIN dept ON emp.`dept_id` = dept.`id`;
- 举例
-
外链接查询:
-
查询的是左表所有数据以及其交集部分。
-
select 字段列表 from 表1 left [outer] join 表2 on 条件;
-
举例
# 查询所有员工信息,如果员工有部门,则查询部门名称,没有部门,则不显示部门名称 SELECT t1.*,t2.`name` FROM emp t1 LEFT JOIN dept t2 ON t1.`dept_id` = t2.`id`; -
右外连接:
select 字段列表 from 表1 right [outer] join 表2 on 条件;- 查询的是右表所有数据以及其交集部分。
- 举例
SELECT * FROM dept t2 RIGHT JOIN emp t1 ON t1.`dept_id` = t2.`id`;
-
-
子查询:
-
查询中嵌套查询,称嵌套查询为子查询。
-
举例
# 查询工资最高的员工信息 # 1 查询最高的工资是多少 9000 SELECT MAX(salary) FROM emp; # 2 查询员工信息,并且工资等于9000的 SELECT * FROM emp WHERE emp.`salary` = 9000; # 一条sql就完成这个操作。子查询 SELECT * FROM emp WHERE emp.`salary` = (SELECT MAX(salary) FROM emp);
- 子查询不同情况
# 子查询的结果是单行单列的: # 子查询可以作为条件,使用运算符去判断。 运算符: > >= < <= = # 查询员工工资小于平均工资的人 SELECT * FROM emp WHERE emp.salary < (SELECT AVG(salary) FROM emp); # 子查询可以作为条件,使用运算符in来判断 # 查询'财务部'和'市场部'所有的员工信息 SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部'; SELECT * FROM emp WHERE dept_id = 3 OR dept_id = 2; # 子查询 SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部'); # 子查询可以作为一张虚拟表参与查询 # 查询员工入职日期是2011-11-11日之后的员工信息和部门信息 SELECT * FROM dept t1 ,(SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11') t2 WHERE t1.id = t2.dept_id; # 普通内连接 SELECT * FROM emp t1,dept t2 WHERE t1.`dept_id` = t2.`id` AND t1.`join_date` > '2011-11-11'
-
-
练习
# 查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述 SELECT t1.`id`, # 员工编号 t1.`ename`, # 员工姓名 t1.`salary`, # 工资 t2.`jname`, # 职务名称 t2.`description` # 职务描述 FROM emp t1, job t2 WHERE t1.`job_id` = t2.`id`; # 2.查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置 SELECT t1.`id`, # 员工编号 t1.`ename`, # 员工姓名 t1.`salary`,# 工资 t2.`jname`, # 职务名称 t2.`description`, # 职务描述 t3.`dname`, # 部门名称 t3.`loc` # 部门位置 FROM emp t1, job t2,dept t3 WHERE t1.`job_id` = t2.`id` AND t1.`dept_id` = t3.`id`; # 3.查询员工姓名,工资,工资等级 SELECT t1.ename , t1.`salary`, t2.* FROM emp t1, salarygrade t2 WHERE t1.`salary` BETWEEN t2.`losalary` AND t2.`hisalary`; # 4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级 SELECT t1.`ename`, t1.`salary`, t2.`jname`, t2.`description`, t3.`dname`, t3.`loc`, t4.`grade` FROM emp t1,job t2,dept t3,salarygrade t4 WHERE t1.`job_id` = t2.`id` AND t1.`dept_id` = t3.`id` AND t1.`salary` BETWEEN t4.`losalary` AND t4.`hisalary`; # 5.查询出部门编号、部门名称、部门位置、部门人数 SELECT t1.`id`,t1.`dname`,t1.`loc` , t2.total FROM dept t1, (SELECT dept_id,COUNT(id) total FROM emp GROUP BY dept_id) t2 WHERE t1.`id` = t2.dept_id; # 6.查询所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询 SELECT t1.ename, t1.mgr, t2.`id`, t2.`ename` FROM emp t1 LEFT JOIN emp t2 ON t1.`mgr` = t2.`id`;
事务
| 命令 | 描述 |
|---|---|
| 开启事务 | start transaction |
| 回滚 | rollback |
| 提交 | commit |
- 如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。
- 举例
CREATE TABLE account ( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(10), balance DOUBLE ); # 添加数据 INSERT INTO account (NAME, balance) VALUES ('zhangsan', 1000), ('lisi', 1000); SELECT * FROM account; UPDATE account SET balance = 1000; # 张三给李四转账 500 元 # 0. 开启事务 START TRANSACTION; # 1. 张三账户 -500 UPDATE account SET balance = balance - 500 WHERE NAME = 'zhangsan'; # 2. 李四账户 +500 # 出错了... UPDATE account SET balance = balance + 500 WHERE NAME = 'lisi'; # 发现执行没有问题,提交事务 COMMIT; # 发现出问题了,回滚事务 ROLLBACK;
约束
| 命令 | 描述 |
|---|---|
| 主键约束 | primary key |
| 非空约束 | not null |
| 唯一约束 | unique |
| 外键约束 | foreign key |
-
对表中的数据进行限定,保证数据的正确性、有效性和完整性。
-
非空约束:not null,某一列的值不能为null
- 示例
# 创建表时添加约束 CREATE TABLE stu( id INT, NAME VARCHAR(20) NOT NULL # name为非空 ); # 创建表完后,添加非空约束 ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL; # 删除name的非空约束 ALTER TABLE stu MODIFY NAME VARCHAR(20);
- 示例
-
唯一约束:unique,某一列的值不能重复
- 唯一约束可以有NULL值,但是只能有一条记录为null
- 示例
# 在创建表时,添加唯一约束 CREATE TABLE stu( id INT, phone_number VARCHAR(20) UNIQUE # 手机号 ); # 删除唯一约束 ALTER TABLE stu DROP INDEX phone_number; # 在表创建完后,添加唯一约束 ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;
-
主键约束:primary key。
- 含义:非空且唯一
- 一张表只能有一个字段为主键
- 主键就是表中记录的唯一标识
- 示例
# 在创建表时,添加主键约束 create table stu( id int primary key, # 给id添加主键约束 name varchar(20) ); # 删除主键约束 ALTER TABLE stu DROP PRIMARY KEY; # 创建完表后,添加主键 ALTER TABLE stu MODIFY id INT PRIMARY KEY; - 如果某一列是数值类型的,使用 auto_increment 可以来完成值得自动增长
- 在创建表时,添加主键约束,并且完成主键自增长
- 示例
create table stu( id int primary key auto_increment, # 给id添加主键约束 name varchar(20) ); # 删除自动增长 ALTER TABLE stu MODIFY id INT; # 添加自动增长 ALTER TABLE stu MODIFY id INT AUTO_INCREMENT; -
外键约束:
foreign key,让表于表产生关系,从而保证数据的正确性。- 示例
# 在创建表时,可以添加外键 create table 表名( .... 外键列 constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称) ); # 删除外键 ALTER TABLE 表名 DROP FOREIGN KEY 外键名称; # 创建表之后,添加外键 ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称); # 添加级联操作 # 级联更新:ON UPDATE CASCADE # 级联删除:ON DELETE CASCADE ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE ON DELETE CASCADE;
- 示例