联表查询不需要外键约束
mysql > select e.id as "编号", e.empName as "姓名", d.deptName as "部门"
from employee e -- 从哪里查?这里定义了简写
inner join dept d -- 使用内连接查询,去连接另一张表,定义了简写
on e.deptId = d.id -- 使用 on 来约束条件,查询条件,id一一对应
where e.name = "Jack" -- 其他约束条件
order by e.id asc; -- id顺序输出
内连接会排空,导致相关数据查不到,所以需要外连接。可以专门用来查询空的值,即不符合条件的。
左表数据一定全部展示,右表来匹配左表数据,如果右表没有数据,显示null。
mysql > select d.deptName as "部门", e.empName as "姓名"
from dept d
left outer join employee e
on d.id = e.deptId;
+-----------+-----------+
| 部门 | 姓名 |
+-----------+-----------+
| 1 | Jack |
| 2 | Jone |
| 3 | LUcy |
| 4 | Peter |
| 5 | Harry |
| 6 | Sparrow |
| 7 | NULL | -- 就是因为左表对应的右表没有数据,显示为null
+-----------+-----------+
右表数据一定全部展示,左表来匹配右表数据,如果左表没有数据,显示null
mysql > select e.empName as "姓名", d.deptName as "部门"
from employee e
right outer join dept d
on e.deptId = d.id
where d.id is null;
一个学生可能会有多次考试,但是每次考试对应的只属于一个学生。
将学生的id和score_record中的stuId建立内连接,进行查询,导出所有结果
-- 1. 找出 某人的所有成绩记录
mysql >
select s.id, s.name, sr.javaScore, sr.cScore, sr.htmlScore -- 查什么
from student s -- 从哪里查
inner join score_record sr -- 连接哪一张表
on s.id = sr.stuId -- 表之间的条件
where s.name = "翘翘"; -- 要求的查询学生的姓名
-- 2. 找出某人的所有成绩的平均分
mysql >
select s.id, s.name, avg(sr.javaScore), avg(sr.cScore), avg(sr.htmlScore) -- 查什么
from student s -- 从哪里查
inner join score_record sr -- 连接哪一张表
on s.id = sr.stuId -- 表之间的条件
where s.name = "翘翘"-- 要求的查询学生的姓名
group by s.id;
-- 3. 找出某人考试了几次???
mysql >
select s.id, s.name, count(sr.stuId)
from student s
inner join score_record sr
on s.id = sr.stuId
where s.name = "翘翘"
group by s.id;
-- 4.输出某人各科成绩,并每次考试都有计算各科成绩之和totalScore,可以使用AS定义
SELECT s.`id`, s.`name`, sr.`javaScore`, sr.`cScore`, sr.`htmlScore`, (sr.`javaScore` + sr.`cScore` + sr.`htmlScore`) AS "totalScore"
FROM student s
INNER JOIN score_record sr
ON s.`id` = sr.`stuId`
WHERE s.`name` = "翘翘";
+----+--------+-----------+--------+-----------+-----------+
| id | name | javaScore | cScore | htmlScore | totalScore|
+----+--------+-----------+--------+-----------+ ---------+
| 1 | 翘翘 | 10.50 | 20.50 | 35.50 | 66.50 |
| 1 | 翘翘 | 12.50 | 22.50 | 33.50 | 68.5 |
| 1 | 翘翘 | 13.50 | 21.50 | 30.50 | 65.5 |
+----+--------+-----------+--------+-----------+----------+
多对多要拆分出一对多的情况进行搭桥解决。
比如多个用户,权限不同,多个不同权限对应多个不同的功能。
mysql > create table user(
id int primary key auto_increment,
name varchar(20) not null,
roleId int not null
);
mysql > create table role(
id int primary key auto_increment,
roleName varchar(20) not null
);
mysql > create table privilege(
id int primary key auto_increment,
pName varchar(20) not null
);
mysql > create table role_to_privilege(
id int primary key auto_increment,
roleId int not null,
pId int not null
);
mysql > insert into user(name, roleId) values("张三", 1);
mysql > insert into user(name, roleId) values("李四", 2);
mysql > insert into role(roleName) values("管理员");
mysql > insert into role(roleName) values("普通用户");
mysql > insert into privilege(pName) values("删除用户"); -- 管理
mysql > insert into privilege(pName) values("添加用户"); -- 管理
mysql > insert into privilege(pName) values("修改用户"); -- 管理 用户
mysql > insert into privilege(pName) values("查看指定用户"); -- 管理 用户
mysql > insert into privilege(pName) values("查看所有用户"); -- 管理
-- role_to_privileg 根据id号,将用户类别和可用权限进行对接
mysql > insert into role_to_privilege(roleId, pId) values(1, 1);
mysql > insert into role_to_privilege(roleId, pId) values(1, 2);
mysql > insert into role_to_privilege(roleId, pId) values(1, 3);
mysql > insert into role_to_privilege(roleId, pId) values(1, 4);
mysql > insert into role_to_privilege(roleId, pId) values(1, 5);
mysql > insert into role_to_privilege(roleId, pId) values(2, 3);
mysql > insert into role_to_privilege(roleId, pId) values(2, 4);
-- 1. 我想找到张三的权限有什么???
-- u.name privilege.pName
mysql >
select u.name, p.pName
from user u
inner join role r
on u.roleId = r.id
inner join role_to_privilege rp
on r.id = rp.roleId
inner join privilege p
on rp.pId = p.id
where u.name = "张三";
mysql >
select u.name, p.pName
from user u
inner join role r
on u.roleId = r.id
inner join role_to_privilege rp
on r.id = rp.roleId
inner join privilege p
on rp.pId = p.id
where u.name = "李四";
比如一个员工对应一份简历,解决办法:
UNION 排重合并
UNION ALL 全部合并
由于可能存在列的不同,所以需要select进行选择。
SELECT name, age from test1 UNION all SELECT name,age from test2;
子查询就是嵌套查询,即SELECT中包含SELECT,如果一条语句中存在两个,或两个以上SELECT,那么就是子查询语句了。
子查询出现的位置:
a. where后,作为被查询的条件的一部分;
b. from后,作临时表;
当子查询出现在where后作为条件时,还可以使用如下关键字:
a. any
b. all
子查询结果集的常见形式:
a. 单行单列(用于条件)
b. 多行单列(用于条件)
c. 多行多列(用于表)
#子查询
#找出工资高于JONES的员工
SELECT * from emp where sal > (select sal from emp where ename='JONES');
#工资高于30号部门所有人的
SELECT * from emp WHERE sal>(SELECT MAX(sal) from emp where deptno=30)
SELECT * from emp WHERE sal> ALL (SELECT sal from emp WHERE deptno=30);
#工资低于30号部门所有人的
SELECT * from emp WHERE sal< ANY (SELECT sal from emp WHERE deptno=30);
#from后面子查询
SELECT ename,job,hiredate FROM (SELECT ename,job,hiredate FROM emp WHERE hiredate>'1987-1-1') AS temp;
-- 导出数据库表
mysqldump -uroot -p 数据库名 > school.sql
-- 导入数据库表
mysql -u root -p
mysql>use 数据库
--然后使用source命令,后面参数为脚本文件(如这里用到的.sql)
mysql>source d:/dbname.sql
1、先备份,右击数据库选择备份—》备份数据库,转储到sql
2、导入,右击选择 “执行SQL脚本”
-- 设定帐号和密码
-- @后面是localhost表示本机可以登录,%是所有人都可以登录,或者可以写ip地址指定某人登录
CREATE USER `zhangsan` IDENTIFIED BY '123';
CREATE USER `zhangsan`@`localhost` IDENTIFIED BY '123';
CREATE USER `zhangsan`@`%` IDENTIFIED BY '123';
CREATE USER `zhangsan`@`10.9.21.188` IDENTIFIED BY '123';
-- all是所有权限,这里可以只写部分列条目
GRANT ALL ON school.* TO `zhangsan`;
REVOKE ALL ON school.* FROM `zhangsan`;
DROP USER `zhangsan`;
分为五张表:
# 创建用户表
create table user(
userId int primary key auto_increment,
username varchar(20) not null,
password varchar(18) not null,
address varchar(100),
phone varchar(11)
);
#一对多的实现
#创建分类表
create table category(
cid varchar(32) PRIMARY KEY ,
cname varchar(100) not null #分类名称
);
# 商品表
CREATE TABLE `products` (
`pid` varchar(32) PRIMARY KEY,
`name` VARCHAR(40) ,
`price` DOUBLE(7,2),
category_id varchar(32),
constraint foreign key(category_id) references category(cid)
);
#多对多的实现
#订单表
create table `orders`(
`oid` varchar(32) PRIMARY KEY ,
`totalprice` double(12,2), #总计
`userId` int,
constraint foreign key(userId) references user(userId) #外键
);
# 订单项表
create table orderitem(
oid varchar(32), #订单id
pid varchar(32), #商品id
num int , #购买商品数量
primary key(oid,pid), #主键
foreign key(oid) references orders(oid),
foreign key(pid) references products(pid)
);
#用户表添加数据
INSERT INTO USER(username,PASSWORD,address,phone) VALUES('张三','123','北京昌平沙河','13812345678');
INSERT INTO USER(username,PASSWORD,address,phone) VALUES('王五','5678','北京海淀','13812345141');
INSERT INTO USER(username,PASSWORD,address,phone) VALUES('赵六','123','北京朝阳','13812340987');
INSERT INTO USER(username,PASSWORD,address,phone) VALUES('田七','123','北京大兴','13812345687');
#给商品表初始化数据
insert into products(pid,name,price,category_id) values('p001','联想',5000,'c001');
insert into products(pid,name,price,category_id) values('p002','海尔',3000,'c001');
insert into products(pid,name,price,category_id) values('p003','雷神',5000,'c001');
insert into products(pid,name,price,category_id) values('p004','JACK JONES',800,'c002');
insert into products(pid,name,price,category_id) values('p005','真维斯',200,'c002');
insert into products(pid,name,price,category_id) values('p006','花花公子',440,'c002');
insert into products(pid,name,price,category_id) values('p007','劲霸',2000,'c002');
insert into products(pid,name,price,category_id) values('p008','香奈儿',800,'c003');
insert into products(pid,name,price,category_id) values('p009','相宜本草',200,'c003');
insert into products(pid,name,price,category_id) values('p010','梅明子',200,null);
#给分类表初始化数据
insert into category values('c001','电器');
insert into category values('c002','服饰');
insert into category values('c003','化妆品');
insert into category values('c004','书籍');
#添加订单
insert into orders values('o6100',18000.50,1);
insert into orders values('o6101',7200.35,1);
insert into orders values('o6102',600.00,2);
insert into orders values('o6103',1300.26,4);
#订单详情表
insert into orderitem values('o6100','p001',1),('o6100','p002',1),('o6101','p003',1);
代码中使用了外键约束,其实可以不用外键约束,直接使用内外连接同样可以达到查询目的。如果使用外键约束,注意数据添加的时候,先添加主表数据,再添加从表数据,否则报错。
select u.userId,u.username,o.totalprice,p.name,p.price,cg.cname
from USER u
LEFT JOIN orders o
ON u.userId = o.userId
LEFT JOIN orderitem oi
ON o.oid = oi.oid
LEFT JOIN products p
ON oi.pid = p.pid
LEFT JOIN category cg
ON p.category_id=cg.cid
-- 第一种方式,使用子查询,这里注意必须是in,因为括号内返回值有很多,DISTINCT为排重关键字
-- 该方式是建立在【外键约束】基础上的,才能利用orders表的结果返回给user表
select * from user where userId in (select DISTINCT userId from orders where totalprice > 800);
-- 第二种方式,使用内连接,不需要建立在外键约束基础上就可以完成
-- 这里使用uer的ID,因为唯一性,排重
select *
from user u
INNER JOIN orders o
ON u.userId=o.userId
where o.totalprice>800
GROUP BY u.userId;
# 创建数据库
CREATE DATABASE db_shopping;
# 创建用户 shop
CREATE USER shop IDENTIFIED BY '123';
# 给shop用户授权
GRANT ALL ON db_shopping.* TO shop;
#使用 shop账户登录创建表结构