多表关系

在实际项目开发的时候可能设计到多张表,表与表之间存在一定关系,如何设计表之间的关系让系统更加优化,需要考虑到多表之间关系。

  1. 1. 一对一(了解)
  2. * 如:人和身份证
  3. * 分析:一个人只有一个身份证,一个身份证只能对应一个人
  4. 2. 一对多(多对一)
  5. * 如:部门和员工
  6. * 分析:一个部门有多个员工,一个员工只能对应一个部门
  7. 3. 多对多
  8. * 如:学生和课程
  9. * 分析:一个学生可以选择很多门课程,一个课程也可以被很多学生选择

一对一关系

一个人有一个身份证号码,一个身份证号码只对应一个人
20211210141742.png

  1. -- 创建身份证表
  2. CREATE TABLE card(
  3. id INT PRIMARY KEY,
  4. number VARCHAR(18)
  5. );
  6. -- 设置身份证号码唯一
  7. ALTER TABLE card MODIFY number VARCHAR(20) UNIQUE;
  8. INSERT INTO card(id,number) VALUES(1,420923199211090512);
  9. INSERT INTO card(id,number) VALUES(2,420923199310230807);
  10. INSERT INTO card(id,number) VALUES(3,420923199007080908);
  11. -- 创建人员表
  12. CREATE TABLE person(
  13. id INT PRIMARY KEY,
  14. NAME VARCHAR(20),
  15. cid INT
  16. );
  17. -- 给人员表添加外键
  18. ALTER TABLE person ADD CONSTRAINT cid_kf FOREIGN KEY(cid) REFERENCES card(id);
  19. -- 设置外键唯一
  20. ALTER TABLE person MODIFY cid INT UNIQUE;
  21. -- person表中添加数据
  22. INSERT INTO person(id,NAME,cid) VALUES(1,"张三",1);
  23. INSERT INTO person(id,NAME,cid) VALUES(2,"李四",2);
  24. INSERT INTO person(id,NAME,cid) VALUES(3,"王五",3);

一对多关系

一个部门可以有多个员工,一个员工只能对应一个部门
20211210141759.png

  1. -- 创建部门表(主表)
  2. CREATE TABLE department(
  3. id INT PRIMARY KEY,
  4. NAME VARCHAR(20)
  5. );
  6. -- 向部门表中添加数据
  7. INSERT INTO department(id,NAME) VALUES(1,"教研部");
  8. INSERT INTO department(id,NAME) VALUES(2,"学工部");
  9. INSERT INTO department(id,NAME) VALUES(3,"就业部");
  10. SELECT * FROM department;
  11. -- 创建员工表(从表)
  12. CREATE TABLE employee(
  13. id INT PRIMARY KEY AUTO_INCREMENT,
  14. NAME VARCHAR(20) NOT NULL,
  15. age INT,
  16. dep_id INT,
  17. CONSTRAINT emp_depid_fk FOREIGN KEY(dep_id) REFERENCES department(id)
  18. );
  19. -- 向员工表中添加数据
  20. INSERT INTO employee(NAME,age,dep_id) VALUES("张三",18,1);
  21. INSERT INTO employee(NAME,age,dep_id) VALUES("李四",20,2);
  22. INSERT INTO employee(NAME,age,dep_id) VALUES("王五",21,1);
  23. INSERT INTO employee(NAME,age,dep_id) VALUES("赵六",19,3);
  24. INSERT INTO employee(NAME,age,dep_id) VALUES("田七",24,2);
  25. INSERT INTO employee(NAME,age,dep_id) VALUES("周八",23,3);
  26. INSERT INTO employee(NAME,age,dep_id) VALUES("黄九",25,1);
  27. SELECT * FROM employee;

多对多关系

一个学生可以选择很多门课程,一个课程也可以被很多学生选择
20211210141813.png

  1. -- 创建学生表
  2. CREATE TABLE student(
  3. sid INT PRIMARY KEY,
  4. NAME VARCHAR(20),
  5. age INT
  6. );
  7. INSERT INTO student(sid,NAME,age) VALUES(1,"张三",20);
  8. INSERT INTO student(sid,NAME,age) VALUES(2,"李四",19);
  9. INSERT INTO student(sid,NAME,age) VALUES(3,"王五",18);
  10. INSERT INTO student(sid,NAME,age) VALUES(4,"赵六",21);
  11. INSERT INTO student(sid,NAME,age) VALUES(5,"田七",24);
  12. INSERT INTO student(sid,NAME,age) VALUES(6,"周八",23);
  13. -- 创建课程表
  14. CREATE TABLE class(
  15. cid INT PRIMARY KEY,
  16. NAME VARCHAR(20)
  17. );
  18. INSERT INTO class(cid,NAME) VALUES(1,"Java基础");
  19. INSERT INTO class(cid,NAME) VALUES(2,"HTML");
  20. INSERT INTO class(cid,NAME) VALUES(3,"Javascript");
  21. INSERT INTO class(cid,NAME) VALUES(4,"mysql");
  22. -- 创建外键表
  23. CREATE TABLE foreign_table(
  24. sid INT,
  25. cid INT,
  26. CONSTRAINT sid_fk FOREIGN KEY(sid) REFERENCES student(sid), -- 外键sid 关联 student sid主键
  27. CONSTRAINT cid_fk FOREIGN KEY(cid) REFERENCES class(cid) -- 外键cid 关联 class cid主键
  28. );
  29. INSERT INTO foreign_table(sid,cid) VALUES(1,1);
  30. INSERT INTO foreign_table(sid,cid) VALUES(1,2);
  31. INSERT INTO foreign_table(sid,cid) VALUES(1,3);
  32. INSERT INTO foreign_table(sid,cid) VALUES(1,4);
  33. INSERT INTO foreign_table(sid,cid) VALUES(2,1);
  34. INSERT INTO foreign_table(sid,cid) VALUES(2,2);
  35. INSERT INTO foreign_table(sid,cid) VALUES(3,4);
  36. INSERT INTO foreign_table(sid,cid) VALUES(3,1);

多表查询

准备数据

  1. -- 创建db4数据库
  2. CREATE DATABASE db4;
  3. -- 使用db4数据库
  4. USE db4;
  5. -- 创建user
  6. CREATE TABLE USER(
  7. id INT PRIMARY KEY AUTO_INCREMENT, -- 用户id
  8. NAME VARCHAR(20), -- 用户姓名
  9. age INT -- 用户年龄
  10. );
  11. -- 添加数据
  12. INSERT INTO USER VALUES (1,'张三',23);
  13. INSERT INTO USER VALUES (2,'李四',24);
  14. INSERT INTO USER VALUES (3,'王五',25);
  15. INSERT INTO USER VALUES (4,'赵六',26);
  16. -- 订单表
  17. CREATE TABLE orderlist(
  18. id INT PRIMARY KEY AUTO_INCREMENT, -- 订单id
  19. number VARCHAR(30), -- 订单编号
  20. uid INT, -- 外键字段
  21. CONSTRAINT ou_fk1 FOREIGN KEY (uid) REFERENCES USER(id)
  22. );
  23. -- 添加数据
  24. INSERT INTO orderlist VALUES (1,'hm001',1);
  25. INSERT INTO orderlist VALUES (2,'hm002',1);
  26. INSERT INTO orderlist VALUES (3,'hm003',2);
  27. INSERT INTO orderlist VALUES (4,'hm004',2);
  28. INSERT INTO orderlist VALUES (5,'hm005',3);
  29. INSERT INTO orderlist VALUES (6,'hm006',3);
  30. INSERT INTO orderlist VALUES (7,'hm007',NULL);
  31. -- 商品分类表
  32. CREATE TABLE category(
  33. id INT PRIMARY KEY AUTO_INCREMENT, -- 商品分类id
  34. NAME VARCHAR(10) -- 商品分类名称
  35. );
  36. -- 添加数据
  37. INSERT INTO category VALUES (1,'手机数码');
  38. INSERT INTO category VALUES (2,'电脑办公');
  39. INSERT INTO category VALUES (3,'烟酒茶糖');
  40. INSERT INTO category VALUES (4,'鞋靴箱包');
  41. -- 商品表
  42. CREATE TABLE product(
  43. id INT PRIMARY KEY AUTO_INCREMENT, -- 商品id
  44. NAME VARCHAR(30), -- 商品名称
  45. cid INT, -- 外键字段
  46. CONSTRAINT cp_fk1 FOREIGN KEY (cid) REFERENCES category(id)
  47. );
  48. -- 添加数据
  49. INSERT INTO product VALUES (1,'华为手机',1);
  50. INSERT INTO product VALUES (2,'小米手机',1);
  51. INSERT INTO product VALUES (3,'联想电脑',2);
  52. INSERT INTO product VALUES (4,'苹果电脑',2);
  53. INSERT INTO product VALUES (5,'中华香烟',3);
  54. INSERT INTO product VALUES (6,'玉溪香烟',3);
  55. INSERT INTO product VALUES (7,'计生用品',NULL);
  56. -- 中间表
  57. CREATE TABLE us_pro(
  58. upid INT PRIMARY KEY AUTO_INCREMENT, -- 中间表id
  59. uid INT, -- 外键字段。需要和用户表的主键产生关联
  60. pid INT, -- 外键字段。需要和商品表的主键产生关联
  61. CONSTRAINT up_fk1 FOREIGN KEY (uid) REFERENCES USER(id),
  62. CONSTRAINT up_fk2 FOREIGN KEY (pid) REFERENCES product(id)
  63. );
  64. -- 添加数据
  65. INSERT INTO us_pro VALUES (NULL,1,1);
  66. INSERT INTO us_pro VALUES (NULL,1,2);
  67. INSERT INTO us_pro VALUES (NULL,1,3);
  68. INSERT INTO us_pro VALUES (NULL,1,4);
  69. INSERT INTO us_pro VALUES (NULL,1,5);
  70. INSERT INTO us_pro VALUES (NULL,1,6);
  71. INSERT INTO us_pro VALUES (NULL,1,7);
  72. INSERT INTO us_pro VALUES (NULL,2,1);
  73. INSERT INTO us_pro VALUES (NULL,2,2);
  74. INSERT INTO us_pro VALUES (NULL,2,3);
  75. INSERT INTO us_pro VALUES (NULL,2,4);
  76. INSERT INTO us_pro VALUES (NULL,2,5);
  77. INSERT INTO us_pro VALUES (NULL,2,6);
  78. INSERT INTO us_pro VALUES (NULL,2,7);
  79. INSERT INTO us_pro VALUES (NULL,3,1);
  80. INSERT INTO us_pro VALUES (NULL,3,2);
  81. INSERT INTO us_pro VALUES (NULL,3,3);
  82. INSERT INTO us_pro VALUES (NULL,3,4);
  83. INSERT INTO us_pro VALUES (NULL,3,5);
  84. INSERT INTO us_pro VALUES (NULL,3,6);
  85. INSERT INTO us_pro VALUES (NULL,3,7);
  86. INSERT INTO us_pro VALUES (NULL,4,1);
  87. INSERT INTO us_pro VALUES (NULL,4,2);
  88. INSERT INTO us_pro VALUES (NULL,4,3);
  89. INSERT INTO us_pro VALUES (NULL,4,4);
  90. INSERT INTO us_pro VALUES (NULL,4,5);
  91. INSERT INTO us_pro VALUES (NULL,4,6);
  92. INSERT INTO us_pro VALUES (NULL,4,7);

内连接查询

  • 内连接查询语法
    • 内连接查询是查询两个表有交集的部分
  1. -- 显示内连接查询
  2. SELECT 列名 FROM 表名1 [INNER] JOIN 表名2 ON 关联条件;
  3. -- 隐式内连接查询
  4. SELECT 列名 FROM 表名1,表名2 WHERE 关联条件;
  • 内连接查询举例
  1. -- 查询用户信息和对应的订单信息
  2. select *from user inner join orderlist on orderlist.uid = user.id;
  3. -- 查询用户信息和对应的订单信息,起别名
  4. select * from user u inner join orderlist o on o.uid=u.id;
  5. -- 查询用户姓名,年龄。和订单编号
  6. select u.name,u.age,o.number from user u inner join orderlist o on o.uid=u.id;

外连接查询

  • 外连接查询语法
  1. -- 左外连接查询:
  2. 查询原理:查询左表的全部数据,和左右两张表有交集的部分
  3. SELECT 列名 FROM 表名1 LEFT [OUTER] JOIN 表名2 ON 条件;
  4. -- 右外连接查询
  5. 查询原理:查询右表的全部数据,和左右两张表有交集的部分
  6. SELECT 列名 FROM 表名1 RIGHT [OUTER] JOIN 表名2 ON 条件;
  • 外连接查询举例
  1. -- 查询所有用户信息,以及用户对应的订单信息
  2. SELECT
  3. u.*,
  4. o.number
  5. FROM
  6. USER u
  7. LEFT OUTER JOIN
  8. orderlist o
  9. ON
  10. o.uid=u.id;
  11. -- 查询所有订单信息,以及订单所属的用户信息
  12. SELECT
  13. u.*,
  14. o.number
  15. FROM
  16. USER u
  17. RIGHT OUTER JOIN
  18. orderlist o
  19. ON
  20. o.uid=u.id;

子查询

子查询就是利用SQL语句的查询结果,再结合其他SQL条件再次进行查询。

  • 子查询的结果是一行一列

子查询的结果是一行一列,可以将子查询的结果当做某一个字段的值,作为where子句的条件;

  1. select 列名 from 表名 where 列名=(select 列名 from 表名[where 条件]);
  2. -- 查询用户最大的年龄
  3. SELECT MAX(age) FROM USER;
  4. -- 查询年龄最大的用户姓名
  5. select name ,age from user where age=(select max(age) from user);
  • 子查询的结果是多行单列

子查询的结果是多行单列,可以将子查询的结果当做某一个字段的多个值,作为where子句的条件。

  1. 可以作为条件,使用运算符innot in来进行判断。
  2. select 列名 from 表名 where 列名 [not]inselect 列名 表名 [where 条件]);
  3. -- 查询张三和李四的id
  4. select id from user where name in('张三','李四');
  5. -- 查询张三和李四的订单信息
  6. select * from orderlist where uid in (select id from user where name in('张三','李四'));
  • 子查询的结果是多行多列

子查询的结果是多行多列,可以将子查询的结果当做一个虚拟表来看待,并和其他表进行连接查询。

  1. select 列名 from 表名,(select 列名 from 表名[where 条件])[where 条件];
  2. -- 查询订单表中id>4的订单信息
  3. select * from orderlist where id>4;
  4. -- 查询订单表中id大于4的订单信息和所属用户信息
  5. select u.name,o.number from user u ,(select * from orderlist where id>4) o where o.uid=u.id;

自关联查询

  • 准备数据
  1. -- 创建员工表
  2. CREATE TABLE employee(
  3. id INT PRIMARY KEY AUTO_INCREMENT, -- 员工编号
  4. NAME VARCHAR(20), -- 员工姓名
  5. mgr INT, -- 上级编号
  6. salary DOUBLE -- 员工工资
  7. );
  8. -- 添加数据
  9. INSERT INTO employee VALUES (1001,'孙悟空',1005,9000.00),
  10. (1002,'猪八戒',1005,8000.00),
  11. (1003,'沙和尚',1005,8500.00),
  12. (1004,'小白龙',1005,7900.00),
  13. (1005,'唐僧',NULL,15000.00),
  14. (1006,'武松',1009,7600.00),
  15. (1007,'李逵',1009,7400.00),
  16. (1008,'林冲',1009,8100.00),
  17. (1009,'宋江',NULL,16000.00);
  1. -- 查询所有员工的姓名及其直接上级的姓名,没有上级的员工也需要查询
  2. /*
  3. 分析
  4. 员工信息 employee表
  5. 条件:employee.mgr = employee.id
  6. 查询左表的全部数据,和左右两张表有交集部分数据,左外连接
  7. */
  8. SELECT
  9. e1.id,
  10. e1.name,
  11. e1.mgr,
  12. e2.id,
  13. e2.name
  14. FROM
  15. employee e1
  16. LEFT OUTER JOIN
  17. employee e2
  18. ON
  19. e1.mgr = e2.id;

多表查询练习

  1. 查询用户的编号、姓名、年龄。订单编号
  1. /*
  2. 分析:
  3. 查询的表:用户表(user),订单表(orderlist)
  4. 查询的字段:用户编号,姓名,年龄,订单编号
  5. 查询的条件:user.id=orderlist.uid
  6. */
  7. select
  8. u.id,u.name,u.age,o.number
  9. from
  10. user u,orderlist o
  11. where
  12. u.id=o.uid;
  1. 查询所有的用户。用户的编号、姓名、年龄。订单编号
  1. /*
  2. 分析:
  3. 查询的表:用户表(user),订单表(orderlist)。 所有用户,左外连接
  4. 查询的字段:用户编号,姓名,年龄,订单编号
  5. 查询的条件:orderlist.uid = user.id
  6. */
  7. select
  8. u.id,u.name,u.age,o.number
  9. from
  10. user u
  11. left join
  12. orderlist o
  13. on
  14. u.id=o.uid;
  1. 查询所有的订单。用户的编号、姓名、年龄。订单编号
  1. /*
  2. 分析:
  3. 查询的表:用户表(user),订单表(orderlist)。所有订单,忧外连接
  4. 查询的字段:用户的编号、姓名、年龄、订单编号
  5. 查询的条件:orderlist.uid = user.id
  6. */
  7. select
  8. u.id,u.name,u.age,o.number
  9. from
  10. user u
  11. right join
  12. orderlist o
  13. on
  14. o.uid=u.id;
  1. 查询用户年龄大于23岁的信息。显示用户的编号、姓名、年龄。订单编号
  1. /*
  2. 分析:
  3. 查询的表:用户表(user),订单表(orderlist)
  4. 查询的字段:用户的编号、姓名、年龄。订单编号
  5. 查询的条件:user.id=orderlist.uid and user.age>23
  6. */
  7. select
  8. u.id,u.name,u.age,o.number
  9. from
  10. user u,orderlist o
  11. where
  12. u.id=o.uid and u.age>23;
  1. 查询张三和李四用户的信息。显示用户的编号、姓名、年龄。订单编号
  1. /*
  2. 分析:
  3. 查询的表:用户表(user),订单表(orderlist)
  4. 查询的字段:显示用户的编号、姓名、年龄。订单编号
  5. 查询的条件:user.name in ("张三","李四") and user.id=orderlist.uid;
  6. */
  7. select
  8. u.id,u.name,u.age,o.number
  9. from
  10. user u,
  11. orderlist o
  12. where
  13. u.id=o.uid and u.name in ("张三","李四");
  1. 查询商品分类的编号、分类名称。分类下的商品名称
  1. /*
  2. 分析:
  3. 查询的表:商品表(product)、分类表(category)
  4. 查询的字段:商品分类的编号、分类名称、商品名称
  5. 查询的条件:product.cid=category.id
  6. */
  7. select
  8. c.id,c.name,p.name
  9. from
  10. product p,
  11. category c
  12. where
  13. p.cid=c.id;
  1. 查询所有的商品分类。商品分类的编号、分类名称。分类下的商品名称
  1. /*
  2. 分析:
  3. 查询的表:商品表(product)、分类表(category)
  4. 查询的字段:商品分类的编号(id)、分类名称(name)、商品名称(name)
  5. 查询的条件:product.cid=category.id
  6. */
  7. select
  8. c.id,c.name,p.name
  9. from
  10. product p
  11. right join
  12. category c
  13. on
  14. p.cid=c.id;
  1. 查询所有的商品信息。商品分类的编号、分类名称。分类下的商品名称
  1. /*
  2. 分析:
  3. 查询的表:商品表(product)、分类表(category)
  4. 查询的字段:商品分类的编号(id)、分类名称(name)、商品名称(name)
  5. 查询的条件:product.cid=category.id
  6. */
  7. select
  8. c.id,c.name,p.name
  9. from
  10. product p
  11. left join
  12. category c
  13. on
  14. p.cid=c.id;
  1. 查询所有的用户和该用户能查看的所有的商品。显示用户的编号、姓名、年龄。商品名称
  1. /*
  2. 分析:
  3. 查询的表:用户表(user),商品表(product),中间表(us_pro)
  4. 查询的字段:用户的编号、姓名、年龄。商品名称
  5. 查询的条件:user.id=us_pro.uid and product.id=us_pro.pid;
  6. */
  7. select
  8. u.id,u.name,u.age,p.name
  9. from
  10. user u,
  11. product p,
  12. us_pro up
  13. where
  14. u.id=up.uid and p.id=up.pid;
  1. 查询张三和李四这两个用户可以看到的商品。显示用户的编号、姓名、年龄。商品名称
  1. /*
  2. 分析:
  3. 查询的表:用户表(user),商品表(product),中间表(us_pro)
  4. 查询的字段:用户的编号、姓名、年龄。商品名称
  5. 查询的条件:
  6. user.name in ("张三","李四")
  7. and us_pro.uid=user.id;
  8. and us_pro.pid=product.id;
  9. */
  10. select
  11. u.id,u.name,u.age,p.name
  12. from
  13. user u,product p,us_pro up
  14. where
  15. u.name in ("张三","李四") and up.uid=u.id and up.pid=p.id;

视图操作

视图(view)是一种虚拟存在的表,本身并不包含数据。它是作为一个select语法查询到的结果集,以此为基表创建的一张虚拟表。对视图的操作对基表有直接影响。

准备视图数据

  1. -- 创建db5数据库
  2. CREATE DATABASE db5;
  3. -- 使用db5数据库
  4. USE db5;
  5. -- 创建country
  6. CREATE TABLE country(
  7. id INT PRIMARY KEY AUTO_INCREMENT, -- 国家id
  8. NAME VARCHAR(30) -- 国家名称
  9. );
  10. -- 添加数据
  11. INSERT INTO country VALUES (NULL,'中国'),(NULL,'美国'),(NULL,'俄罗斯');
  12. -- 创建city
  13. CREATE TABLE city(
  14. id INT PRIMARY KEY AUTO_INCREMENT, -- 城市id
  15. NAME VARCHAR(30), -- 城市名称
  16. cid INT, -- 外键列。关联country表的主键列id
  17. CONSTRAINT cc_fk1 FOREIGN KEY (cid) REFERENCES country(id) -- 添加外键约束
  18. );
  19. -- 添加数据
  20. INSERT INTO city VALUES (NULL,'北京',1),(NULL,'上海',1),(NULL,'纽约',2),(NULL,'莫斯科',3);

创建视图

  • 创建视图语法
  1. CREATE VIEW 视图名称 [(列名列表)] AS 查询语句;
  • 创建视图举例
  1. -- 创建city_country视图,保存城市和国家的信息(使用指定列名)
  2. CREATE VIEW city_country (city_id,city_name,country_name) AS
  3. SELECT
  4. c1.id,
  5. c1.name,
  6. c2.name
  7. FROM
  8. city c1,
  9. country c2
  10. WHERE
  11. c1.cid=c2.id;

查询视图

  • 查询视图语法
  1. SELECT * FROM 视图名称;
  • 查询视图举例
  1. -- 查询city_country视图
  2. SELECT * FROM city_country;

修改视图数据

  • 修改视图数据语法
  1. UPDATE 视图名称 SET 列名=值 WHERE 条件;
  • 修改视图数据举例
  1. UPDATE city_country SET city_name='深圳' WHERE city_name='北京';

修改视图结构

  • 修改视图结构语法
  1. ALTER VIEW 视图名称 (列名列表) AS 查询语句;
  • 修改视图结构举例
  1. ALTER VIEW city_country (city_id,city_name,NAME) AS
  2. SELECT
  3. c1.id,
  4. c1.name,
  5. c2.name
  6. FROM
  7. city c1,
  8. country c2
  9. WHERE
  10. c1.cid=c2.id;

删除视图

  • 删除视图语法
  1. DROP VIEW [IF EXISTS] 视图名称;
  • 删除视图举例
  1. DROP VIEW IF EXISTS city_country;

备份与还原

命令操作

数据库备份

  1. mysqldump -u用户名 -p 数据库名称 > 备份文件路径
  2. 输入密码:

数据库还原

  1. -- 1. 登录数据
  2. mysql -u root -p
  3. 输入密码:
  4. -- 2. 创建数据库
  5. create databse 数据库名称;
  6. -- 3. 使用数据库
  7. use 数据库名称;
  8. -- 4. 执行文件备份文件
  9. source 备份文件路径

图形操作

备份数据库

20211210141847.png

还原数据库

20211210141857.png