1.数据完整性
在查询的时候可以没有外键约束,就算没有外键约束也可以进行查询,但是在添加,更新的时候必须要有。
保证用户输入的数据保存到数据库当中是正确的(保存到数据库当中的数据是正确的)。具体做法是在建表的时候给约束,完整性可以分为一下三类
实体完整性
域完整性
引用完整性
(一)实体完整性
表当中的一行就代表一个实体,实体完整性的作用是约束每一行的数据不能重复,完整性约束主要可以分为一下三类
主键约束(primary key)
唯一约束(unique)
自动增长列(auto_increment)
1.主键约束
特点:每个表当中要有一个主键,并且数据唯一,不能为null
添加方式:
**********************建表的同时创建主键*****************
create table 表名(字段1 数据类型 primary key,字段2 数据类型.....字段n 数据类型);
create table 表名(字段1 数据类型,字段2 数据类型....primary key(要设置主键的字段));
create table 表名(字段1 数据类型,字段2 数据类型....primary key(主键1,主键2...));
*********************先建表,在创建主键********************************
1.建表
2.修改表,添加主键
alter table 表名 add constraint primary key (id);
create table person(
id bigint primary key,
name varchar(10)
);
**********************************************
create table person(
id bigint,
name varchar(10),
age int,
primary key (id)
);
******************************************************
-- 联合主键,两个主键合起来作为一个联合主键,
-- 两个主键都不能为null,不能有2个重复,可以有1个重复
create table student(
id bigint,
snum bigint,
sname varchar(10),
primary key(id,snum)
);
*********************************************
alter table students add constraint primary key(id);
2.唯一性约束
特点:指定列的数据不能重复,可以为null(可以有多个)
格式:
create table 表名(字段1 数据类型 unique,字段二 数据类型......);
注意主键约束可以有多个null
create table student(
id bigint primary key,
name varchar(50) unique,
age int
);
3.字段增长列
特点:指定列的数据自动增长,即使数据删除了,还是村删除的序号往下继续增长。
格式:
create table 表名(字段1 数据类型 primary key auto_increment,字段2 数据类型....);
create table student(
id bigint primary key auto_increment,
name varchar(20) unique,
age int
);
(二)域完整性
使用:限制此单元格的数据正确,不与此列的其他单元格进行比较,域代表当前当单元格。
域完整性约束主要分为一下三个方面:
数据类型:数值类型,日期类型,字符串类型
非空约束(not null)
默认值约束(default)
1.非空约束,默认值约束
create table 表名(字段1 数据类型 not null,字段2 数据类型....);
create table 表名(字段1 数据类型 default '男',字段2 数据类型....);
create table student(
id bigint primary key auto_increment,
name varchar(50) unique not null,
gender char(2) default '男'
);
(三)参照完整性
什么是参照完整性:是指表于表之间的一种对应关系,通常情况下可以通过设置2张表之间的主键,外键关系,或者编写2张表的触发器来实现,有对应参照完整性的2张表,对他们的数据进行插入删除更新操作的时候,系统都会将被修改表格与另一张对应的表格进行对照,从而阻止一些不正确的数据的操作。
数据库的主键和外键类型必须要一致
2个表必须要是Innodb类型
设置参照完整性后,外键当中的内值,必须是主键当中的内容
一个表设置当中的字段为主键,设置主键的为主表
创建表时,设置外键,设置外键的为子表
create table stu(
id int primary key,
name varchar(50),
age int
);
-- 设置score当中的sid为外键,和stu当中的主键id关联
create table score(
sid int,
score int,
constraint sc_st_fk foreign key (sid) references stu(id)
);
***************如果表以及建好了,可以使用SQL语句添加外键***********
alter table score add constraint foreign key (sid) references stu(id);
2.多表关系的创建
创建多对多关系的方法:创建一个中间关系表来实现
-- 多对多,要创建中间表
create table teacher(
tid int primary key ,
name varchar(50)
);
create table student(
sid int primary key,
name varchar(50)
);
-- 注意此处的字段名不能乱写,必须要是前两个表的主键,不然是无用的
create table tea_stu_rel(
tid int,
sid int
);
-- 添加中间表与其他表的联系(设置外键),中间表当中的字段都要设置外键.
alter table tea_stu_rel add constraint foreign key (tid) references teacher(tid);
alter table tea_stu_rel add constraint foreign key (sid) references student(sid);
总结:中间表约束创建完成之后,添加到中间表当中的数据全部是表一表二当中的数据,加入其他的数据会报错。
3.外什么要拆分表?
为了避免大量冗余数据的出现
4.多表查询
多表查询大致分为以下四个方面:
合并结果集
连接查询
子查询
自连接
(一)合并结果集
-- 合并结果集
create table A(
name varchar(50),
score int
);
create table B(
name varchar(20),
score int
);
insert into A values('a',80),('b',90);
insert into B values('a',80),('c',90),('b',100),('d',120)
select * from A union select * from B;
select * from A union all select * from B;
******************************************************
注意:在合并结果集的时候,要求2张表的列和列数据类型一致,不然不能合并
(二)连接查询
*********************多表查询会出现笛卡尔积结果集***********************
select * from student,teacher
笛卡尔积的记录书:A记录数*B记录数
1.如何保证数据的正确性,避免笛卡尔积结果集?
select * from stu,score where stu.id=score.sid;
***************************************************
在查询时保持主键和外键的一致性
主表当中的数据参照子表当中的数据
原理:逐行判断,相等的留下,不相等的全部要。
2.连接查询分类
注意查询的时候可以没有主外键约束
连接查询主要可以分为以下三类:
内连接
外连接
自然连接
(一)内连接
内连接可以分为如下的三种:
等值连接
多表连接
非等值连接
1.等值连接
**********************内连接*********************************
-- 注意查询的时候虽然没有主外键约束,但是我们在心里面应该明白有主外键约束
-- 99写法
select * from stu st,score sc where st.id=sc.id;
select * from stu st inner join score sc on st.id=sc.id;
select * from stu st join score sc on st.id=sc.id;
*******************************************************
select * from stu st join score sc on st.id=sc.id where score>80;
2.多表连接
表如下:
-- 查询处学生的姓名,分数,科目,在此处是三表查询
select st.name,sc.score ,cs.name from stu st,score sc ,course cs
where st.id=sc.id and sc.sid=cs.cid;
*******************************************************************
select st.name,cs.name,sc.score from stu st
inner join score sc on st.id=sc.id
inner join course cs on sc.sid=cs.cid;
总结:在进行多表查询的时候,具体的做法是一步一步,两表进行查询。
3.非等值连接
非等值查询:即查询后面的条件不是等值的
-- 查询所有员工的姓名,工资,所在部门名称以及该工资的等级
select emp.ename,emp.salary ,dept.dname ,salgrade.grade from
emp,dept ,salgrade
where emp.deptno=dept.deptno
and emp.salary>=salgrade.lowSalary
and emp.salary<=salgrade.higghSalary;
***************************************************
select e.ename,e.salary,d.dname,s.grade from emp e
inner join dept d on e.deptno=d.deptno
inner join salgrade s on e.salary between s.lowSalary and s.higghsalary;
(二)外连接
外连接可以分为:
左外连接(左连接)
右外连接(右连接)
1.左连接
将2表满足条件的数据查询出来,如果左边表右不同的数据,被左边表当中的数据查询出来
select * from stu st left outer join score sc on st.id=sc.id;
2.右链接
select * from stu st right outer join score sc on st.id=sc.id;
(三)自然连接
-- 不加where条件的时候,求出的结果是笛卡尔积的结果
select * from stu,score;
select * from stu ,score where stu.id=score.id;
select * from stu inner join score on stu.id=score.id;
-- 自然连接,当有相同列名及数据类型的时候,会按照主外键查
-- 如果没有对应的,会进行笛卡尔积查询
select * from stu natural join score;
总结:
4.子查询
什么是子查询:一个select语句当中包含另一个select语句,或者多个select语句。
子查询出现的位置:
where后:把select查询出来的结果当成另一个select的条件值。
from后:把查询出来的结果当成一个新表。
(一)where后
查询出和项羽同部门的员工名称
-- 查询与项羽同一部门的员工
-- 先查询项羽所在的部门,再查询同部门人员
select emp.deptno from emp where emp.ename='项羽' ;
select ename ,empno from emp
where deptno=(select emp.deptno from emp where emp.ename='项羽');
(二)from后
查询30号部门里面所有员工的薪资
-- 查询30号部门所有薪资大于2000的员工
-- 先查询30号部门的员工的工资,再查询大于2000的
select ename,salary from emp where deptno=30;
select es.ename ,es.salary from (select ename,salary from emp where deptno=30) es
where es.salary>2000;
(三)练习
-- 查询薪资高于程咬金的员工
第一步查询出程咬金的薪水,第二部查询出薪水大于他的员工
select e.salary from emp e where e.ename='程咬金';
select * from emp
where emp.salary>(select e.salary from emp e where e.ename='程咬金');
*****************************************************************
-- 查询工资高于30号部门所有人的员工信息
-- 第一步查询出30号部门的最高工资,第二部查处大于最高工资的所有人信息
select max(salary) from emp where deptno=30;
select * from emp
where emp.salary>(select max(salary) from emp where deptno=30);
******************************************************************************
-- 查询工作和工资都与妲己完全相同的员工的信息
-- 第一步查询妲己的工作和工资,第二部查询相同的员工
select salary,job from emp where ename='妲己';
select * from emp
where job=(select job from emp where ename='妲己')
and salary=(select salary from emp where ename='妲己');
select * from emp
where (salary,job) in (select salary,job from emp where ename='妲己');
-- 利用99查询查询出共同的数据(salary,job相同)
select * from emp,(select salary,job from emp where ename='妲己') sj
where emp.salary=sj.salary
and emp.job=sj.job;
******************************************************************************
-- 查询有2个以上直接下属的员工信息
-- 对上级字段mgr进行统计,有2个相同说明,该编号所对应的人有2个直接下级
select mgr,group_concat(mgr),count(mgr) from emp group by mgr having count(mgr)>2;
select * from emp
where empno in (select mgr from emp group by mgr having count(mgr)>2);
*************************************************************************
-- 查询编号为7788的员工的名称,员工工资,部门名称,部门地址
select e.ename,e.salary ,d.dname ,d.local from emp e ,dept d
where e.deptno=d.deptno
and e.empno=7788;
***********************切记不可写成以下的形式*****************************
select e.ename,e.salary ,d.dname ,d.local from emp e ,dept d
where e.empno=7788;
总结:这是错误的,因为在进行多表查询的时候,没有写连接字段,肯定是错误的。
5.自连接
自己连接自己,起别名
-- 求7902的员工编号,姓名,经理编号,经理姓名
select mgr from emp where empno=7369;
select ename from emp where empno=(select mgr from emp where empno=7369);
select e1.ename,e1.empno,e2.mgr,e2.ename from emp e1,emp e2
where e1.empno=e2.mgr
and e1.empno=7902;