表之间的关系

一对一、一对多

不需要创建中间表

CREATE TABLE person(id INT PRIMARY KEY auto_increment,name VARCHAR(50));
CREATE TABLE car(name VARCHAR(20),color VARCHAR(20),pid INT,# pid 外键 关联person的id
		CONSTRAINT c_p_fk FOREIGN KEY(pid) REFERENCES person(id) #添加约束
);

hibernatetemplate多表查询_数据库


hibernatetemplate多表查询_数据_02

多对多关系创建

需要创建中间表——分别关联两个表
比如学生选课

CREATE TABLE teacher(tid INT PRIMARY KEY,name VARCHAR(50));
CREATE TABLE student(sid INT PRIMARY KEY,name VARCHAR(50));
CREATE TABLE tea_stu_relation(tid INT,sid INT);
-- 一个表可添加多个外键
-- ADD 添加约束
ALTER TABLE tea_stu_relation ADD CONSTRAINT FOREIGN KEY(tid) REFERENCES teacher(tid);
ALTER TABLE tea_stu_relation ADD CONSTRAINT FOREIGN KEY(sid) REFERENCES student(sid);

hibernatetemplate多表查询_sql_03


hibernatetemplate多表查询_数据库_04


hibernatetemplate多表查询_数据_05

拆分表

在上例中使用了三个表而非一整个表。

  • 拆分表的目的:避免大量冗余数据的出现。

多表查询

合并结果集

  • 把两个select语句的查询结果合并到一起
  • 两种方式:UNION-合并时去除重复记录;UNION ALL-合并时不去除重复记录。
  • 格式:
SELECT * FROM 表1 UNION SELECT * FROM 表2;
SELECT * FROM 表1 UNION ALL SELECT * FROM 表2;
  • 示例:
CREATE TABLE A(name VARCHAR('a',10),score INT);
CREATE TABLE B(name VARCHAR('b',10),score INT);
-- 插入数据
INSERT INTO A VALUES('a',10),('b',20),('c',30);
INSERT INTO B VALUES('a',10),('b',20),('c',40);
SELECT * FROM A UNION SELECT * FROM B;

hibernatetemplate多表查询_数据_06

SELECT * FROM A UNION ALL SELECT * FROM B;

hibernatetemplate多表查询_数据_07

  • 注意:被合并的两个结果的列数、列数据类型必须相同。

连接查询

  • 连接查询也叫跨表查询,需要关联多个表进行查询。
  • 笛卡尔集:假设集合A={a, b},集合B={0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。
  • 同时查询两个,结果为笛卡尔集。
SELECT * FROM student,teacher;

hibernatetemplate多表查询_外键_08

去除笛卡尔集

查询时给表起别名。

SELECT * FROM student stu,teacher tea;

多表查询,如何保证数据正确

  1. 查询时主键外键要保持一致;
SELECT * FROM student stu,score sco WHERE stu.id=sco.sid;
-- 这里不起别名也行
  1. 主表当中的数据参照子表当中的数据;
  2. 原理:相等的留下,不相等的全不要。

根据连接方式分类

内连接
等值连接

两个表同时出现的id值才显示。

SELECT * FROM student stu INNER JOIN score sco ON stu.id=sco.sid;

与多表联查约束主外键一样,只是写法不同。
ON后只写主外键。
如果还有其他条件,直接用where写。
多表联查后面还有条件就直接写and。

多表连接
-- 创建科目表
CREATE TABLE course(cid INT PRIMARY KEY,name VARCHAR(50));
-- 多表连接-学生、成绩、科目
--99查询->每多一个条件就多写一个AND
SELECT st.`name`,sc.score,c.name FROM student st,score sc,score c WHERE st.id=sc.sid AND sc.sid=c.;
非等值连接

查询后的限制条件不再是‘=’,仅此而已,原理都相同。

自连接(不赘述,不太重要)
外连接
左外连接

查询结果:两表中条件相同的数据+左边表中的独有数据=左边全部数据+右边满足条件的数据

SELECT * FROM student st LEFT JOIN score sc ON st.id=sc.sid;
右外连接

跟左连接相反

自然连接
  • 连接查询会产生无用的笛卡尔集,我们通常使用上述的主外键关系等式去除笛卡尔集。
  • 自然连接无需给出主外键等式,会自动生成。
  • 要求:两张表中的列名称和列数据类型必须一致,会去出相同的列。
-- 先建表
CREATE TABLE student(id INT,name VARCHAR(20));
CREATE TABLE score(sid INT,score INT);

不去除笛卡尔集,直接连

CREATE * FROM sutdent,score;

hibernatetemplate多表查询_外键_09

去除笛卡尔集

-- 普通连接 两种方法 二选一
SELECT * FROM student,score WHERE student.id=score.sid;
SELECT * FROM student JOIN score ON student.id=score.sid;

hibernatetemplate多表查询_外键_10

-- 自然连接
SELECT * FROM student NATURAL JOIN score;

hibernatetemplate多表查询_数据_11


没达到自然连接的效果,需要修改表结构——把student中的id改成sid重试即可。

hibernatetemplate多表查询_外键_12


hibernatetemplate多表查询_数据库_13


ok了

子查询

  • 一个select语句中包含另一个或两个以上完整的select语句。
  • 使用情况:一、where后把select查询出的结果当作另一个select的值;二、from后,把查询出的结果当作一个新表。

where 条件查询

-- 查询与项羽同一部门的员工 编号20
SELECT ename,deptno FROM emp 
WHERE deptno=(SELECT deptno FROM emp WHERE ename='项羽');

from表形式

SELECT ename FROM 
(SELECT ename,salary,deptno FROM emp WHERE deptno=30) s #别名在这种场合比较实用
WHERE s.salary>2000;

自连接

表连接表本身的不同字段

SELECT * FROM emp e1,emp e2
WHERE e1.mgr=e2.empno;