Java学习(十二)

1.外键的约束

#建一张表  id  员工的名字  员工部门  创建时间
mysql> use javadd;
Database changed
mysql> create table employee (
    -> id int primary key auto_increment,
    -> emp_name varchar(32) not null,
    -> dept_name varchar(32) not null,
    -> create_time timestamp default current_timestamp
    -> );
Query OK, 0 rows affected (0.01 sec)
mysql> insert into employee (emp_name, dept_name) values("11", "教学部");
Query OK, 1 row affected (0.02 sec)
​
mysql> insert into employee (emp_name, dept_name) values("22", "教学部");
Query OK, 1 row affected (0.00 sec)
​
mysql> insert into employee (emp_name, dept_name) values("33", "品保部");
Query OK, 1 row affected (0.00 sec)
​
mysql> insert into employee (emp_name, dept_name) values("44", "品保部");
Query OK, 1 row affected (0.00 sec)
​
mysql> insert into employee (emp_name, dept_name) values("55", "技术部");
Query OK, 1 row affected (0.00 sec)
mysql> select * from employee;
+----+----------+-----------+---------------------+
| id | emp_name | dept_name | create_time         |
+----+----------+-----------+---------------------+
|  1 | 11     | 教学部    | 2023-04-10 09:20:42 |
|  2 |22    | 教学部    | 2023-04-10 09:20:51 |
|  3 |33     | 品保部    | 2023-04-10 09:21:36 |
|  4 | 44    | 品保部    | 2023-04-10 09:21:44 |
|  5 | 55     | 技术部    | 2023-04-10 09:22:20 |
+----+----------+-----------+---------------------+
#这种设计表是有问题的,部门的数据是冗余的,这样是不好的,必须拆开两个表,一个员工表  一个部门表
​

#
mysql> create table dept (
    -> dept_id int primary key auto_increment,
    -> dept_name varchar(32)
    -> );
    
Query OK, 0 rows affected (0.01 sec)
mysql> create table emp (
    -> emp_id int primary key auto_increment,
    -> emp_name varchar(32) ,
    -> dept_id int,
    -> reg_time timestamp default current_timestamp
    -> );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into  dept(dept_name) values("教学部");
Query OK, 1 row affected (0.00 sec)
​
mysql> insert into  dept(dept_name) values("品保部");
Query OK, 1 row affected (0.01 sec)
​
mysql> insert into  dept(dept_name) values("技术部");
Query OK, 1 row affected (0.00 sec)
mysql> insert into emp (emp_name, dept_id) values ("lag", 1);
Query OK, 1 row affected (0.01 sec)
​
mysql> insert into emp (emp_name, dept_id) values ("sl", 1);
Query OK, 1 row affected (0.00 sec)
​
mysql> insert into emp (emp_name, dept_id) values ("eb", 2);
Query OK, 1 row affected (0.00 sec)
​
mysql> insert into emp (emp_name, dept_id) values ("ej", 2);
Query OK, 1 row affected (0.00 sec)
​
mysql> insert into emp (emp_name, dept_id) values ("js", 3);
Query OK, 1 row affected (0.00 sec)
mysql> select * from dept;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
|       1 | 教学部    |
|       2 | 品保部    |
|       3 | 技术部    |
+---------+-----------+
3 rows in set (0.00 sec)
​
mysql> select * from emp;
+--------+----------+---------+---------------------+
| emp_id | emp_name | dept_id | reg_time            |
+--------+----------+---------+---------------------+
|      1 | laoxing  |       1 | 2023-04-10 09:39:49 |
|      2 | sl       |       1 | 2023-04-10 09:39:55 |
|      3 | eb       |       2 | 2023-04-10 09:40:09 |
|      4 | ej       |       2 | 2023-04-10 09:40:13 |
|      5 | js       |       3 | 2023-04-10 09:40:19 |
+--------+----------+---------+---------------------+
​
#插入一个数据:  要求插入员工数据,但是需要写dept_id  写一个没有的部门id  8  能插入成功不?
#可以插入成功不。需求开发场景不合适
mysql> insert into emp (emp_name, dept_id) values("gd", 8);
Query OK, 1 row affected (0.00 sec)
#删除一个部门的话:   如果我将一个部门删除技术部,真实的需求的时候  删除一个部门,部门下面所对应也要全部删除
mysql> delete from dept where dept_id = 3;
Query OK, 1 row affected (0.00 sec)
​
mysql> select * from emp;
+--------+----------+---------+---------------------+
| emp_id | emp_name | dept_id | reg_time            |
+--------+----------+---------+---------------------+
|      1 | lng  |       1 | 2023-04-10 09:39:49 |
|      2 | sl       |       1 | 2023-04-10 09:39:55 |
|      3 | eb       |       2 | 2023-04-10 09:40:09 |
|      4 | ej       |       2 | 2023-04-10 09:40:13 |
|      5 | js       |       3 | 2023-04-10 09:40:19 |
|      6 | gd       |       8 | 2023-04-10 09:42:13 |
+--------+----------+---------+---------------------+
​
#添加员工的时候,随便可以添加,尽管这个部门不存在,删除一个部门。部门下面的员工也还在。这些都是实际开发中不合理的,造成不合理的原因,这两张表是没有关系的!!!
#咋让两张表产生关系呢? 使用外键

mysql> create table emp (
    -> emp_id int primary key auto_increment,
    -> emp_name varchar(32) ,
    -> dept_id int,
    -> reg_time timestamp default current_timestamp,
    #constraint  约束的意思
    #fk_emp_dept  外键的名字 随意起
    #foreign key(dept_id)  外键 使用本表中的一个字段作为外键去和别的表产生关系
    #references 关联 引用的意思,去关联主表里面的某一个字段(外键所在的表叫副表)
    
    -> constraint fk_emp_dept foreign key(dept_id)  references dept(dept_id)
    -> );
Query OK, 0 rows affected (0.09 sec)
mysql> drop table emp;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from dept;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
|       1 | 教学部    |
|       2 | 品保部    |
+---------+-----------+
#插入数据  
mysql> insert into emp (emp_name, dept_id) values("lx", 1);
Query OK, 1 row affected (0.01 sec)
​
mysql> insert into emp (emp_name, dept_id) values("sl", 1);
Query OK, 1 row affected (0.00 sec)
#插入了一个不存在的部门  的时候结果报错课
mysql> insert into emp (emp_name, dept_id) values("gd", 4);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`java2304`.`emp`, CONSTRAINT `fk_emp_dept` FOREIGN KEY (`dept_id`) REFERENCES `dept` (`dept_id`))
​
#删除数据  删除教学部
mysql> delete from dept where dept_id = 1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`java2304`.`emp`, CONSTRAINT `fk_emp_dept` FOREIGN KEY (`dept_id`) REFERENCES `dept` (`dept_id`))
​
#修改数据
mysql> update dept set dept_id  = 5 where dept_id = 1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`java2304`.`emp`, CONSTRAINT `fk_emp_dept` FOREIGN KEY (`dept_id`) REFERENCES `dept` (`dept_id`))
mysql>
​
#加上外键约束以后,增删改  有的时候会报错
#主表(部门表)   副表(员工表)
#增加的时候: 先看主表  然后增加副表
#删除的时候: 先删除副表 再删除主表
#修改的时候:  先修改副表 再修改主表
#这样才能不报错
#太麻烦了,还得记这些
#级联操作!!!  级联修改 和级联删除
mysql> drop table emp;
Query OK, 0 rows affected (0.01 sec)
​
mysql> create table emp (
    -> emp_id int primary key auto_increment,
    -> emp_name varchar(32) ,
    -> dept_id int,
    -> reg_time timestamp default current_timestamp,
    -> constraint fk_emp_dept foreign key(dept_id)  references dept(dept_id)
    #加的两个状态
    -> on delete cascade
    -> on update cascade
    -> );
Query OK, 0 rows affected (0.01 sec)
    mysql> delete from dept where dept_id  =1;
Query OK, 1 row affected (0.01 sec)
​
mysql> select * from emp;
+--------+----------+---------+---------------------+
| emp_id | emp_name | dept_id | reg_time            |
+--------+----------+---------+---------------------+
|      3 | xueke    |       2 | 2023-04-10 10:46:04 |
|      4 | erbei    |       2 | 2023-04-10 10:46:08 |
|      5 | erjia    |       2 | 2023-04-10 10:46:11 |
+--------+----------+---------+---------------------+
#修改:
mysql> update dept set dept_id = 4 where dept_id  =2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
​
mysql> select * from emp;
+--------+----------+---------+---------------------+
| emp_id | emp_name | dept_id | reg_time            |
+--------+----------+---------+---------------------+
|      3 | xueke    |       4 | 2023-04-10 10:46:04 |
|      4 | erbei    |       4 | 2023-04-10 10:46:08 |
|      5 | erjia    |       4 | 2023-04-10 10:46:11 |
+--------+----------+---------+---------------------+
​
真实开发的时候,特别是外键约束的表的时候,要加上级联删除和级联修改
mysql> create table emp (
    -> emp_id int primary key auto_increment,
    -> emp_name varchar(32) ,
    -> dept_id int,
    -> reg_time timestamp default current_timestamp,
    -> constraint fk_emp_dept foreign key(dept_id)  references dept(dept_id)
    #加的两个状态
    -> on delete cascade
    -> on update cascade
    -> );
    
    

2.联表查询【重点】

2.1常规的联表查询

#增删改和外键约束有关     查询没有关系的
mysql> select * from dept;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
|       4 | 品保部    |
|       5 | 教学部    |
|       6 | 技术部    |
+---------+-----------+
3 rows in set (0.00 sec)
​
mysql> select * from emp;
+--------+----------+---------+---------------------+
| emp_id | emp_name | dept_id | reg_time            |
+--------+----------+---------+---------------------+
|      3 | xue    |       4 | 2023-04-10 10:46:04 |
|      4 | erbei    |       4 | 2023-04-10 10:46:08 |
|      5 | erjia    |       4 | 2023-04-10 10:46:11 |
|      6 | 东哥     |       5 | 2023-04-10 11:00:59 |
|      7 | 飞哥     |       5 | 2023-04-10 11:01:11 |
+--------+----------+---------+---------------------+
#联表查询  查看 erbei 属于哪个部门
​
​
select emp.emp_name, dept.dept_name  # 查什么
from emp, dept  #从哪查
where emp.dept_id = dept.dept_id and emp.emp_name = "erbei" #查询的条件
mysql> select *
    -> from emp, dept
    -> where emp.dept_id = dept.dept_id;
+--------+----------+---------+---------------------+---------+-----------+
| emp_id | emp_name | dept_id | reg_time            | dept_id | dept_name |
+--------+----------+---------+---------------------+---------+-----------+
|      3 | xueke    |       4 | 2023-04-10 10:46:04 |       4 | 品保部    |
|      4 | e3    |       4 | 2023-04-10 10:46:08 |       4 | 品保部    |
|      5 | erjia    |       4 | 2023-04-10 10:46:11 |       4 | 品保部    |
|      6 | 东哥     |       5 | 2023-04-10 11:00:59 |       5 | 教学部    |
|      7 | 飞哥     |       5 | 2023-04-10 11:01:11 |       5 | 教学部    |
+--------+----------+---------+---------------------+---------+-----------+
5 rows in set (0.01 sec)
​
mysql> select *
    -> from emp, dept
    -> where emp.dept_id = dept.dept_id and emp.emp_name = "erbei";
+--------+----------+---------+---------------------+---------+-----------+
| emp_id | emp_name | dept_id | reg_time            | dept_id | dept_name |
+--------+----------+---------+---------------------+---------+-----------+
|      4 | erbei    |       4 | 2023-04-10 10:46:08 |       4 | 品保部    |
+--------+----------+---------+---------------------+---------+-----------+
1 row in set (0.00 sec)
​
mysql> select emp.emp_name, dept.dept_name
    -> from emp, dept
    -> where emp.dept_id = dept.dept_id and emp.emp_name = "erbei";
+----------+-----------+
| emp_name | dept_name |
+----------+-----------+
| erbei    | 品保部    |
+----------+-----------+
1 row in set (0.00 sec)
​
​
#对表起表名
select e.emp_name, d.dept_name
from emp e, dept d
where e.dept_id = d.dept_id and e.emp_name = "erbei";
​
​
mysql> select e.emp_name as "员工名字", d.dept_name  as "部门名字"
    -> from emp e, dept d
    -> where e.dept_id = d.dept_id and e.emp_name = "erbei";
+----------+-----------+
| emp_name | dept_name |
+----------+-----------+
| erbei    | 品保部    |
+----------+-----------+
1 row in set (0.00 sec)
​
#找出教学部有有哪些人
select d.dept_name, e.emp_name
from dept d, emp e
where d.dept_id = e.dept_id  and d.dept_name= "教学部";
mysql> select d.dept_name, e.emp_name
    -> from dept d, emp e
    -> where d.dept_id = e.dept_id  and d.dept_name= "教学部";
+-----------+----------+
| dept_name | emp_name |
+-----------+----------+
| 教学部    | 东哥     |
| 教学部    | 飞哥     |
+-----------+----------+
2 rows in set (0.00 sec)

2.2内连接和外连接

也是牵涉多表联查,只不过换了一种写法而已

2.2.1内连接

SELECT column_name(s)  查什么
FROM table_name1    从哪查  表1
INNER JOIN table_name2   关联 表2
ON table_name1.column_name=table_name2.column_name

注释:INNER JOIN 与 JOIN 是相同的。

mysql> select * from dept;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
|       4 | 品保部    |
|       5 | 教学部    |
|       6 | 技术部    |
+---------+-----------+
3 rows in set (0.00 sec)
​
mysql> select * from emp;
+--------+----------+---------+---------------------+
| emp_id | emp_name | dept_id | reg_time            |
+--------+----------+---------+---------------------+
|      3 | xueke    |       4 | 2023-04-10 10:46:04 |
|      4 | erbei    |       4 | 2023-04-10 10:46:08 |
|      5 | erjia    |       4 | 2023-04-10 10:46:11 |
|      6 | 东哥     |       5 | 2023-04-10 11:00:59 |
|      7 | 飞哥     |       5 | 2023-04-10 11:01:11 |
+--------+----------+---------+---------------------+
​
select e.emp_name, d.dept_name 
from emp  e
inner join dept d
on  e.dept_id = d.dept_id
where e.emp_name = "erjia";
mysql> select *
    -> from emp
    -> inner join dept
    -> on  emp.dept_id = dept.dept_id
    -> where emp.emp_name = "erjia";
+--------+----------+---------+---------------------+---------+-----------+
| emp_id | emp_name | dept_id | reg_time            | dept_id | dept_name |
+--------+----------+---------+---------------------+---------+-----------+
|      5 | erjia    |       4 | 2023-04-10 10:46:11 |       4 | 品保部    |
+--------+----------+---------+---------------------+---------+-----------+
1 row in set (0.01 sec)
​
mysql> select emp.emp_name, dept.dept_name
    -> from emp
    -> inner join dept
    -> on  emp.dept_id = dept.dept_id
    -> where emp.emp_name = "erjia";
+----------+-----------+
| emp_name | dept_name |
+----------+-----------+
| erjia    | 品保部    |
+----------+-----------+
1 row in set (0.00 sec)
​
mysql> select e.emp_name, d.dept_name  #查什么
    -> from emp  e  #从第一个表
    -> inner join dept d #关联第二表
    -> on  e.dept_id = d.dept_id  #表之间的连接的字段
    -> where e.emp_name = "erjia"; #条件
+----------+-----------+
| emp_name | dept_name |
+----------+-----------+
| erjia    | 品保部    |
+----------+-----------+
1 row in set (0.00 sec)
#查 品保部的人
mysql> select d.dept_name, e.emp_name
    -> from dept d
    -> join emp e
    -> on d.dept_id = e.dept_id
    -> where d.dept_name= "品保部";
+-----------+----------+
| dept_name | emp_name |
+-----------+----------+
| 品保部    | xueke    |
| 品保部    | erbei    |
| 品保部    | erjia    |
+-----------+----------+
​
​

2.2.2外连接【开发中用的很少】

#左外连接 和右外连接
#LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。
mysql> select *
    -> from dept d
    -> left outer join emp e
    -> on d.dept_id = e.dept_id;
+---------+-----------+--------+----------+---------+---------------------+
| dept_id | dept_name | emp_id | emp_name | dept_id | reg_time            |
+---------+-----------+--------+----------+---------+---------------------+
|       4 | 品保部    |      3 | xueke    |       4 | 2023-04-10 10:46:04 |
|       4 | 品保部    |      4 | erbei    |       4 | 2023-04-10 10:46:08 |
|       4 | 品保部    |      5 | erjia    |       4 | 2023-04-10 10:46:11 |
|       5 | 教学部    |      6 | 东哥     |       5 | 2023-04-10 11:00:59 |
|       5 | 教学部    |      7 | 飞哥     |       5 | 2023-04-10 11:01:11 |
|       6 | 技术部    |   NULL | NULL     |    NULL | NULL                |
|       7 | 总经办    |   NULL | NULL     |    NULL | NULL                |
+---------+-----------+--------+----------+---------+---------------------+
#RIGHT JOIN 关键字会右表 (table_name2) 那里返回所有的行,即使在左表 (table_name1) 中没有匹配的行。
​
mysql> select *
    -> from emp e
    -> right outer join dept d
    -> on e.dept_id = d.dept_id;
+--------+----------+---------+---------------------+---------+-----------+
| emp_id | emp_name | dept_id | reg_time            | dept_id | dept_name |
+--------+----------+---------+---------------------+---------+-----------+
|      3 | xueke    |       4 | 2023-04-10 10:46:04 |       4 | 品保部    |
|      4 | erbei    |       4 | 2023-04-10 10:46:08 |       4 | 品保部    |
|      5 | erjia    |       4 | 2023-04-10 10:46:11 |       4 | 品保部    |
|      6 | 东哥     |       5 | 2023-04-10 11:00:59 |       5 | 教学部    |
|      7 | 飞哥     |       5 | 2023-04-10 11:01:11 |       5 | 教学部    |
|   NULL | NULL     |    NULL | NULL                |       6 | 技术部    |
|   NULL | NULL     |    NULL | NULL                |       7 | 总经办    |
+--------+----------+---------+---------------------+---------+-----------+
7 rows in set (0.00 sec)

上午的内容

1.外键约束
    在创建表的时候,本表中的一个字段h会作为另外一个表的的外键 让两个表有关系
    constraint  外键名字(自定义的)  foreign key(本表字段) references 另外一张表(字段)
    on delete cascade  on update cascade;
    
2.多表联查
    常规写法:   select * from emp, dept where emp.dept_id = dept.dept_id 
    内连接:   select * from emp inner join dept on emp.dept_id = dept.dept_id
    左外连接: select * from emp left outer join dept on emp.dept_id = dept.dept_id
    右外连接
    

3.开发中如何使用多表联查

3.1一对多或者多对一 的查询

mysql> create table teacher (
    -> t_id int primary key auto_increment,
    -> t_name varchar(32)
    -> );
Query OK, 0 rows affected (0.02 sec)
​
mysql> create table student(
    -> s_id int primary key auto_increment,
    -> s_name varchar(32),
    -> teacher_id int
    -> );
Query OK, 0 rows affected (0.01 sec)
​
​
#老邢带学生有哪些?
select teacher.t_name, student.s_name
from teacher, student 
where teacher.t_id = student.teacher_id and teacher.t_name = "老邢";
mysql> select teacher.t_name, student.s_name
    -> from teacher, student
    -> where teacher.t_id = student.teacher_id and teacher.t_name = "老邢";
+--------+--------+
| t_name | s_name |
+--------+--------+
| 1   | 张三   |
| 1   | 王五   |
| 1   | 老八   |
+--------+--------+
4 rows in set (0.00 sec)
​
mysql> select t.t_name,s.s_name
    -> from teacher t
    -> inner join student s
    -> on t.t_id = s.teacher_id
    -> where t.t_name = "老邢";
+--------+--------+
| t_name | s_name |
+--------+--------+
|1   | 张三   |
| 1   | 李四   |
| 1   | 王五   |
| 1   | 老八   |
+--------+--------+
4 rows in set (0.00 sec)

3.2多对多的场景

场景:
    学生和课程的关系   学生要选课   课要被选
    一个学生对应着多门的课程
    一个课程可以被多个学生选择
    

mysql> create table stu (
    -> s_id int primary key auto_increment,
    -> s_name varchar(32)
    -> );
Query OK, 0 rows affected (0.01 sec)
​
mysql> create table course (
    -> c_id int primary key auto_increment,
    -> c_name varchar(32)
    -> );
Query OK, 0 rows affected (0.01 sec)
​
mysql> create table stu_course (
    -> id int primary key auto_increment,
    -> s_id int,
    -> c_id int
    -> );
Query OK, 0 rows affected (0.08 sec)
​
​
#有三张表就意味着着必须使用三表联查
#需求:  司马懿选了哪些课程
select stu.s_name, course.c_name
from stu, stu_course, course
where stu.s_id = stu_course.s_id and stu_course.c_id = course.c_id and stu.s_name = "司马懿";
mysql> select *
    -> from stu, stu_course, course
    -> where stu.s_id = stu_course.s_id and stu_course.c_id = course.c_id and stu.s_name = "司马懿";

​
mysql> select stu.s_name, course.c_name
    -> from stu, stu_course, course
    -> where stu.s_id = stu_course.s_id and stu_course.c_id = course.c_id and stu.s_name = "司马懿";
)
​
#内连接的写法
select s.s_name, c.c_name
from stu s
inner join stu_course sc
on s.s_id  = sc.s_id
inner join course c
on sc.c_id = c.c_id
where s.s_name = "司马懿";
mysql> select s.s_name, c.c_name
    -> from stu s
    -> inner join stu_course sc
    -> on s.s_id  = sc.s_id
    -> inner join course c
    -> on sc.c_id = c.c_id
    -> where s.s_name = "司马懿";

​
select c.c_name, s.s_name
from course c
inner join stu_course sc
on c.c_id = sc.c_id
inner join stu s
on sc.s_id = s.s_id
where c.c_name = "挖掘机";
mysql> select c.c_name, s.s_name
    -> from course c
    -> inner join stu_course sc
    -> on c.c_id = sc.c_id
    -> inner join stu s
    -> on sc.s_id = s.s_id
    -> where c.c_name = "挖掘机";
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值