(1)内连接
--隐示内连接
select 字段列表 from 表1 , 表2... where 条件;
-- 显示内连接
select 字段列表 from 表1,inner join 表2 on 条件;
内连接相当于查询A B的交集数据
隐士内连接和显示内连接没有任何的区别,查询出来的结构都是一样的,只不过这就是两种语法而已。
创建两张表(体现一对多的形式)
create table category(
cid int primary key auto_increment,
cname varchar(50) not null unique
);
create table product(
pid int primary key auto_increment,
pname varchar(50) not null ,
cid int ,
constraint FK_cid_cid foreign key (cid) references category(cid)
);
添加一些数据:
-- 笛卡尔积
select * from product,category;
select * from product,category where product.cid= category.cid;
select * from product,category inner join product p on category.cid = p.cid;
select p.* ,c.cid from category c inner join product p on c.cid = p.cid;
(2)外连接
左外连接和右外连接
-- 外连接
select p.pname,c.cname from product p inner join category c on p.cid = c.cid;
-- 左外连接
select p.pname,c.cname from product p left join category c on p.cid = c.cid;
-- 右外连接
select p.pname,c.cname from category c right join product p on p.cid = c.cid;
MySQL中不支持全连接。全连接不是笛卡尔积。
(3)子查询
子查询就是一个SQL语句查询的结果作为
子查询结果分为三种:
1)单行单列
使用比较运算符 >,<, >=, <=, = 等
2) 多行单列
使用in关键字
例如:
-- 创建一个产品表
create table product(
pid int primary key,
pname varchar(20),
price double,
category_id varchar(32)
);
-- 在表中添加一些数据
INSERT INTO product(pid,pname,price,category_id) VALUES(1,'联想',5000,'c001');
INSERT INTO product(pid,pname,price,category_id) VALUES(2,'海尔',3000,'c001');
INSERT INTO product(pid,pname,price,category_id) VALUES(3,'雷神',5000,'c001');
INSERT INTO product(pid,pname,price,category_id) VALUES(4,'JACK JONES',800,'c002');
INSERT INTO product(pid,pname,price,category_id) VALUES(5,'真维斯',200,'c002');
INSERT INTO product(pid,pname,price,category_id) VALUES(6,'花花公子',440,'c002');
INSERT INTO product(pid,pname,price,category_id) VALUES(7,'劲霸',2000,'c002');
INSERT INTO product(pid,pname,price,category_id) VALUES(8,'香奈儿',800,'c003');
INSERT INTO product(pid,pname,price,category_id) VALUES(9,'相宜本草',200,'c003');
INSERT INTO product(pid,pname,price,category_id) VALUES(10,'面霸',5,'c003');
INSERT INTO product(pid,pname,price,category_id) VALUES(11,'好想你枣',56,'c004');
INSERT INTO product(pid,pname,price,category_id) VALUES(12,'香飘飘奶茶',1,'c005');
INSERT INTO product(pid,pname,price,category_id) VALUES(13,'果9',1,NULL);
select avg(price) from product where pid in (1,3,7);
select*from product where pid in (1,3,5,7) order by price desc;
3)多行多列
将查询的结果使用AS取别名作为一张表,与其他表进行关联查询
(4)事务
事务的简介:数据库的事务(Transaction)是一种机制、一个操作序列,包含了一组数据库操作命令事务把所有的命令看作一个整体一起向系统提交或者撤销请求操作,即这一组数据库命令要么同时成功,要不就同时失败。
事务是一个不可分割的工作逻辑单元。
开启事务
START TRANSACTION;
或者 BEGIN;
提交事务
COMMIT;
回滚事务
ROLLBACK;
事务的四大特性:
1.原子性(Atomicity): 事务是不可分割的最小操作单位,要么同时成功,要么同时失败
2.一致性(Consistency) :事务完成时,必须使所有的数据都保持一致状态
3.隔离性(Isolation) :多个事务之间,操作的可见性
4.持久性(Durability) :事务一旦提交或回滚,它对数据库中的数据的改变就是永久的
关于子查询的一些小练习题
-- 需求:
-- 1.查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述
-- 2.查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
-- 3.查询员工姓名,工资,工资等级
-- 4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
-- 5.查询出部门编号、部门名称、部门位置、部门人数
-- 6.查询所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询
-- 部门表.
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);
参考答案:
-- 1.查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述
select e.id, e.ename, e.salary, j.jname, j.description
from emp e
inner join job j on e.job_id = j.id;
-- 2.查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
select *
from emp e
inner join job j
inner join dept d on e.job_id = j.id and d.id = e.dept_id;
-- 3.查询员工姓名,工资,工资等级
select e.ename, e.salary, s.grade
from salarygrade s
inner join emp e on e.salary between s.losalary and s.hisalary;
-- 4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
select e.ename, e.salary, j.jname, j.description, d.dname, d.loc, s.grade
from salarygrade s
inner join emp e
inner join job j
inner join dept d on e.dept_id = d.id and e.job_id = j.id and e.salary between s.losalary and s.hisalary;
-- 5.查询出部门编号、部门名称、部门位置、部门人数
select dept_id, count(dept_id)
from emp
group by dept_id;
select d.id, d.dname, d.loc, c.count
from (select dept_id, count(dept_id) as count
from emp
group by dept_id) c
inner join dept d on c.dept_id = d.id;
-- 6.查询所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询
select e1.ename, e2.ename
from emp e1
left join emp e2 on e1.mgr = e2.id;