• Mysql 讲解所有的约束类型


    Mysql 讲解所有的约束类型

    在这里插入图片描述


    每博一文案

    知乎上有个问题:你是如何发现,你彻底失去了一个人。
    有个高赞回答。这样说,当我无论说什么对方都只是沉默时,我就知道一切已经无法挽回了。
    从什么时候开始,你宁愿一个人挺着,也不对人诉说,从什么时候开始,宁愿把委屈吞下,
    也不解释太多,久而久之,有事,偷偷隐藏,有难,独自去扛,有泪,自己流淌。
    其实我们每个人越来越沉默,不过是,因为看透了,有些事不必说,有些事,不能说,
    渐渐的都变成了,不想说。
    沉默是一个人,最大的私心。周国平在风中的纸屑里说,在最深重的苦难中,没有身影,
    没有哭泣,沉默是绝望者最后的尊严,在最可怕的屈辱中,没有诅咒,没有叹息。
    沉默是复仇者最高的情面,经历越多就越明白。世上没有真正的感同身受,拥抱沉默
    ,是我们成长路上的必修课。谁干净不是,因为它没有杂质,而是它懂得沉淀,
    再浑浊的水,只要经过了长久的沉淀,都能变得清澈,
    你所有的沉默都是修炼自己的过程,日后想来,都会变成礼物。
    原每个懂得沉默的人,都能从容跨过坎坷,每个努力生活的人,都能被世界温柔相待。
                           ——————   一禅心灵庙语
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14


    1. 约束

    约束 是表级的强制规定,可以在创建表时规定约束 (通过 CREATE TABLE 语句),或者在表创建之后通过 ATLTER TABL 语句规定约束

    1.1 为什么需要约束

    为了保证数据的完整性,**数据完整性(Data lntegrity) **是指 数据的 精确性(Accuracy)可靠性(Reliability) 。 它是防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息而提出的。

    SQL 规范以约束的方式对表数据进行额外的条件限制。从以下四个反面考虑:

    • 实体完整性(Entity lntegrity) : 例如 在同一个表中,不能存在两条完全相同无法区分的记录
    • 域完整性(Domain lntegrity): 例如 年龄范围 0 -120 ,性别 范围 男/女
    • 引用完整性(Referential lntegrity) :例如:员工所在部门,在部门表中要能找这个部门
    • 用户自定义完整性 (User-defined lntegrity): 例如:用户名唯一,密码不能空等,工资不得低于 平均工资的 5 倍。

    1.2 约束的分类

    • 根据约束数据列的限制,约束可分为:
      • 单列约束 :每个约束只能约束一列 (主键约束)
      • 多列约束 :每个约束可约束多列数据
    • 根据约束的作用范围,约束可分为:
      • 列级约束: 只能作用在一个列上,定义在列的定义后面
      • 表级约束: 可以作用在多个列上,不与列一起,而是单独定义

    列级约束: 简单的说:就是定义在创建字段是,紧跟定义在字段的后面的

    表级约束: 简单的说:就是定义所以字段的最后面。

    名称位置支持的约束类型是否可以另起约束名
    列级约束列的后面所有约束都支持,但外键没有效果不可以
    表级约束所有列的最后面默认约束和非空约束不支持,其他都支持可以(但主键没有效果)
    • 根据约束的作用,约束可分为:
      • NOT NULL 非空约束,作用:规定某个字段的内容不能空
      • UNIQUE 唯一约束,作用:规定某个字段中的值,不可以重复,每个值都是唯一的
      • PRIMARY KEY 主键约束,作用:非空约束 + 唯一约束
      • AUTO_INCREMENT 自增约束,作用:自动增加数值,但是只能是整型数据类型才行
      • FOREIGN KEY 外键约束,作用:主表中的列 与 从表中的列建立联系
      • CHECK 检查约束,作用:检查数值的范围
      • DEFAULT 默认值约束,作用:定义字段中的默认值属性

    1.3 查看表中的含有的所有约束

    具体格式如下:

    -- 查看表中含有的所有约束
    SELECT * 
    FROM information_schema.table_constraints
    WHERE table_name = '填查看的表名';
    
    -- information_schema 是数据库名(系统库)
    -- table_constraints 表名称(专门存储各个表的约束)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2. NOT NULL 非空约束

    NOT NULL 非空约束 作用: 限定某个字段/某列的值不允许为空。

    在这里插入图片描述

    特点:

    • 默认,所有的类型的值都可以是 NULL,包括 INT,FLOAT 等数据类型,
    • 注意:非空约束只能定义在某个单独的字段/列上,不能组合(多个列/字段)定义非空约束
    • 一个表中可以存在多列分别定义非空约束。
    • 注意:空字符串 不等于 NULL ,0 也 不等于 NULL

    2.1 添加非空约束

    • 建表时 CREATE TABLE 添加约束

    格式如下:

    CREATE TABLE 表名 
    (
    字段名1 数据类型 NOT NULL,
    字段名2 数据类型 NOT NULL
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5

    举例

    CREATE TABLE test1(
    id INT NOT NULL,
    last_name VARCHAR(15) NOT NULL,
    email VARCHAR(25),
    salary DECIMAL(10,2)
    );
    
    DESC test1;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述


    插入数据,

    INSERT INTO test1 (id,last_name,email,salary)
    VALUES (1,'张三','tom@123.com',10000);
    
    • 1
    • 2

    在这里插入图片描述


    存在了 NOT NULL 约束的字段不可以,插入 NULL值,不然报错。

    INSERT INTO test1 (id,last_name,email,salary)
    VALUES (NULL,'张三','tom@123.com',10000);  -- id 存在非空约束不可为 NULL
    
    • 1
    • 2

    在这里插入图片描述


    需要注意的是,还有一个,隐式的插入 NULL的方式,没有指明字段名,插入数值时,默认是 NULL,同样会报错

    INSERT INTO test1(last_name,email,salary) -- 省略了 id,默认插入NULL,报错
    VALUES ('张三','tom@123.com',10000);
    
    • 1
    • 2

    在这里插入图片描述


    • 建表后,使用 ALTER TABLE 添加 NOT NULL 非空约束,使用 MODIFY 修改字段属性

    所谓的建表之后,添加 NOT NULL 非空约束的:本质上就是修改字段的数据类型 或者 属性 为 NOT NULL

    注意:建表之后,添加 NOT NULL 非空约束的字段,其本身不能含有 NULL 值,如果含有 NULL,是无法添加成功的,并报错

    格式如下:

    ALTER TABLE 表名
    MODIFY 字段名 数据类型 NOT NULL;
    
    • 1
    • 2

    举例子:将表 test 中的字段 email 添加 NOT NULL 非空约束

    在这里插入图片描述

    ALTER TABLE test1
    MODIFY email VARCHAR(25) NOT NULL; -- 字段的数据类型不要忘记了
    
    • 1
    • 2

    在这里插入图片描述


    建表之后,为字段添加 NOT NULL 非空约束,注意:其字段本身不可以含有 NULL值,不然报错, 道理很简单,非空约束嘛,既然你自身都含有 NULL值了,自然无法附加该非空约束了。

    如下:我们在表 test1 中字段 emial 中插入 NULL值,后再添加 非空约束,报错

    在这里插入图片描述

    ALTER TABLE test1
    MODIFY email VARCHAR(25) NOT NULL; -- 修改失败,email中含有 NULL值
    
    • 1
    • 2

    在这里插入图片描述


    2.2 删除非空约束

    对于删除已添加的 NOT NULL 非空约束。

    同样是使用 ALTER TABLE 中的 MODIFY 修改字段中的数据类型/属性

    两个方式,格式如下

    -- 方式1 去掉not null,相当于修改某个非注解字段,该字段允许为空
    ALTER TABLE 表名
    MODIFY 字段名 数据类型 NULL;
    -- 方式2 去掉not null,相当于修改某个非注解字段,该字段允许为空
    ALTER TABLE 表名
    MODIFY 字段名 数据类型;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    举例:使用方式 1 ,将 test1 表中的字段 id 中的非空约束删除了

    在这里插入图片描述

    ALTER TABLE test1
    MODIFY id INT NULL; -- 不要忘记了数据类型
    
    • 1
    • 2

    在这里插入图片描述


    举例子:使用方式2 将表 test1 中字段 last_name 的非空约束删除了

    在这里插入图片描述

    ALTER TABLE test1
    MODIFY last_name VARCHAR(15);
    
    • 1
    • 2

    在这里插入图片描述


    3. UNIQUE 唯一性约束

    UNIQUE 唯一性约束 作用: 用来限制某个字段/某列的值不能重复。

    在这里插入图片描述


    特点:

    • 同一个表中可以有多个唯一约束
    • 唯一约束可以是某一个列的值唯一,也可以多个列组合的值唯一
    • 唯一性约束允许列值为NULL(空)
    • 在创建唯一约束的时候,如果不给唯一约束命名,就默认和列名相同
    • MySQL会给唯一约束的列上,默认创建一个唯一索引

    3.1 添加唯一约束

    建表时 CREATE TABLE 添加唯一约束 UNIQUE

    格式如下:

    CREATE TABLE 表名
    (
    字段名1 数据类型 UNIQUE,
    字段名2 数据类型 UNIQUE
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5

    举例:创建数据表,表名为: test2,字段 id 定义 unique 唯一约束

    CREATE TABLE test2
    (
    id INT UNIQUE,  -- 唯一约束
    last_name VARCHAR(15),
    email VARCHAR(25),
    salary DECIMAL(10,2)
    );
    
    DESC test2;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述


    • 建表后:使用 ALTER TABLE 添加 UNIQUE 唯一约束,两种方式
      • 第一种,使用 **ALTER TABLE **中的 ADD 添加字段的同时添加 unique 唯一约束

    格式如下:

    ALTER TABLE 表名
    ADD 添加的字段名 数据类型 UNIQUE;
    
    • 1
    • 2

    还可以指定约束名,格式如下:

    ALTER TABLE 表名
    ADD CONSTRAINT 约束名 UNIQUE(需要附加的唯一约束的字段名);
    
    • 1
    • 2
      • 第二种,在已有的字段中,使用 ALTER TABLE 中的 MODIFY 修改其数据类型/属性/约束; 这种方式需要注意:当需要为表中已有的字段添加 UNIQUE 约束时,该字段中一定不能含有重复的值,不然时,无法附加 该唯一约束的 ,道理很简单,唯一约束吗,既然你本身都有重复的值了,自然无法附加唯一约束了。

    格式如下:

    ALTER TABLE 表名
    MODIFY 字段名 数据类型 UNIQUE;
    
    • 1
    • 2

    举例子:为表 test2 中的字段 email 添加 UNIQUE 唯一约束

    在这里插入图片描述

    ALTER TABLE test2
    MODIFY email VARCHAR(25) UNIQUE;  -- 不要忘记了,数据类型名
    
    • 1
    • 2

    在这里插入图片描述


    查看表 test2 中含有的约束,没有指明约束名,默认是和列名相同

    SELECT *
    FROM information_schema.table_constraints
    WHERE table_name = 'test2';
    
    • 1
    • 2
    • 3

    在这里插入图片描述


    插入数据

    INSERT INTO test2(id,last_name,email,salary)
    VALUES (1,'张三','Tom@126.com',10000);
    
    • 1
    • 2

    在这里插入图片描述


    定义了 UNIQUE 唯一约束的字段中,不可插入重复的数据,不然报错

    这里我们插入,刚刚已经插入过的数据 id 1 ,报错

    INSERT INTO test2(id,last_name,email,salary)
    VALUES (1,'张三','Tom@126.com',10000);
    
    • 1
    • 2

    在这里插入图片描述


    定义为 UNIQUE 唯一约束的字段中可以添加 NULL值,也可以添加多个 NULL值

    如下:为字段 id 插入 三个 NULL值

    INSERT INTO test2(id)
    VALUES (NULL),
           (NULL),
           (NULL);
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述


    3.2 复合唯一约束

    所谓的复合唯一约束就是同一个表中的 表级约束 中 对多个字段组合成一个 UNIQUE唯一约束 ,多个字段之间使用逗号分隔开来。

    表级约束: 在创建表时,定义在所有字段的最后面。

    复合唯一约束的特点: 只有当 复合约束中包含的所有字段的值同时重复,才表示重复,只要不是全部重复,就不算重复,可以插入数内容。

    注意复合唯一约束只能在表级约束中定义创建 ,如果没有指定该复合唯一约束的越是名,默认和复合唯一约束中第一个字段名一样。

    格式如下:

    CREATE TABLE 表名
    (
    字段名1 数据类型 可以附加上其他约束,
    字段名1 数据类型,
    -- 表级约束
    CONSTRAINT 该复合唯一约束名 UNIQUE(字段名1,字段名2) -- 复合唯一约束
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    也可以不使用 CONSTRAINT 指定约束名,格式如下:

    CREATE TABLE 表名
    (
    字段名1 数据类型 约束,
    字段名2 数据类型,
    -- 表级约束
    UNIQUE key(字段名1,字段名2)  -- 复合唯一约束
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    举例创建表 uesr 包含复合唯一约束

    CREATE TABLE `user`(
    id INT,
    `name` VARCHAR(15),
    `password` VARCHAR(25),
    -- 表级约束
    CONSTRAINT up_user_name_pwd UNIQUE(`name`,`password`) -- name password 与关键字冲突了,使用着重号  -- constraint 设定约束名,若没有指定约束名,默认和复合唯一约束上第一个字段名相同
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    查看表中的约束

    SELECT *
    FROM information_schema.table_constraints
    WHERE table_name = 'user';
    
    • 1
    • 2
    • 3

    在这里插入图片描述


    插入数据

    INSERT INTO `user`(id,`name`,`password`)
    VALUES (1,'张三','000');
    
    • 1
    • 2

    在这里插入图片描述


    向表 user 中 字段 name 再次插入 ”张三“, 字段 password 插入 ’111‘,不会报错,可以插入该数据,因为这是复合唯一约束,只有当复合唯一约束中所有的字段内容全部重复了,才算重复。单单是复合唯一约束中的一个字段的重复了是没有问题的。不算重复

    INSERT INTO `user`(id,`name`,`password`)
    VALUES (2,'张三','111'),
           (3,'张三','333'),
           (4,'李四','111');
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述


    但是,当我们插入 的内容重复了,复合唯一约束中包含的所有字段时,就算是 重复了,无法插入,并报错

    如下:我们将复合唯一约束的字段 name ,password 中已有内容的 张三, 000 ,再次插入报错

    INSERT INTO `user`(id,`name`,`password`)
    VALUES (5,'张三','000');
    
    • 1
    • 2

    在这里插入图片描述


    举个学生,选课的数据表的例子

    创建表:

    -- 课程表
    CREATE TABLE course (
    cid INT,
    cname VARCHAR(20)
    );
    
    DESC course;
    
    -- 学生表
    CREATE TABLE student (
    sid INT,
    sname VARCHAR(15),
    tel CHAR(11) UNIQUE,
    cardid CHAR(18) UNIQUE -- 唯一约束
    );
    
    DESC student;
    
    -- 选课表
    CREATE TABLE student_course (
    id INT,
    sid INT,
    cid INT,
    score INT,
    UNIQUE KEY (sid,cid)  -- 复合唯一约束
    );
    
    DESC student_course;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述


    插入数据

    -- 学生表
    INSERT INTO student (sid,sname,tel,cardid)
    VALUES (1,'张三','134568033','128024803299303'),
           (2,'李四','123390890','139880908270580');
           
    SELECT *
    FROM student;
    
    
    -- 课程表
    INSERT INTO course(cid,cname)
    VALUES (1001,'JAVA'),
           (1002,'MySQL');
           
    SELECT *
    FROM course;
    
    
    -- 选课表
    INSERT INTO student_course(id,sid,cid,score)
    VALUES (1,1,1001,89),
           (2,1,1002,90),
           (3,2,1001,99),
           (4,2,1002,100);
           
    SELECT *
    FROM student_course;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述


    不可以重复复合唯一约束中包含的所有内容,不然报错

    INSERT INTO student_course(id,sid,cid,score)
    VALUES (5,2,1001,90);  -- 2, 1001 复合唯一约束都重复了,报错;
    
    • 1
    • 2

    在这里插入图片描述


    3.3 删除唯一约束

    • 我们添加唯一约束的列/字段会自动创建唯一索引
    • 删除唯一约束只能通过删除唯一索引的方式删除
    • 删除时需要指定唯一索引名,唯一索引名就和 唯一约束名一样
    • 如果创建唯一约束时,为指定该约束名称时,
      • 如果是单列,就默认和列名相同
      • 如果是组合列(复合唯一约束),默认就是和 定义复合中括号 中( )排在第一个的列名/字段名相同,如果设定的唯一性约束名,就用你设定的。

    可以通过show index from 表名称; 查看表的索引

    格式如下:

    SHOW INDEX
    FROM 表名称;
    
    • 1
    • 2

    查看 user 表中的索引

    SHOW INDEX 
    FROM `user`;
    
    • 1
    • 2

    在这里插入图片描述


    使用 ALTER TABLE 中的 DROP 删除索引,删除了索引也就删除了该唯一约束

    格式如下:

    ALTER TABLE 表名
    DROP INDEX 索引名;
    
    • 1
    • 2

    举例子:删除表 user 中的唯一约束

    在这里插入图片描述

    ALTER TABLE `user`
    DROP INDEX up_user_name_pwd;
    
    • 1
    • 2

    查看表约束

    SELECT *
    FROM information_schema.table_constraints
    WHERE table_name = 'user';
    
    • 1
    • 2
    • 3

    在这里插入图片描述


    4. PRIMARY KEY 主键约束

    PRIMARY KEY 主键约束:作用: 用来唯一标识表中的一行记录。主键约束的列/字段,不允许内容重复,同时也不允许出现 NULL空值

    主键约束是一个表中最重要的约束,一个数据表中,可以没有其他所有约束,但是一定要有 主键约束 ,因为主键约束是用来 唯一标识表中的一行记录的存在。没有了 主键 这张数据表就没有了灵魂,没有了意义。

    PRIMARY KEY 主键约束的特点:

    • 主键约束相当于 唯一约束 + 非空约束的组合 ,主键约束列不允许重复,也不允许出现空值

    在这里插入图片描述


    • 一个表中最多只能又一个主键约束,建立主键约束可以在 列级别创建,也可以在表级别上创建
    • 主键约束对应着表中的一列或者多列(复合主键),如果是多列组合的复合主键约束,那么这些都不允许为控制,并且组合的值不允许重复。
    • MySQL的主键名总是 PRIMARY ,就算自己命名了,主键约束名也没用。
    • 当创建主键约束时,系统默认会在所在的列或组合上建立对应的主键索引(能够根据主键查询的,就根据主键查询,效率更高)。如果删除主键约束了,主键约束对应的索引也就自动删除了。
    • 需要注意的一点是,不要修改主键字段的值,因为主键是数据记录的唯一标识,如果修改了主键的值,就有可能会破坏数据的完整性。

    4.1 添加主键约束

    • 在创建表时, CREATE TABLE 添加主键约束 PRIMARY KEY

    格式如下:

    方式1 列级约束

    ALTER TABLE 表名
    (
    字段名1, 数据类型 PRIMARY KEY,
    字段名2, 数据类型
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5

    方式2 表级约束

    ALTER TABLE 表名
    (
    字段名1 数据类型,
    字段名2 数据类型,
    PRIMARY KEY(需要设为的字段名)
    );
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    举例创建表,包含一个主键约束

    CREATE TABLE test5(
    id INT PRIMARY KEY, -- 主键约束
    last_name VARCHAR(15),
    salary DECIMAL(10,2),
    email VARCHAR(25)
    );
    
    DESC test5;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述


    查看表约束

    FROM information_schema.table_constraints
    WHERE table_name = 'test5';
    
    • 1
    • 2

    在这里插入图片描述

    查看表索引

    SHOW INDEX FROM test5;
    
    • 1

    在这里插入图片描述


    插入数据

    INSERT INTO test5(id,last_name,salary,email)
    VALUES (1,'Tom',9000,'tom@126.com');
    
    • 1
    • 2

    在这里插入图片描述


    设定为主键的字段上的内容不可以重复

    INSERT INTO test5(id,last_name,salary,email)
    VALUES (1,'jAA',9000,'jaa@126.com');  -- 报错 主键内容 1重复了
    
    • 1
    • 2

    在这里插入图片描述


    设定为主键的字段,不可插入 NULL空值,不然报错,注意,默认隐式插入空值也一样

    INSERT INTO test5(id,last_name,salary,email)
    VALUES(NULL,'jAA',9000,'jaa@126.com'); -- 报错,主键不可以插入 NULL值
    
    • 1
    • 2

    在这里插入图片描述


    • 创建表之后,在ALTER TABLE 添加 PRIMARY KEY 主键约束。**注意在创建表之后,再定义主键约束中,添加的字段为主键,该字段中不可以 含有重复的内容以及NULL值 ** ,不然,添加主键失败,报错,道理很简单,你要添加主键约束其中字段含有 重复的内容或者 NULL值,自然无法添加 主键。

    格式如下:

    ALTER TABLE 表名
    ADD PRIMARY KEY(字段名);
    
    • 1
    • 2

    举例 重新创建一个表,因为一个表中只能有一个主键约束

    CREATE TABLE test6(
    id INT, 
    last_name VARCHAR(15),
    salary DECIMAL(10,2),
    email VARCHAR(25)
    );
    
    DESC test6;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述


    使用 ALTER TABLE 添加主键约束,的字段内容中不可有重复的内容以及 NULL值,不然无法添加

    ALTER TABLE test6
    ADD PRIMARY KEY(id);
    
    • 1
    • 2

    在这里插入图片描述


    4.2 复合主键约束

    复合主键约束,只能在 表级约束 中创建 ,对多个字段组合成一个 PRIMARY KEY复合主键约束 ,多个字段之间使用逗号分隔开来。

    表级约束 :简单的说就是,创建表时,定义在所有字段的最后面。

    PRIMARY KEY 复合主键约束: 复合主键中包含的字段/列,都不可以为 NULL,只有当复合主键中包含的所有的字段/列中的内容都重复了,才算重复,只是单独中的其中一两字段/列的内容重复了,是不算重复的,是可以插入数据的

    格式如下:

    CREATE TABLE 表名
    (
    字段名1 数据类型 约束,
    字段名2 数据类型,
    字段名3 数据类型 约束,
    PRIMARY KEY(字段名1,字段名2)表示字段1和字段2的组合是唯一的,也可以有更多个字段
    );
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    举例:创建复合主键约束

    CREATE TABLE test7(
    cid INT,
    sid INT,
    `name` VARCHAR(15),
    -- 表级约束
    PRIMARY KEY(cid,sid)  -- cid sid 组合为复合主键
    );
    
    DESC test7;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述


    插入数据

    INSERT INTO test7(cid,sid,`name`)
    VALUES(1,1,'张三'),
          (2,2,'李四'),
          (1,2,'小华'),
          (2,1,'小红');  -- 复合主键中的内容,不是全部重复,一两个重复是没有问题的,可以插入
          
    SELECT *
    FROM test7;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述


    复合主键中字段/列,任意一个都不可插入 NULL 值,不然报错

    INSERT INTO test7(cid,sid,`name`)
    VALUES (NULL,2,'小小');
    
    INSERT INTO test7(cid,sid,`name`)
    VALUES (1,NULL,'小小');
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    在这里插入图片描述


    4.3 删除主键约束

    注意:删除主键约束,不需要指定主键名,因为一个表只有一个主键,删除主键约束后,非空 还存 在

    使用 ALTER TABLE 中的 DROP 来删除主键约束

    格式如下:

    ALTER TABLE 表名
    DROP PRIMARY KEY;  -- 不需要指明主键名,因为一个表中只有一个主键约束
    
    • 1
    • 2

    举例: 删除 表 test7 中的主键约束

    ALTER TABLE test7
    DROP PRIMARY KEY;
    
    • 1
    • 2

    在这里插入图片描述

    在这里插入图片描述


    5. 自增列:AUTO_INCREMENT 约束

    AUTO_INCREMENT 自增列约束。作用: 某个字段的值自增

    AUTO_INCREMENT 约束的特点和要求

    • 一个表中最多只能有一个自增长列 一般配合主键约束使用
    • 当需要产生唯一标识符或顺序值时,可设置自增长
    • 自增长列约束的列必须是键列(主键列或者时唯一键列),一般都是 主键列
    • 自增约束的数据类型必须是整数类型
    • 如果自增列指定了 0 和 NULL,会在当前最大值的基础上自增(并不会插入 0 或者 NULL值),一般没有 NULL,因为一般是和 主键列一起的,如果自增列手动指定了具体值,直接赋值为具体值。

    格式如下:

    CREATE TABLE 表名
    (
    字段名1 整形数据类型 PRIMARY KEY AUTO_INCREMENT,
    字段名2 数据类型
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5

    错误演示:

    1. 自增长列约束必须是和(主键列/唯一键列)使用定义,不然报错
    CREATE TABLE test10(
    id INT AUTO_INCREMENT -- 报错,不是主键列,或唯一键列
    );
    
    • 1
    • 2
    • 3

    在这里插入图片描述


    1. 定义的自增列约束不是整数类型报错
    CREATE TABLE test9(
    id VARCHAR(15) AUTO_INCREMENT  -- 不是整数类型报错
    );
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    1. 一个表中最多只能有一个 自增列约束,多个报错
    CREATE TABLE test9(
    id1 INT PRIMARY KEY AUTO_INCREMENT,
    id2 INT UNIQUE AUTO_INCREMENT
    );
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述


    5.1 添加自增列约束

    • 创建表时,在CREATE TABLE 添加自增列约束,注意:配合主键约束使用,数据类型必须是整形

    格式如下:

    CREATE TABLE 表名 
    (
    字段名1 整型数据类型 PRIMARY KEY AUTO_INCREMENT,   -- 自增约束配合主键约束使用
    字段名2 数据类型
    字段名3 数据类型 约束
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    举例子:创建表

    CREATE TABLE test8 (
    id INT PRIMARY KEY AUTO_INCREMENT,
    last_name VARCHAR(15)
    );
    
    DESC test8;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述


    附有AUTO_INCREMENT 自增列约束的字段中插入 0 或者 NULL,会自动改为添加上自动增加的数值(从1 开始)递增,因为主键不可以为 NULL,

    INSERT INTO test8(id,last_name)
    VALUES (0,'张三'),
           (NULL,'李四');
    
    • 1
    • 2
    • 3

    在这里插入图片描述


    插入数据,在开发中,一旦主键作用的字段上声明了AUTO_INCREMENT 自增列约束时,在添加数据时就不要给主键,对应的字段去赋值了,让自增列约束自己添加。防止,对主键的数值混乱。

    INSERT INTO test8 (last_name) -- 在开发中,一旦主键作用的字段声明有 AUTO_INCREMENT,则我们在添加
    VALUES ('小华'),            -- 数据时不要给主键,对应的字段赋值了,让它自动添加
           ('小红');
    
    • 1
    • 2
    • 3

    在这里插入图片描述


    为自增列插入指定的数值 -1

    INSERT INTO test8(id,last_name)
    VALUES (-1,'测试');
    
    • 1
    • 2

    在这里插入图片描述


    • 建表之后,添加AUTO_INCREMENT自增列约束,使用在ALTER TABLE 中的 MODIFY 修改字段数据类型/属性/约束的方式,添加

    注意:建表后,添加自增列约束的字段必须是 整形数据类型 以及 主键约束/唯一约束,不然无法添加,报错

    格式如下:

    ALTER TABLE 表名
    MODIFY 字段名 整形数据类型 AUTO_INCREMENT;
    
    • 1
    • 2

    举例:为表 tes11 中的 id 添加 自增列约束,注意该字段不是 整形数据类型或者不是主键列/唯一约束 ,无法添加报错

    CREATE TABLE test10 (
    id VARCHAR(15) PRIMARY KEY,
    last_name VARCHAR(15)
    );
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    添加报错
    ALTER TABLE test10
    MODIFY id VARCHAR(15) AUTO_INCREMENT;
    
    • 1
    • 2
    • 3

    在这里插入图片描述


    不是主键约束/唯一约束的同样也是无法添加的,同样报错,这里就不演示了。

    正确添加自增列约束

    CREATE TABLE test11 (
    id INT PRIMARY KEY,
    last_name VARCHAR(15)
    );
    
    DESC test11;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述


    ALTER TABLE test11
    MODIFY id INT AUTO_INCREMENT;
    
    • 1
    • 2

    在这里插入图片描述


    5.2 删除自增列约束

    去掉 AUTO_INCREMENT 就相当于是删除了自增列约束,

    这里我们再次使用,建表后,添加自增列约束的方式,删除自增列约束。

    使用在ALTER TABLE 中的 MODIFY 修改字段数据类型/属性/约束的方式,添加,删除

    格式如下:

    ALTER TABLE 表名
    MODIFY 字段名 数据类型;  -- 去掉AUTO_INCREMENT就相当于删除了该自增列约束了
    
    • 1
    • 2

    举例:删除表 test11 中 id 的自增列约束

    在这里插入图片描述

    ALTER TABLE test11
    MODIFY id INT;
    
    • 1
    • 2

    在这里插入图片描述


    5.3 MySQL 8.0新特性:自增列变量的持久化

    Mysql8.0 之前,自增主键 AUTO_INCREMENT 的值,如果大于 max(primary key) +1,在MySQL重启后,会重置

    AUTO_INCREMENT = max(primary key) +1, 这种现象在某些情况下会导致业务主键冲突或者其他难以发现的问题。

    MySQL 5.7系统中,对于自增主键的分配规则,是由 InnoDB 数据字典内部一个 计数器 来决定的,而该计数器只在 内存中维护,并不会持久化到磁盘中。当数据库重启时,该计数器会被初始化。所以无法做到持久化

    MySQL 8.0 版本的已经将 自增列变量持久化了 。将自增主键的计数器持久化到了重做日志中。每次计数器发生改变,都会将其写入到重做日志中。如果数据库重启,InnoDB 会根据重做日志中的信息来初始化计数器的内存值。从而达到持久化。

    测试步骤如 下: 创建的数据表中包含自增主键的id字段,语句如下:

    CREATE TABLE test (
    id INT PRIMARY KEY AUTO_INCREMENT
    );
    
    DESC test;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述


    插入四个 NULL值,自动转化为 自增列数值,不会插入 NULL

    INSERT INTO test (id)
    VALUES (NULL),
           (NULL),
           (NULL),
           (NULL);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述


    删除 4 ,

    DELETE FROM test
    WHERE id = 4;
    
    • 1
    • 2

    在这里插入图片描述


    我们打开我们 管理员身份的 DOS 命令,输入 net stop mysql 关闭服务器

    net stop mysql
    
    • 1

    在这里插入图片描述

    再使用命令 net start mysql 重启服务器

    net start mysql
    
    • 1

    在这里插入图片描述


    好了,我们再次向原来的,数据表 test 中插入 一个 NULL值

    INSERT INTO test(id)
    VALUES (NULL);
    
    • 1
    • 2

    我们从下图可以看到,插入的不是我们刚刚上面删除的 4 而是,接着从 4 后面递增添加,这就是:MySQL8.0新特性: AUTO_INCREMENT 自增列约束的持久化

    在这里插入图片描述


    6. FOREIGN KEY 外键约束

    FOREIGN KEY 外键约束:作用: 限定某个表的某个字段的引用完整性

    比如:员工表的员工所在部门的选择,必须在部门表能找到对应的部分。不然是无法将数据插入的

    在这里插入图片描述


    主表和从表/父表和子表

    1. 主表(父表): 被引用的表,被参考的表
    2. 从表(子表): 引用别人的表,参考别人的表中的数据

    例如:员工表的员工所在的部门,这个字段的值要参考部门表,而部门表是主表,员工表是从表。

    再例如:学生表,课程表,选课表,其中选课表的学生和课程要分别参考学生表和课程表,学生表和课程表是主表,选课表是从表。

    特点和要求:

    1. 从表的外键列,必须引用/参考主表的主键或唯一约束的列

    因为被依赖/被参考的值必须是唯一的

    1. 在创建外键约束时,如果不给外键约束命名,默认名不是列名,而是自动产生一个外键名比如:student_ibfk_1),也可以指定外键约束名
    2. 使用 CREATE 创建表时,就指定外键约束的话,必须先创建主表,再创建从表

    因为从表中的外键依托于主表中的字段数据

    1. 删表时,先删除从表,或者先删除外键约束,再删除主表

    因为主表中存在与从表中的依赖的数据(外键),导致主表无法删除,需要先将从表的依赖删除了,才能删除主表

    1. 当主表的记录被从表参照时,主表的记录将不允许删除,如果要删除数据,需要先删除从表中依赖该记录的数据,然后才可以删除该主表上的数据。
    2. 在“从表”中指定外键约束,并且一个表可以创建多个外键约束。
    3. 从表的外键列与主表被参照的字段/列的数据类型,约束必须相同,字段名可以不一样也可以一样。从逻辑意义一致,如果类型不一样,创建子表时,就会出现错误:ERROR 1005 (HY000): Can't create table'database.tablename'(errno: 150) 例如:都是表示部门编号,都是必须是 同一类型
    4. 每创建一般外键,MySQL都会自动创建对应的索引
    5. 删除外键约束后,必须手动删除对应的索引
    6. 外键的创建必须在表级约束 中定义

    6.1 添加外键约束

    • 建表时,在CREATE TABLE 添加外键键约束 FOREIGN KEY ,注意建表时,创建外键,必须先创建主表,再创建从表,从表中定义的外键,数据类型,约束必须所依赖的主表上的字段相同,不然无法创建报错

    格式如下:

    方式1:创建外键时,指明外键的约束名

    -- 必须先创建主表
    CREATE TABLE 主表名
    (
    字段名1 数据类型 约束,
    字段名2 数据类型 约束,
    );
    
    -- 必须先创建主表
    CREATE TABLE 从表名 
    (
    字段名1 数据类型 约束,
    字段名2 数据类型 约束,
    字段名3 数据类型 约束,
    -- 表级约束
    CONSTRAINT 外键约束名 FOREIGN KEY (从表中的某个字段名作为外键) REFERENCES 主表名(从表依托的主表中的字段名)
    );
    
    
    -- (从表的某个字段)的数据类型必须与主表名(被参考的字段)的数据类型以及约束一致,逻辑意义也一样
    -- (从表的某个字段)的字段名可以与主表名(被参考字段)的字段名一样,也可以不一样。
    
    -- CONSTRAINT  指明该外键的约束名
    -- FOREIGN KEY: 在表级指定子表(从表)中的列
    -- REFERENCES: 标识在父表(主表)中的列
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    方式2:不指明 外键约束名

    -- 必须先创建主表
    CREATE TABLE 主表名
    (
    字段名1 数据类型 约束,
    字段名2 数据类型 约束,
    );
    
    -- 必须先创建主表
    CREATE TABLE 从表名 
    (
    字段名1 数据类型 约束,
    字段名2 数据类型 约束,
    字段名3 数据类型 约束,
    -- 表级约束   
    FOREIGN KEY (从表中的某个字段名作为外键) REFERENCES 主表名(从表依托的主表中的字段名)
    );  -- 把CONSTRAINT 指明外键约束名去了。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    举例:创建主表 dep ,创建从表 emp ,从表中的 deptid作为外键,依托于主表中的 did

    -- 必须先创建主表
    CREATE TABLE dep (  -- 主表
    did INT PRIMARY KEY, -- 部门编号
    dname VARCHAR(50)    -- 部门名称
    );
    
    DESC dep;
    -- 再创建从表
    CREATE TABLE emp (
    eid INT PRIMARY KEY,  -- 员工编号
    ename VARCHAR(15),    -- 员工姓名
    deptid INT,           -- 员工所在的部门
    -- 表级约束
    CONSTRAINT fk_emp_dept_id FOREIGN KEY(deptid) REFERENCES dep(did)
    );
    DESC emp;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述


    查看表中的约束

    -- 查看表 dep
    SELECT *
    FROM information_schema.table_constraints
    WHERE table_name = 'dep';
    
    -- 查看表 emp
    SELECT *
    FROM information_schema.table_constraints
    WHERE table_name = 'emp';
    
    说明:
    (1)主表dept必须先创建成功,然后才能创建emp表,指定外键成功。
    (2)删除表时,先删除从表emp,再删除主表dept
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    在这里插入图片描述


    **插入数据:**从表外键插入数据,需要依托于主表中的字段的数据才能插入数据

    -- 主表插入数据
    INSERT INTO dep(did,dname)
    VALUES (1001,'教学部'),
           (1002,'财务部');
    
    SELECT *
    FROM dep;
    
    -- 从表插入数据
    INSERT INTO emp(eid,ename,deptid)
    VALUES (1,'张三',1001),
           (2,'李四',1002);
           
    SELECT *
    FROM emp;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述


    插入数据:不可添加外键对于主表中没有的数据。不然会报错

    如:下面,为从表 emp 中的外键中添加 1003数据,可是所依托的主表中该信息,所以无法插入到外键中,报错

    INSERT INTO emp(eid,ename,deptid)
    VALUES (3,'小小',1003);
    
    • 1
    • 2

    在这里插入图片描述


    删除数据:如果主表中的字段含有从表外键的依托时,无法删除该主表中有所外键约束的数据,

    在这里插入图片描述

    DELETE FROM dep
    WHERE did = 1002;
    
    • 1
    • 2

    在这里插入图片描述


    同样主表中含有从表外键依托的字段的数据无法修改,不然

    在这里插入图片描述

    UPDATE dep
    SET did = 1006
    WHERE did = 1002;
    
    • 1
    • 2
    • 3

    在这里插入图片描述


    创建表失败的演示说明例子:

    1. 错误:从表中外键依托的不是主表中的 主键/唯一约束 。无法创建外键报错
    CREATE TABLE dep1 (
    did INT,    -- 部门编号
    dname VARCHAR(15)  -- 部门名称
    );
    
    -- 从表
    CREATE TABLE emp1 (
    eid INT PRIMARY KEY,  -- 员工编号
    dname VARCHAR(15),     -- 员工姓名
    deptid INT    -- 员工所在部门
    CONSTRAINT fk_emp1_dep1_did FOREIGN KEY(deptid) REFERENCES dep1(did)
    );
    
    -- 报错原因: 是dep1的did不是主键/唯一键
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述


    1. 从表定义的外键的数据类型与依托从表中的字段的数据类型不一样,不一致
    -- 主表
    CREATE TABLE dep2 ( 
    did INT PRIMARY KEY,    -- 部门编号
    dname VARCHAR(15)      -- 部门名称
    ); 
    
    -- 从表
    CREATE TABLE emp2 (
    eid INT PRIMARY KEY,    -- 员工编号
    dname VARCHAR(15),      -- 员工姓名
    deptid VARCHAR(15)              -- 员工所在部门
    CONSTRAINT fk_emp1_dep2_did FOREIGN KEY(deptid) REFERENCES dep2(did)
    );
    
    -- 创建的失败的原因: 定义的从表中的主键 deptid 与 依托的主表中的 did 的数据类型不一致。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述


    • 建表之后,添加外键约束:使用:在ALTER TABLE 添加 FOREIGN KEY 主键约束。同样需要满足外键依托的必须是主表中主键/唯一约束 的字段,以及之间的数据类型 ,必须一致,不然无法创建,并报错

    一般情况下,表与表的关联都是提前设计好了的,因此,会在创建表的时候就把外键约束定义好。

    不过,如果需要修改表的设计(比如:添加新的字段,增加新的关联关系),但没有预先定义外键约束,那么,就需要用修改表的方式来补充定义了。

    格式如下:

    指定外键约束名的方式

    ALTER TABLE 表名
    ADD CONSTRAINT 外键约束名 FOREIGN KEY(从表中的需要定义成外键字段名) REFERENCES 主表名(依托主表的字段名);
    
    • 1
    • 2

    也可以不指定外键约束名的方式把: CONSTRAINT 去了

    ALTER TABLE 表名
    ADD FOREIGN KEY(从表中的需要定义成外键字段名) REFERENCES 主表名(依托主表的字段名);
    
    • 1
    • 2

    举例子:

    创建表

    -- 主表
    CREATE TABLE dep4 ( 
    did INT PRIMARY KEY AUTO_INCREMENT,    -- 部门编号
    dname VARCHAR(15)      -- 部门名称
    ); 
    
    DESC dep4;
    
    -- 从表
    CREATE TABLE emp4 (
    eid INT PRIMARY KEY,    -- 员工编号
    dname VARCHAR(15),      -- 员工姓名
    deptid INT              -- 员工所在部门
    );
    
    DESC emp4;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    SELECT *
    FROM information_schema.table_constraints
    WHERE table_name = 'emp4';
    -- 查看约束
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述


    添加外键约束

    ALTER TABLE emp4
    ADD CONSTRAINT fk_emp4_dept4_id FOREIGN KEY(deptid) REFERENCES emp4(eid);
    
    • 1
    • 2

    在这里插入图片描述


    约束关系的总结

    • 约束关系是双向的,
    • 添加了外键约束后,主表的修改和删除数据会受到外键依托约束
    • 添加了外键约束后,从表的添加和修改数据受到了主表中的依托数据的约束
    • 在从表上建立外键,要求主表必须存在
    • 删除主表时,要求从表先删除,或将从表中的外键约束先删除

    6.2 约束等级

    Cascade 方式:在父表上 update/delete 记录时,同步 update/delete 掉子表的匹配记录

    Set null 方式:在父表上update/delete 记录时,将子表上匹配记录的列设为 NULL,但是要注意子表的外键列不能为 not null 非空约束

    NO action 方式:如果子表中有匹配的记录,则不允许对父表对应候选键进行 update/delete 操作

    Restrict 方式:同 no action ,都是立即检查外键约束

    Set default 方式:在可视化工具SQLyog 中可能显示空白 ,父表有变更时,子表将外键列设置成一个默认的值,但 lnnodb 不能识别

    如果没有指定等级,就相当于Restrict方式。

    对于外键约束,最后是采用:ON UPDATE CASCADE ON DELETE RESTRICT 的方式

    演示: ON UPDATE CASCADE ON DELETE RESTRICT 的实例

    -- 主表
    CREATE TABLE deptest( 
    did INT PRIMARY KEY AUTO_INCREMENT,    -- 部门编号
    dname VARCHAR(15)      -- 部门名称
    ); 
    
    -- 从表
    CREATE TABLE emptest (
    eid INT PRIMARY KEY,    -- 员工编号
    dname VARCHAR(15),      -- 员工姓名
    deptid INT,           -- 员工所在的部门
    -- 表级约束
    CONSTRAINT fk_emptest_deptest_id FOREIGN KEY(deptid) REFERENCES deptest(did) ON UPDATE CASCADE ON DELETE SET NULL
    );                
    -- ON UPDATE CASCADE ON DELETE SET NULL 把修改操作设置为级联修改等级,把删除操作设置为set null等级
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述


    插入数据,先将主表中从表所依托的数据插入,再插入从表的数据

    -- 主表插入数据
    INSERT INTO deptest(did,dname)
    VALUES (1001,'教学部'),
           (1002,'财务部'),
           (1003,'咨询部');
           
    SELECT *
    FROM deptest
    
    -- 从表插入数据
    INSERT INTO emptest(eid,dname,deptid)
    VALUES (1,'张三',1001),
           (2,'李四',1003),
           (3,'王五',1002);
           
    SELECT *
    FROM emptest;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述


    修改主表中含有外键约束的字段信息,从表会跟着修改

    UPDATE deptest
    SET did = 1006
    WHERE did = 1002;
    
    • 1
    • 2
    • 3

    在这里插入图片描述


    删除主表中含有外键约束的字段的信息,不会报错,从表中外键记录该信息被置为了 NULL

    DELETE FROM deptest
    WHERE did = 1003;
    
    • 1
    • 2

    在这里插入图片描述


    6.3 删除外键约束

    删除外键必须先删除外键约束,再删除对应的索引

    删除外键约束后,必须手动删除对应的索引

    格式如下:

    -- 第一步先查看需要删除的表中的约束名和删除外键约束
    SELECT * 
    FROM information_schema.table_constraints
    WHERE table_name = '填查看的表名';
    
    -- 再根据查找到的约束名,删除约束
    ALTER TABLE 表名
    DROP FOREIGN KEY 外键约束名;
    
    -- 第二步,看索引名和删除索引。(注意,只能手动删除索引)
    SHOW INDEX FROM 表名;   -- 查看表的索引
    
    ALTER TABLE 表名
    DROP INDEX 索引名;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    举例: 将表 emp 中的 外键约束删除。

    第一步,查看 emp 表的约束名,并删除

    SELECT *
    FROM information_schema.table_constraints
    WHERE table_name = 'emp';
    
    • 1
    • 2
    • 3

    在这里插入图片描述


    删除查询到的约束名,

    ALTER TABLE emp
    DROP FOREIGN KEY fk_emp_dept_id;
    
    • 1
    • 2

    在这里插入图片描述


    第二步,查看表中的外键索引,并把该索引删除了

    SHOW INDEX FROM emp;
    
    • 1

    在这里插入图片描述


    删除索引。

    ALTER TABLE emp
    DROP INDEX fk_emp_dept_id;
    
    • 1
    • 2

    在这里插入图片描述


    6.4 外键开发总结

    问题1: 如果两个表之间有关系 (一对一,一对多),比如:员工表和部门表(一对多),它们之间是否一定要键外键约束 ???

    答,不是

    问题2: 建和不建外键约束有什么区别?

    答:建外键约束,你的操作(创建表,删除表,添加,修改,删除)会受到限制,从语法层面受到限制,例如:

    在员工表中不可能添加一个员工信息,它的部门的值在部门表中找不到。不建外键约束,你的操作(创建表,删除表,添加,修改,删除) 不受限制,要保证数据的引用完整性,只能依靠程序员的自觉,或者是 Java程序中进行限定。例如:在员工表中,可以添加一个员工的信息,它的部门指定为一个完全不存在的部门。


    问题3: 那么建和不建外键约束和查询有没有关系?

    答:没有关系


    注意:

    在MySQL里,外键约束是有成本的,需要消耗系统资源。对于 大并发 的 SQL 操作,有可能不适合。

    比如大型网站的中央数据库,可能会因为外键约束的系统开销而变得非常慢。所以,MySQL允许你不使用系统自带的外键约束而是在应用层面 完成检查数据一致性的逻辑,也就是说,即使你不用外键约束,也要想办法通过应用层面上的附加逻辑,来实现外键约束的功能,确保数据的一致性

    阿里开发规范

    不得使用外键与级联,一切外键概念必须在应用层解决

    解释: 例如:学生表中 student_id 是主键,那么成绩表中的 student_id 则为外键。

    如果更新学生表中的 student_id ,同时触发成绩表中的 student_id更新,即为级联更新

    外键与级联更新适用于单机低并发,不适合 分布式,高并发集群;级联更新 是强阻塞,存在数据库 更新风暴 的风险,外键影响数据库的 插入速度。所以强制不推荐使用 外键约束

    所以,外键说了,这么多,结果却不推荐使用,而是从应用层面上实现逻辑上的外键约束。呵呵

    7. CHECK 约束 范围数值约束

    CHECK 约束:作用: 检查某个字段的值是否符号xx要求,一般指的是值的范围

    MySQL5.7 可以使用 check 约束,但 check 约束对数据验证没有任何的作用。添加数据时,没有任何错误或警告,但是MySQL 8.0 中可以使用 check 约束。

    格式如下:

    CREATE TABLE 表名
    (
    字段名1 数据类型 CHECK( 字段名1 > 10000),
    字段名2 数据类型 CHECK( 字段名2 > 10000 AND 字段名2 < 1000000000),
    字段名3 数据类型 CHECK( 字段名3 > 10000 OR 字段名3 < 100000000)
    );
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    举例:创建表

    CREATE TABLE test12 (
    id INT CHECK (id > 0),
    last_name VARCHAR(15),
    salary DECIMAL(10,2) CHECK( salary > 10000 AND 1000000000)
    );
    
    DESC test12;
    
    -- 查看表约束
    SELECT *
    FROM information_schema.table_constraints
    WHERE table_name = 'test12';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述


    插入数据,

    INSERT INTO test12(id,last_name,salary)
    VALUES (1,'Tom',12000),
           (2,'张三',20000);
    
    • 1
    • 2
    • 3

    在这里插入图片描述


    当插入的数据,不符合 check 约束条件报错

    INSERT INTO test12(id,last_name,salary)
    VALUES (-1,'测试',1000000);
    
    • 1
    • 2

    在这里插入图片描述


    8. DEFAULT 默认值约束

    DEFAULT 默认值约束,作用: 给某个字段/某列指定默认值,一旦设置默认值,在插入数据时,如果此字段没有显式赋值,则赋值为默认值。

    默认没有添加的默认值约束的字段,默认都是 NULL

    说明:默认值约束一般不在唯一键和主键列上加 添加了,

    8.1 添加默认值约束

    建表时,使用 CREATE TABLE 创建表时,添加默认值约束

    格式如下:

    CREATE TABLE 表名
    (
    字段名1 数据类型 DEFAULT 设定默认数值,
    字段名2 数据类型 
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5

    举例:创建表附加默认约束

    CREATE TABLE test15 (
    id INT,
    last_name VARCHAR(15),
    salary DECIMAL(10,2) DEFAULT 10000
    );
    
    DESC test15;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述


    插入数据

    显示插入默认值数据

    INSERT INTO test15 (id,last_name,salary)
    VALUES (1,'张三',DEFAULT),
           (2,'李四',20000);
    
    • 1
    • 2
    • 3

    在这里插入图片描述


    隐式插入默认值数据,省略对含有默认值字段的声明

    INSERT INTO test15(id,last_name) -- 省略 salary 声明,隐式插入默认值数据
    VALUES (3,'王五');
    
    • 1
    • 2

    在这里插入图片描述


    建表之后,添加默认值约束,在ALTER TABLE 中的MODIFY添加默认值约束

    注意: 默认值约束,不可以添加到已经含有 主键,或者唯一性约束中,存在冲突,虽然可以添加成功,但是没有意义

    格式如下:

    ALTER TABLE 表名
    MODIFY 字段名  数据类型 DEFAULT;
    
    • 1
    • 2

    举例:创建表

    CREATE TABLE test17 ( 
    id INT PRIMARY KEY,  -- 主键约束
    last_name VARCHAR(15),
    cid INT UNIQUE,   -- 唯一约束
    salary DECIMAL(10,2)
    );
    
    DESC test17;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述


    添加默认值约束

    ALTER TABLE test17
    MODIFY salary DECIMAL(10,2) DEFAULT 10000;
    
    • 1
    • 2

    在这里插入图片描述


    注意不可在已经含有 PRIMARY KEY主键约束的字段中,再添加DEFAULT默认值约束了,它们之间存在冲突,虽然可以添加成功,但是没有意义。

    ALTER TABLE test17
    MODIFY cid INT DEFAULT 10000;
    
    • 1
    • 2

    在这里插入图片描述


    8.2 删除默认值约束

    同样使用 在ALTER TABLE 中的 MODIFY删除默认值约束,

    需要 注意的是,如果含有默认值约束的字段同时又含有 not null非空约束的,删除默认值约束的同时也会把not null 非空约束给删除了 ,因为它们两个约束的删除方式是一样的。当然我们也可以保留 not null 非空约束,不被删除

    方式一:删除默认约束的同时会将not null 非空约束删除

    ALTER TABLE 表名
    MODIFY 字段名 数据类型;   -- 把默认约束去了,就是删除了,同时会把 非空约束删除了
    
    • 1
    • 2

    方式二:删除默认约束的,保留 not null 非空约束

    ALTER TABLE 表名
    MODIFY 字段名 数据类型 NOT NULL; -- 把默认约束删除了,保留为空约束
    
    • 1
    • 2

    举例:

    在这里插入图片描述

    ALTER TABLE test17
    MODIFY salary DECIMAL(10,2);
    
    • 1
    • 2

    在这里插入图片描述


    9. 面试题

    面试1: 为什么建表时,加 not null default '’ 或 default 0

    答:是为了不让表中出现 NULL

    面试2: 为什么不想要 null 的值

    1. 不好比较,NULL 是一种特殊值,比较时,只能用专门的 IS NULLIS NOT NULL 来比较。碰到

    运算符,通常返回 NULL,

    1. 效率不高,影响提高索引效果,因此,我们往往在建表时 NOT NULL DEFAUIT 或者 DEFAUIT 0 来避免它

    面试3: 带AUTO_INCREMENT约束的字段值是从1开始的吗?

    答不是的。在MySQL中,默认 AUTO_INCREMENT 的初始值是1,每新增一条记录,字段值自动 +1

    设置自增属性(AUTO_INCREMENT) 的时候,还可以指定第一条插入记录的自增字段的值,这样新插入的记录的自增字段值,从初值值开始递增。

    如:在表中插入第一条记录,同时指定 id 值为 5 的话,则以后插入的记录的 id 值就会从 6 开始往上增加。添加主键约束时,往往需要设置字段自动增加属性。

    面试4: 并不是每个表都可以任意选择存储引擎吗 ?

    外键约束(FOREIGN KEY) 不能跨引擎使用,MySQL支持多种存储引擎,每个表都可以指定一个不同的存储引擎,需要注意的是:外键约束是用来保证数据的参照完整性的。

    如果表之间需要关联外键,却指定了不同的存储引擎,那么这些表之间是不能创建外键约束的。

    所以说,存储引擎的选择也不完全是随意的。至少外键约束不行


    10. 最后:

    限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见 !!!


    在这里插入图片描述

  • 相关阅读:
    服务为中心,产品为素材,与消费者双向交流的经销存经营管理软件
    初识进程状态
    论文阅读笔记:Instance-Aware Dynamic Neural Network Quantization
    在 Android Studio 中为 C++ 设置 OpenCV(4.6.0)
    2023年【通信安全员ABC证】找解析及通信安全员ABC证考试总结
    uniapp Android如何打开常用系统设置页面?
    Google Earth Engine(GEE)——计算特定区域得每年特点月份得1985-2021年得ndvi影像值
    高薪程序员&面试题精讲系列115之Redis缓存如何实现?怎么发现热key?缓存时可能存在哪些问题?
    10. java的servlet+JSP总结
    js-算法题-移动0
  • 原文地址:https://blog.csdn.net/weixin_61635597/article/details/126909294