* 本博客涉及到的数据为bjpowernode.sql,数据见文末,SQL文见MySQL入门(9)文末。
* 该数据有三张表,分别是部门表dept(deptno部门编号、dname部门名称、loc位置)、
员工表emp(empno工号、ename员工姓名、job职位、mgr直属领导工号、
hiredate入职日期、sal月薪、comm补贴、deptno部门编号)、
薪水等级表salgrade(grade等级、losal区间下限、hisal区间上限)
6、主键约束-primary key-PK
6.1 主键涉及到的术语:
-主键约束
-主键字段
-主键值
6.2主键约束、主键字段、主键值的关系?
表中的某个字段添加主键约束之后,该字段被称为主键字段,主键字段中出现的每一个数据被称为主键值。
6.3主键的作用:作为某行纪录的唯一标识
给某个字段添加主键约束(primary key)之后,该字段不能重复,且不能为空。
效果和not null unique相同,但是本质不同。
主键约束除了可以做到not null unique之外,主键字段还会默认添加‘索引-index’。
6.4一张表应该有主键字段,若没有,表示这张表是无效的。
主键值是当前行数据的唯一标识,是当前行数据的身份证号。
即使表中的两行记录相关的数据是相同的,但是只要主键值不同,便认为这两行是完全不同的数据。
6.5 【单一主键】:给一个字段添加主键约束。
//单一主键
//列级定义方式/列级约束
drop table if exists t_user;
create table t_user(
id int(10) primary key,
name varchar(32)
);
//单一主键
//表级定义方式/表级约束
drop table if exists t_user;
create table t_user(
id int(10),
name varchar(32),
primary(key)
);
//单一主键
//表级定义方式/表级约束
//起名
drop table if exists t_user;
create table t_user(
id int(10),
name varchar(32),
constraint t_user_id_pk primary key(id)
);
mysql> desc t_user;
+-------+-------------+------+-----+---------+-------+
| Field | Type |Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(10) | NO | PRI | NULL | |
| name | varchar(32) |YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
6.6 【复合主键】:给多个字段联合添加一个联合主键。
//单一主键
//表级定义方式/表级约束
//起名
drop table if exists t_user;
create table t_user(
id int(10),
name varchar(32),
email varchar(128),
constraint t_user_ib_name_pk primary key(id,name)
);
mysql>desc t_user;
+-------+--------------+------+-----+---------+-------+
| Field | Type |Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int(10) | NO | PRI | NULL | |
| name |varchar(32) | NO | PRI | NULL | |
| email | varchar(128) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
mysql> insert into t_user(id,name,email)values(1,'jack','[email protected]');
Query OK, 1 row affected (0.01 sec)
mysql> insert into t_user(id,name,email)values(1,'jack','[email protected]');
ERROR 1062 (23000): Duplicate entry '1-jack' for key 'PRIMARY'
mysql> insert into t_user(id,name,email)values(2,'jack','[email protected]');
Query OK, 1 row affected (0.01 sec)
mysql> insert into t_user(id,name,email)values(2,'abc','[email protected]');
Query OK, 1 row affected (0.01 sec)
mysql> select * from t_user;
+----+------+----------------------+
| id | name | email |
+----+------+----------------------+
| 1 | jack |[email protected] |
| 2 | abc | [email protected] |
| 2 | jack | [email protected]|
+----+------+----------------------+
6.7 无论是单一主键还是复合主键,一张表的主键约束只能有一个。
6.8 主键根据性质分类:
- 自然主键
* 主键值是一个自然数,且该自然数和当前表的业务没有任何关系
- 业务主键
* 主键值和当前表中业务紧密相关,当业务数据发生改变的时候,主键值通常会受到影响,所以业务主键使用较少,
大部分都是使用自然主键。
6.9 主键在MYSQL数据管理系统中提供了一个自增的数字,专门用来自动生成主键值。
主键值不需要用户维护,也不需要用户提供,自动生成,这个自增的数字默认以1递增:1,2,3,4,……
drop table if exists t_user;
create table t_user(
id int(10) primary key auto_increment,
name varchar(32)
);
insertinto t_user(name) values('jack');
insertinto t_user(name) values('jack');
insertinto t_user(name) values('jack');
insertinto t_user(name) values('jack');
insertinto t_user(name) values('jack');
insertinto t_user(name) values('jack');
select* from t_user;
+----+------+
| id | name |
+----+------+
| 1 | jack |
| 2 | jack |
| 3 | jack |
| 4 | jack |
| 5 | jack |
| 6 | jack |
+----+------+
delete from t_user where id=4;
insert into t_user(name) values('jack');
select * from t_user;
+----+------+
| id | name |
+----+------+
| 1 | jack |
| 2 | jack |
| 3 | jack |
| 5 | jack |
| 6 | jack |
| 7 | jack |
+----+------+
7、外键约束-foreign key-简称FK
7.1外键约束涉及到的术语:
-外键约束
-外键字段
-外键值
7.2外键约束、外键字段、外键值之间的关系
某个字段添加外键约束之后,该字段为外键字段,外键字段中的每一个数据都是外键值。
7.3外键分为:
-单一外键:给一个字段添加外键约束
-复合外键:给多个字段添加一个外键约束、
7.4一张表中可以有多个外键字段。
7.5 案例:请设计数据库表,引来存储学生和班级信息,给出两种解决方案:
学生信息和班级信息之间的关系,一个班级对应多个学生,这是典型的一对多的关系。
第一种设计方案:将学生信息和班级信息存储到一张表中。
学生信息表t_student
Sno(PK) sname classno cname
--------------------------------------------------------------
1 jack 100 北京市海淀区………高三1班
2 lucy 100 北京市海淀区………高三1班
3 zhangsan 100 北京市海淀区………高三1班
4 ford 200 北京市海淀区………高三2班
5 king 200 北京市海淀区………高三2班
6 allen 300 北京市海淀区………高三3班
7 lisi 300 北京市海淀区………高三3班
以上设计的缺点:数据冗余
第二种解决方案:将学生信息和班级信息两张表存储,学生表+ 班级表
学生表t_student
sno(PK) sname classno(FK)
----------------------------------
1 jack 100
2 lucy 100
3 zhangsan 100
4 ford 200
5 king 200
6 allen 300
7 lisi 300
班级表t_class
classno(PK) cname
---------------------------------------------
100 北京市海淀区………高三1班
200 北京市海淀区………高三2班
300 北京市海淀区………高三3班
结论: 为了保证t_student表中的classno字段中的数据必须来源于t_class表中cno字段中的数据,有必要给t_student表中的classno字段添加外键约束,classno字段被称为外键字段,该字段中100,200,300被称为外键值,且这里的classno是一个单一外键字段。
注:外键值可以为NULL。
外键字段引用其他表的某个字段时,被引用字段必须具备unique约束。
有了外键引用之后,表分为父表和子表,以上父表是班级表,子表是学生表;
创建表先创建父表,在创建子表;删除数据时先删除子表中的数据,再删除父表中的数据;插入数据时先插入父表中的数据,在插入子表中的数据
7.6 SQL语句(SQL文)【外键约束只有表级定义方式】
drop table if exists t_student;
drop tableif exists t_class;
create table t_class(
cno int(10) primary key,
cname varchar(128) not null unique
);
create table t_student(
sno int(10) primary key,
sname varchar(32) not null,
classno int(10),
constraint t_student_classno_fk foreign key(classno) referencest_class(cno)
);
insertinto t_class(cno,cname) values(100, '高三1班');
insertinto t_class(cno,cname) values(200, '高三2班');
insertinto t_class(cno,cname) values(300, '高三3班');
insertinto t_student(sno,sname,classno) values(1, 'jack',100);
insertinto t_student(sno,sname,classno) values(2, 'lucy',100);
insertinto t_student(sno,sname,classno) values(3, 'zhangsan',100);
insertinto t_student(sno,sname,classno) values(5, 'ford',200);
insertinto t_student(sno,sname,classno) values(4, 'king',200);
insertinto t_student(sno,sname,classno) values(6, 'allen',300);
insertinto t_student(sno,sname,classno) values(7, 'lisi',300);
select* from t_class;
select* from t_student;
mysql> insert into t_student(sno,sname,classno) values(8, 'lily',500); //失败
ERROR 1452 (23000): Cannot add or update a child row: a foreign keyconstraint fails (`mydb`.`t_student`, CONSTRAINT `t_student_classno_fk` FOREIGNKEY (`classno`) REFERENCES `t_class` (`cno`))
重点:典型的一对多,在多的一方加外键
案例:找出每个学生的班级名称
select s.sname,c.cname from t_students,t_class c where s.classno = c.cno;
+----------+------------+
| sname | cname |
+----------+------------+
| jack | 高三1班 |
| lucy | 高三1班 |
| zhangsan | 高三1班 |
| king | 高三2班 |
| ford | 高三2班 |
| allen | 高三3班 |
| lisi | 高三3班 |
+----------+-------------+
8、级联更新和级联删除
- 添加级联更新和级联删除的时候需要在外键约束后添加
- 在删除父表中数据的时候,级联删除子表中的数据 on delect cascade
* 删除外键约束
alter table t_student drop foreign keyt_student_classno_fk;
* 添加外键约束
alter table t_student add
constraintt_student_classno_fk
foreignkey(classno) references t_class(cno) on delete cascade;
mysql> delete from t_class where cno = 100;
mysql> select * from t_class;
+-----+------------+
| cno | cname |
+-----+------------+
| 200 | 高三2班 |
| 300 | 高三3班 |
+-----+------------+
mysql> select * from t_student;
+-----+-------+---------+
| sno | sname | classno |
+-----+-------+---------+
| 4 | king | 200 |
| 5 | ford | 200 |
| 6 | allen | 300 |
| 7 | lisi | 300 |
+-----+-------+---------+
- 在更新父表中数据的时候,级联更新自表中的数据 onupdate cascade
* 删除外键约束
alter table t_student drop foreign keyt_student_classno_fk;
* 添加外键约束
alter table t_student add
constraintt_student_classno_fk
foreignkey(classno) references t_class(cno) on update cascade;
mysql> update t_class set cno = 2000 wherecno = 200;
mysql> select * from t_class;
+------+------------+
| cno |cname |
+------+------------+
| 2000 | 高三2班 |
| 300 |高三3班 |
+------+------------+
mysql> select * from t_student;
+-----+-------+---------+
| sno | sname | classno |
+-----+-------+---------+
| 4 |king | 2000 |
| 5 |ford | 2000 |
| 6 |allen | 300 |
| 7 |lisi | 300 |
+-----+-------+---------+
- 以上的级联更新和级联删除谨慎使用,因为级联操作会将数据改变或者删除【数据无价】
DEPTNO | DNAME | LOC |
10 | ACCOUNTING | NEW YORK |
20 | RESEARCHING | DALLAS |
30 | SALES | CHICAGO |
40 | OPERATIONS | BOSTON |
EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
7369 | SMITH | CLERK | 7902 | 1980/12/17 | 800 | NULL | 20 |
7499 | ALLEN | SALESMAN | 7698 | 1981/2/20 | 1600 | 300 | 30 |
7521 | WARD | SALESMAN | 7698 | 1981/2/22 | 1250 | 500 | 30 |
7566 | JONES | MANAGER | 7839 | 1981/4/2 | 2975 | NULL | 20 |
7654 | MARTIN | SALESMAN | 7698 | 1981/9/28 | 1250 | 1400 | 30 |
7698 | BLAKE | MANAGER | 7839 | 1981/5/1 | 2850 | NULL | 30 |
7782 | CLARK | MANAGER | 7839 | 1981/6/9 | 2450 | NULL | 10 |
7788 | SCOTT | ANALYST | 7566 | 1987/4/19 | 3000 | NULL | 20 |
7839 | KING | PERSIDENT | NULL | 1981/11/17 | 5000 | NULL | 10 |
7844 | TURNER | SALESMAN | 7698 | 1981/9/8 | 1500 | NULL | 30 |
7876 | ADAMS | CLERK | 7788 | 1987/5/23 | 1100 | NULL | 20 |
7900 | JAMES | CLERK | 7698 | 1981/12/3 | 950 | NULL | 30 |
7902 | FORD | ANALYST | 7566 | 1981/12/3 | 3000 | NULL | 20 |
7934 | MILLER | CLERK | 7782 | 1982/1/23 | 1300 | NULL | 10 |
GRADE | LOSAL | HISAL |
1 | 700 | 1200 |
2 | 1201 | 1400 |
3 | 1401 | 2000 |
4 | 2001 | 3000 |
5 | 3001 | 9999 |