多表操作
1.外键
1.1:什么是外键
为了了解外键,我们先创两张表
mysql> USE itcast;
Database changed
创建完成第一张表
mysql> CREATE TABLE class(id INT(11) PRIMARY KEY,name VARCHAR(20))ENGINE=INNODB;
Query OK, 0 rows affected
给第一张表添加数据
mysql> INSERT INTO class(id,name) VALUES(1913,"上午班"),(1923,"下午班");
Query OK, 2 rows affected
Records: 2 Duplicates: 0 Warnings: 0
创建第二张表
mysql> CREATE TABLE student(id INT PRIMARY KEY,name VARCHAR(20),class_id INT(11))ENGINE=INNODB;
Query OK, 0 rows affected
给第二张表添加数据
mysql> INSERT INTO student(id,name,class_id) VALUES (191301,"张三",1913),(192301,"李四",1923),(191302,"王二",1913);
Query OK, 3 rows affected
Records: 3 Duplicates: 0 Warnings: 0
1.2:为表添加外键约束
为表添加外键格式如下:
需要注意的地方如下几点:
MYSQL可以在建立外键时添加ON DELETE 或ON UPDATE 子句来告诉数据库,怎么避免垃圾数据的产生,具体格式如下:
语句中的各参数的具体说明如下:
1.3:删除外键约束
格式如下:
2:操作关联表
2.1:关联关系
MYSQL中数据表的关联关系有三种,具体如下:
1:多对一
是最常见的一种关系,如,员工与部门之间的关系,一个部门可以有多个员工,而一个员工不能属于多个部门,也就是说部门表中的一行在员工表中可以有许多匹配行,但员工表中的一行在部门表中只能有一个匹配行。
2:多对多
3:一对一
3:添加数据
最常见的关联关系为多对一,接下来,为表class和student添加外键约束来建立两个表的关联关系。具体语句如下:
mysql> alter table student add constraint FK_ID foreign key(class_id) REFERENCES class(id);
Query OK, 3 rows affected
Records: 3 Duplicates: 0 Warnings: 0
3.1查看外键约束是否成功添加,查询结果如下:
mysql> SHOW CREATE TABLE student;
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| student | CREATE TABLE `student` (
`id` int(11) NOT NULL,
`name` varchar(20) DEFAULT NULL,
`class_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK_ID` (`class_id`),
CONSTRAINT `FK_ID` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set
我们事先添加过数据了,使用可以不用添加数据,如果要添加数据的话,也可以选择添加几个数据
3.2.1查询1913班有哪些学生,首先要查询1923班id,根据id在student表中查询该班级有哪些学生,具体步骤如下:
mysql> SELECT id FROM class WHERE id=1913;
+------+
| id |
+------+
| 1913 |
+------+
1 row in set
3.2.2:在student表中,查询class_id=1913的学生,即为1913班的学生,具体语句如下:
mysql> SELECT name FROM student WHERE class_id=1913;
+------+
| name |
+------+
| 张三 |
| 王二 |
+------+
2 rows in set
3.3:删除数据
由于class表和student表之间具有关联关系,参照列被参照的值是不能被删除的,所以,在删除1913班的时候,一定要删除该班级的所有学生,然后再删除班级,具体步骤如下:
Query OK, 1 row affected
Query OK, 1 row affected
Empty set
Query OK, 1 row affected
+------+--------+
| id | name |
+------+--------+
| 1923 | 下午班 |
+------+--------+
1 row in set
1451 - Cannot delete or update a parent row: a foreign key constraint fails (`itcast`.`student`, CONSTRAINT `FK_ID` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))
交叉语句格式如下:
接下来通过具体的案例演示如何实现交叉连接,首先创建两个表,department和emlpoyee,具体语句如下:
Query OK, 0 rows affected
Query OK, 0 rows affected
Query OK, 4 rows affected
Records: 4 Duplicates: 0 Warnings: 0
Query OK, 4 rows affected
Records: 4 Duplicates: 0 Warnings: 0
+-----+--------+----+------+-----+-----+
| did | dname | id | name | age | did |
+-----+--------+----+------+-----+-----+
| 1 | 网络部 | 1 | 王红 | 20 | 1 |
| 2 | 媒体部 | 1 | 王红 | 20 | 1 |
| 3 | 研发部 | 1 | 王红 | 20 | 1 |
| 5 | 人事部 | 1 | 王红 | 20 | 1 |
| 1 | 网络部 | 2 | 李强 | 22 | 1 |
| 2 | 媒体部 | 2 | 李强 | 22 | 1 |
| 3 | 研发部 | 2 | 李强 | 22 | 1 |
| 5 | 人事部 | 2 | 李强 | 22 | 1 |
| 1 | 网络部 | 3 | 赵四 | 20 | 2 |
| 2 | 媒体部 | 3 | 赵四 | 20 | 2 |
| 3 | 研发部 | 3 | 赵四 | 20 | 2 |
| 5 | 人事部 | 3 | 赵四 | 20 | 2 |
| 1 | 网络部 | 4 | 郝娟 | 20 | 4 |
| 2 | 媒体部 | 4 | 郝娟 | 20 | 4 |
| 3 | 研发部 | 4 | 郝娟 | 20 | 4 |
| 5 | 人事部 | 4 | 郝娟 | 20 | 4 |
+-----+--------+----+------+-----+-----+
16 rows in set
内连接语法格式
mysql> SELECT employee.name,department.dname FROM department JOIN employee ON department.did=employee.did;
+------+--------+
| name | dname |
+------+--------+
| 王红 | 网络部 |
| 李强 | 网络部 |
| 赵四 | 媒体部 |
+------+--------+
3 rows in set
mysql> SELECT employee.name,department.dname FROM department,employee WHERE department.did=employee.did;
+------+--------+
| name | dname |
+------+--------+
| 王红 | 网络部 |
| 李强 | 网络部 |
| 赵四 | 媒体部 |
+------+--------+
3 rows in set
mysql> SELECT p1.* FROM employee p1 JOIN employee p2 ON p1.did=p2.did WHERE p2.name="王红";
+----+------+-----+-----+
| id | name | age | did |
+----+------+-----+-----+
| 1 | 王红 | 20 | 1 |
| 2 | 李强 | 22 | 1 |
+----+------+-----+-----+
2 rows in set
4.3:外连接
分为左连接和右连接
语法格式如下:
4.3.1:左连接
mysql> SELECT department.did,department.dname,employee.name FROM department LEFT JOIN employee ON department.did=employee.did;
+-----+--------+------+
| did | dname | name |
+-----+--------+------+
| 1 | 网络部 | 王红 |
| 1 | 网络部 | 李强 |
| 2 | 媒体部 | 赵四 |
| 3 | 研发部 | NULL |
| 5 | 人事部 | NULL |
+-----+--------+------+
5 rows in set
4.3.2:右连接
mysql> SELECT department.did,department.dname,employee.name FROM department RIGHT JOIN employee ON department.did=employee.did;
+------+--------+------+
| did | dname | name |
+------+--------+------+
| 1 | 网络部 | 王红 |
| 1 | 网络部 | 李强 |
| 2 | 媒体部 | 赵四 |
| NULL | NULL | 郝娟 |
+------+--------+------+
4 rows in set
4.4:复合条件连接查询
mysql> SELECT employee.name,employee.age,department.dname FROM department JOIN employee ON department.did=employee.did order by age;
+------+-----+--------+
| name | age | dname |
+------+-----+--------+
| 王红 | 20 | 网络部 |
| 赵四 | 20 | 媒体部 |
| 李强 | 22 | 网络部 |
+------+-----+--------+
3 rows in set
5.1带IN关键字的子查询
mysql> SELECT *FROM department WHERE did IN(SELECT did FROM employee WHERE age=20);
+-----+--------+
| did | dname |
+-----+--------+
| 1 | 网络部 |
| 2 | 媒体部 |
+-----+--------+
2 rows in set
mysql> SELECT *FROM department WHERE did NOT IN(SELECT did FROM employee WHERE age=20);
+-----+--------+
| did | dname |
+-----+--------+
| 3 | 研发部 |
| 5 | 人事部 |
+-----+--------+
2 rows in set
5.2:带EXISTS关键字的子查询
mysql> SELECT *FROM department WHERE EXISTS(SELECT did FROM employee WHERE age>21);
+-----+--------+
| did | dname |
+-----+--------+
| 1 | 网络部 |
| 2 | 媒体部 |
| 3 | 研发部 |
| 5 | 人事部 |
+-----+--------+
4 rows in set
5.3:带ANY关键字的子查询
mysql> SELECT *FROM department WHERE did>any(SELECT did FROM employee);
+-----+--------+
| did | dname |
+-----+--------+
| 2 | 媒体部 |
| 3 | 研发部 |
| 5 | 人事部 |
+-----+--------+
3 rows in set
5.4:带ALL关键字的子查询
mysql> SELECT *FROM department WHERE did>all(SELECT did FROM employee);
+-----+--------+
| did | dname |
+-----+--------+
| 5 | 人事部 |
+-----+--------+
1 row in set
5.5:带比较运算符的子查询
mysql> SELECT *FROM department WHERE did=(SELECT did FROM employee where name="赵四");
+-----+--------+
| did | dname |
+-----+--------+
| 2 | 媒体部 |
+-----+--------+
1 row in set