手机扫码查看
2020Javaweb教程之MySQL约束和多表查询
第一节 数据完整性
作用:保证用户输入的数据保存到数据库中是正确的。
确保数据的完整性 = 在创建表时给表中添加约束
完整性的分类:
实体完整性: 行
域完整性: 列
引用完整性: 学生表(学号 ,姓名) 成绩表( 学号,科目,成绩) 科目表(科目编号,科目名称)
1.1 实体完整性约束
实体:即表中的一行(一条记录)代表一个实体(entity)
实体完整性的作用:标识每一行数据不重复。 实体唯一
约束类型:
主键约束(primary key)
唯一约束(unique)
自动增长列(auto_increment)
主键约束(primary key)
注:每个表中要有一个主键。
特点:数据唯一,且不能为null
唯一约束(unique)
特点:数据不能重复。可以为null
自动增长列(auto_increment)
sqlserver数据库 (identity) oracle数据库( sequence)
自动增长不能单独使用,一般需要和主键配合。
给主键添加自动增长的数值,列只能是数值类型
CREATE TABLE users(
id INT AUTO_INCREMENT PRIMARY KEY,#自动增长且主键
username VARCHAR(20) NOT NULL,
identity VARCHAR(18) UNIQUE NOT NULL,#唯一约束不可重复
mobile VARCHAR(11) NOT NULL
)CHARSET=utf8
域完整性约束
域完整性约束的作用:限制此单元格的数据正确,不对其它单元格起作用,域代表当前单元格.
域完整性约束:数据类型、非空约束(not null)、默认值约束(default)
check约束(mysql不支持)check(sex=’男’or sex=’女’)
CREATE TABLE users(
username VARCHAR(20) NOT NULL,#非空约束
sex VARCHAR(2) DEFAULT ‘男’#默认值约束
)CHARSET=utf8
引用完整性约束
外键约束:FOREIGN KEY
外键列的数据类型一定要与主键的类型一致
CREATE TABLE stu(#学生表
sid INT PRIMARY KEY AUTO_INCREMENT,
sname VARCHAR(5) NOT NULL,
sex VARCHAR(2) DEFAULT ‘男’
)CHARSET=utf8;
CREATE TABLE score(#学生成绩表
id INT PRIMARY KEY AUTO_INCREMENT,
score DOUBLE(5,2) NOT NULL,
CONSTRAINT fk_score_sid FOREIGN KEY(id) REFERENCES stu(sid)
)
INSERT INTO stu(sname,sex)VALUES(‘张三’,’女’)#添加学生
INSERT INTO score(score)VALUES(120.55)#添加成绩
SELECT*FROM stu
SELECT*FROM score
多表查询
多表约束:外键约束。
多表的关系
一对多关系:客户和订单,分类和商品,部门和员工
一对多建表原则:在多的一方创建一个字段,字段作为外键指向一方的主键.
多对多关系
学生和课程:
多对多关系建表原则:需要创建第三张表,中间表中至少两个字段,这两个字段分别作为外键指向各自一方的主键.
一对一关系
一个丈夫对应一个妻子
一个员工对应一个简历
在实际的开发中应用不多.因为一对一可以创建成一张表.
两种建表原则:
唯一外键对应:在多的一方创建一个外键指向一的一方的主键,将外键设置为unique和非空.
主键对应:让一对一的双方的主键进行建立关系. 唯一 非空
多表查询
多表查询有如下几种:
1 合并结果集;UNION 、 UNION ALL
2 连接查询
内连接 INNER JOIN ON
外连接 OUTER JOIN ON
左外连接 LEFT OUTER JOIN
右外连接 RIGHT OUTER JOIN
子查询
2.2.1 合并结果集
作用:合并结果集就是把两个select语句的查询结果合并到一起!
注意:被合并的两个结果:列数必须相同,列类型可以不同。
合并结果集有两种方式:
UNION:去除重复记录,例如:SELECT*FROM emp UNION SELECT*FROM empno
UNION ALL:不去除重复记录,例如:SELECT*FROM emp UNION ALL SELECT*FROM empno
连接查询
连接查询就是求出多个表的乘积,例如t1连接t2,那么查询出的结果就是t1*t2。
连接查询会产生笛卡尔积,假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以扩展到多个集合的情况。
实例:
emp表
CREATE TABLE emp(
id INT AUTO_INCREMENT PRIMARY KEY,
ename VARCHAR(20) NOT NULL,
sex VARCHAR(2) NOT NULL,
identity VARCHAR(18) UNIQUE NOT NULL
)CHARSET=utf8
dept表
CREATE TABLE dept(
deptno INT,
dname VARCHAR(20),
loc VARCHAR(5)
)CHARSET=utf8
执行sql语句:SELECT*FROM emp,dept
使用主外键关系做为条件来去除无用信息
SELECT*FROM emp,dept WHERE emp.`depno`=dept.`deptno`
如果不需要那么多列,可以筛选指定列
SELECT emp.`id`,emp.`ename`,emp.`salary`,dept.`dname` FROM emp,dept WHERE emp.`depno`=dept.`deptno`
内连接
上面连接语句就是内连接,但不是SQL标准中的查询方式,是mysql扩展的功能
SQL标准的内连接为:
SELECT*FROM emp INNER JOIN dept ON emp.`depno`=dept.`deptno`
注意:on后面 主外键关系
外连接
包括左外连接和右外连接,外连接的特点:查询出的结果存在不满足条件的可能。
a.左外连接:以左表为主表,右表是从表
SELECT*FROM emp LEFT JOIN dept ON emp.`depno`=dept.`deptno`
左连接是先查询出左表(即以左表为主),然后查询右表,左表中满足条件和不满足条件都显示出来,右边不满足条件的显示NULL。
外连接
右连接就是先把右表中所有记录都查询出来,然后左表满足条件的显示,不满足显示NULL。例如在dept表中的40部门并不存在员工,但在右连接中,如果dept表为右表,那么还是会查出40部门,但相应的员工信息为NULL。
SELECT*FROM emp RIGHT OUTER JOIN dept ON emp.`depno`=dept.`deptno`
连接查询总结:
连接不限于两张表,连接查询也可以是三张、四张,甚至N张表的连接查询。通常连接查询不可能需要整个笛卡尔积,而只是需要其中一部分,那么这时就需要使用条件来去除不需要的记录。这个条件大多数情况下都是使用主外键关系去除。
子查询
一个select语句中包含另一个完整的select语句。
子查询就是嵌套查询,即SELECT中包含SELECT,如果一条语句中存在两个,或两个以上SELECT,那么就是子查询语句了。里面的查询叫做子查询,外层的查询叫父查询,一般情况都是先执行子查询,再执行父查询。
子查询出现的位置:
where后,作为被查询的条件的一部分;
from后,作临时表;
当子查询出现在where后作为条件时,还可以使用如下关键字:
any 跟结果集里面的多行单列部分进行比较,满足就返回true
all 跟结果里面的多行单列所有进行比较,所有都满足了才返回true
子查询结果集的常见形式:
单行单列(用于条件)
多行单列(用于条件)
多行多列(用于表)
示例:
1. 工资高于JONES的员工。
分析:
查询条件:工资>JONES工资,其中JONES工资需要一条子查询。
第一步:查询JONES的工资
SELECT sal FROM emp WHERE ename=’JONES’;
第二步:查询高于JONES工资的员工
SELECT * FROM emp WHERE sal > (第一步结果);
结果:
SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename=’JONES’);
查询与 admin777同一个部门的员工
第一步:查询admin777的部门编号
SELECT depno FROM emp WHERE ename=’admin777′
第二步:查询部门编号等于admin777的部门编号的员工
SELECT * FROM emp WHERE depno=
(SELECT depno FROM emp WHERE ename=’admin777′)
工资小于10号部门的所有员工信息
第一步:查询10号部门所有员工工资:
select salary from emp where deptno=10
第二步:查询小于10号部门所有人工资的员工信息
select*from emp where salary <all(第一步)
结果:SELECT * FROM emp WHERE salary<ALL
(SELECT MAX(salary) FROM emp WHERE depno=10)



发表回复