MySQL入门(8)- 约束——主键约束&外键约束&级联更新/删除

约束——主键约束&外键约束&级联更新/删除

此系列记录PN视频学习笔记


* 本博客涉及到的数据为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


你可能感兴趣的:(MySQL)