一、多表如何建表:参看1NF、2NF、3NF
百度答案:
1、第一范式(1NF)
` 是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。
2、第二范式(2NF)
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求实体的属性完全依赖于
主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与
原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式就是非主属性非部分依赖于主关键字。
3、第三范式(3NF)
满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。简而言之,
第三范式就是属性不依赖于其它非主属性。
自我理解:
1NF:是指数据库的每一列都不可以再次分割的基本数据项,既原子性。
2NF:每一列的数据项都对主键具有直接或者间接地依懒性,既依赖性。
3NF:每一列的数据项都对主键具有直接依懒性,既对主键不具有传递依赖性
二、外键:
外键约束是指在主表中的一列信息与附表中的主键相关联;使用外键,可以保证数据的完整性。
a表 |
||||||
职位 |
小时工资率 |
|||||
工程师 |
100 |
|||||
助理 |
50 |
|||||
工人 |
80 |
|||||
技术员 |
60 |
|||||
会计 |
150 |
|||||
b表 |
外键 |
|||||
员工编号 |
员工姓名 |
职位 |
||||
1001 |
jim |
工程师 |
||||
1002 |
tom |
工程师 |
||||
1003 |
jerry |
工人 |
||||
1004 |
eric |
NULL |
||||
1005 |
marry |
会计 |
||||
添加不能乱添加 |
b表如果要添加职位,a表中必须要有这个职位 |
|||||
修改不能乱修改 |
b表如果要修改职位,a表中必须要有这个职位 |
|||||
删除不能乱删除 |
a表如果要删除职位,b表中必须没有这个职位的信息 |
|||||
如果想实现上面的功能,必须要给b表添加外键。
建表次序:先建立a表,再建立b表
Create table p_post(
Postnamevarchar(50) primary key,
Hoursalaryint
);
create table p_emp(
eidint primary key auto_increment,
enamevarchar(50) not null,
postvarchar(50),
constraintemp_post foreign key p_emp(post) references p_post(postname)
);
语法:constraint 外键名 foreign key 从表(外键列名)references 主表(主键列名)
1、 从表的外键列和主表的主键列类型一定要一致;名字可以不一样;
2、 主表被从表引用的列一定得是主键。
员工表添加数据或修改数据必须职位信息已经在职位表中存在:
insert into p_emp values(1005,'水电工');
注意查看错误关键字:foreign key constraint fails
删除职位表要注意员工表是否有员工拥有该职位
工程号 |
工程名称 |
Pid pname
工程号 |
职工号 |
工时 |
Pid eid hour
职工工号 |
姓名 |
职务 |
Eid ename post
职务 |
小时工资率 |
Postname hoursalary
建表的时候先建箭头末梢的,比如工程表和职务表
三、 多表查询
a) 多表连接不要用
员工编号 |
员工姓名 |
职位 |
小时工资率 |
|
1001 |
jim |
工程师 |
100 |
|
1002 |
tom |
工程师 |
100 |
|
1003 |
jerry |
工人 |
80 |
|
1005 |
marry |
会计 |
150 |
select * from p_emp,p_post where p_emp.post=p_post.postname;
select * from p_emp a,p_post b where a.post=b.postname;给表起别名
b) 内连接 *****
select *
from p_emp
join p_post on p_emp.post=p_post.postname;
写全是inner join ,inner可以不写
最终版本
select eid,ename,post,hoursalary
from p_emp a
joinp_post b on a.post=b.postname;
四张表一起查询:
selecta.pid,pname,c.eid,ename,post,hoursalary,hour,hour*hoursalary as total
fromp_construct a
joinp_project b on a.pid=b.pid
joinp_emp c on c.eid=a.eid
joinp_post d on c.post=d.postname
c) 左外连接
员工编号 |
员工姓名 |
职位 |
小时工资率 |
|
1001 |
jim |
工程师 |
100 |
|
1002 |
tom |
工程师 |
100 |
|
1003 |
jerry |
工人 |
80 |
|
1004 |
eric |
NULL |
NULL |
|
1005 |
marry |
会计 |
150 |
select *
fromp_emp a
left join p_post b on a.post=b.postname;
写全是left outer join,outer可以不写
join关键字左边的表全部行显示,右边的表没有数据就显示null
d) 右外连接
员工编号 |
员工姓名 |
职位 |
小时工资率 |
|
1001 |
jim |
工程师 |
100 |
|
1002 |
tom |
工程师 |
100 |
|
1005 |
marry |
会计 |
150 |
|
1003 |
jerry |
工人 |
80 |
|
NULL |
NULL |
技术员 |
60 |
|
NULL |
NULL |
助理 |
50 |
|
select *
fromp_emp a
right join p_post bon a.post=b.postname;
join关键字右边的表全部行显示,左边的表没有数据就显示null
mysql不支持全连接
e) 子查询
i. = > >= 等
/*查找工人的小时工资率*/
/*查找比工人的小时工资率还低的职位*/
select * from p_post where hoursalary<(select hoursalaryfrom p_post where postname='工人');
查找比jerry小时工资率高的员工
select *
fromp_emp a
joinp_post b on a.post=b.postname
where hoursalary>
(
select d.hoursalary
from p_emp c
join p_post d on c.post=d.postname
where c.ename='jerry'
);
查找和jim小时工资率一样的员工
1、 先查找jim的小时工资率
2、 再查找和jim的小时工资率一样的员工
select *
from p_emp a
join p_post b on a.post=b.postname
where b.hoursalary=
(
select d.hoursalary
from p_emp c
join p_post d on c.post=d.postname
where c.ename='jim'
)
查找小时工资率大于50
ii. In/not in 集合
内连接:
学号 姓名 选课 课程名
学号 课程 课程名 学分 分数
学号 姓名 课程名 教师 职称 学分 分数
子查询:
查找和1001同学选修的课程一样的学生信息
查找和1001同学选修的课程数目一样的学生信息
查找选修了高老师的课程的学生信息
四、 视图
五、索引
六、 系统函数
a) 流程控制函数 case when if then end if
b) 聚合函数
c) 日期函数 getdate
d) 字符串函数 substr trim ltrim rtrim concat replace reverse right
e) 其他 cast convert
七、 自定义函数
八、存储过程
九、触发器