• MySQL【约束】


    目录

    一、约束概述

    为什么要约束

    约束是什么 

    约束的分类 

    如何添加、删除约束 

    如何查看已有的约束

    二、非空约束

    1.在建表时添加非空约束 

    2.在ALTER TABLE是添加非空约束

    3.在ALTER TABLE删除约束

    三、唯一性约束

    1.在建表时创建唯一性约束 

    如何查看唯一性约束

    2.在ALTER TABLE时添加唯一性约束

    复合的唯一性约束

    例子

    删除唯一性约束

    四、主键约束

    在创建表时添加主键 

    复合主键

    在ALTER TABLE中添加主键

    如何删除主键约束

    五、自增列

    建表时创建自增列 

    在ALTER TABLE时添加自增列

    删除自增列 

    自增变量的持久化 

    六、FOREIGN KEY约束 

    建表时添加FOREIGN KEY 

    在ALTER TABLE时添加FOREIGN KEY

    约束等级 

     Cascade方式 :

    删除外键约束 

    使用场景

    七、CHECK约束

    八、default约束

    在建表时创建default约束 

    在ALTER TABLE中创建DEFAULT约束

    删除DEFAULT约束

    一些问题


    一、约束概述

    为什么要约束

    数据完整性(Data Integrity)是指数据的精确性(Accuracy)和可靠性(Reliability)。它是防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息而提出的。
    为了保证数据的完整性,SQL规范以约束的方式对表数据进行额外的条件限制。从以下四个方面考虑:

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

    约束是什么 

    约束是表级的强制规定。是对表中字段的限制
    可以在创建表时规定约束(通过 CREATE TABLE 语句),或者在表创建之后通过 ALTER TABLE 语句规定约束。 

    约束的分类 

    根据约束数据列的限制,约束可分为:
            单列约束:每个约束只约束一列
            多列约束:每个约束可约束多列数据
    根据约束的作用范围,约束可分为:
            列级约束:只能作用在一个列上,跟在列的定义后面(将此约束声明在对应字段的后面)
            表级约束:可以作用在多个列上,不与列一起,而是单独定义(在表中所有字段都声明完,在所有字段的后面声明的约束)    

      

    根据约束起的作用,约束可分为:
            NOT NULL 非空约束,规定某个字段不能为空
            UNIQUE 唯一约束,规定某个字段在整个表中是唯一的
            PRIMARY KEY 主键(非空且唯一)约束
            FOREIGN KEY 外键约束
            CHECK 检查约束
            DEFAULT 默认值约束 

    如何添加、删除约束 

    在CREATE TABLE时添加约束

    在ALTER TABLE时增加约束、删除约束

    如何查看已有的约束

    1. #2. 如何查看表中的约束
    2. SELECT * FROM information_schema.table_constraints
    3. WHERE table_name = '表名';

    二、非空约束

    限定某个字段/某列的值不允许为空

    关键字
    NOT NULL

    特点
    默认,所有的类型的值都可以是NULL,包括INT、FLOAT等数据类型
    非空约束只能出现在表对象的列上,只能某个列单独限定非空,不能组合非空
    一个表可以有很多列都分别限定了非空
    空字符串''不等于NULL,0也不等于NULL 

    1.在建表时添加非空约束 

    1. # not null (非空约束)
    2. # 在CREATE TABLE时添加约束
    3. CREATE TABLE test1(
    4. id INT NOT NULL,
    5. last_name VARCHAR(15) NOT NULL,
    6. email VARCHAR(25),
    7. salary DECIMAL(10,2)
    8. );
    9. DESC test1;

    从下面表的结构中可以看出我们的id字段和last_name字段已经不允许填充空值了 

     

     

    1. INSERT INTO test1(id,last_name,email,salary)
    2. VALUES(1,'催逝员','cuishiyuan@126.com',3400);
    3. SELECT * FROM test1;

     如果在我们刚刚设置的非空的字段输入空的数据,就会报错。

    1. #错误:Column 'last_name' cannot be null
    2. INSERT INTO test1(id,last_name,email,salary)
    3. VALUES(2,NULL,'wangdaduizhang1@126.com',3400);
    1. #错误:Column 'id' cannot be null
    2. INSERT INTO test1(id,last_name,email,salary)
    3. VALUES(NULL,'薛总司令','xuezongsiling@126.com',3400);
    1. #错误,没有给另外两个参数赋值,另外两个参数就是null,而之前设置的又是非空
    2. INSERT INTO test1(id,email)
    3. VALUES(2,'abc@126.com');
    1. #也不能在更新数据的时候给我们之前设置为非空的字段添加空值
    2. UPDATE test1
    3. SET last_name = NULL
    4. WHERE id = 1;

    2.在ALTER TABLE是添加非空约束

    1. ALTER TABLE test1
    2. MODIFY email VARCHAR(25) NOT NULL;

    注意要是我们原来的email字段中有null值,是不允许我们这样直接将email修改为非空字段的。 

     也就是说如果我们原来的表为如下情况

     

    再运行我们之前将email字段修改为非空的代码的时候就会报告如下的错误 

     

    3.在ALTER TABLE删除约束

     

    1. #在ALTER TABLE时删除约束
    2. ALTER TABLE test1
    3. MODIFY email VARCHAR(25) NULL;
    4. desc test1

    这里我们看到原先是非空的email字段此刻变成了可以为空值 

    三、唯一性约束

    用来限制某个字段/某列的值不能重复。

    关键字
    UNIQUE

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

    1.在建表时创建唯一性约束 

    1. # 在CREATE TABLE时添加约束
    2. CREATE TABLE test2(
    3. id INT UNIQUE, #列级约束
    4. last_name VARCHAR(15) ,
    5. email VARCHAR(25),
    6. salary DECIMAL(10,2),
    7. #表级约束
    8. CONSTRAINT uk_test2_email UNIQUE(email)
    9. );
    10. DESC test2;

     

    如何查看唯一性约束

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

    我们发现刚刚对ID的列级约束的约束名还是ID,而我们给email定的表级约束就变成了我们给它起的别名uk_test2_email 

     

    1. INSERT INTO test2(id,last_name,email,salary)
    2. VALUES(1,'催逝员','cuishiyuan@126.com',4500);
    3. select * from test2;

     

    这时如果我们再添加ID编号为1的记录就会报错 

    1. #错误:Duplicate entry '1' for key 'test2.id'
    2. INSERT INTO test2(id,last_name,email,salary)
    3. VALUES(1,'王大队长','wangdaduizhang@126.com',4600);

     

     如果我们的薛总司令的邮箱号和催逝员的一样也会报错。

    1. #错误:Duplicate entry
    2. INSERT INTO test2(id,last_name,email,salary)
    3. VALUES(2,'薛总司令','cuishiyuan@126.com',4600);

     

    1. #可以向声明为unique的字段上添加null值。而且可以多次添加null
    2. INSERT INTO test2(id,last_name,email,salary)
    3. VALUES(2,'老冯',NULL,4600);
    4. INSERT INTO test2(id,last_name,email,salary)
    5. VALUES(3,'穿山甲',NULL,4600);
    6. SELECT * FROM test2;

    从下面的测试结果中可以看出null是不算在unique的约束里面的。 

    2.在ALTER TABLE时添加唯一性约束

     如果当前要添加唯一约束性的字段中的数据并不是唯一的,就会报错

     

    1. #方式1
    2. ALTER TABLE test2
    3. ADD CONSTRAINT uk_test2_sal UNIQUE(salary);
    4. DESC TEST2;

    1. #方式2
    2. ALTER TABLE test2
    3. MODIFY last_name VARCHAR(15) UNIQUE;
    4. DESC TEST2

     

    复合的唯一性约束

     又是我们需要多个字段组合在一起的内容变成一个唯一的约束,就需要用到复合的唯一性约束。

    1. #复合的唯一性约束
    2. CREATE TABLE USER(
    3. id INT,
    4. `name` VARCHAR(15),
    5. `password` VARCHAR(25),
    6. #表级约束
    7. #这里我们将name和password组合成的一整个整体形成了一个复合型约束
    8. CONSTRAINT uk_user_name_pwd UNIQUE(`name`,`password`)
    9. );
    10. DESC USER;

     

    1. INSERT INTO USER
    2. VALUES(1,'催逝员','abc');
    3. #可以成功的:
    4. INSERT INTO USER
    5. VALUES(1,'王大队长','abc');
    6. SELECT *
    7. FROM USER;

    1. #这时如果我们再添加一条这样和上面完全重复的记录,就会报错
    2. INSERT INTO USER
    3. VALUES(1,'王大队长','abc');

    例子

    1. #案例:复合的唯一性约束的案例
    2. #学生表
    3. CREATE TABLE student(
    4. sid INT, #学号
    5. sname VARCHAR(20), #姓名
    6. tel CHAR(11) UNIQUE KEY, #电话
    7. cardid CHAR(18) UNIQUE KEY #身份证号
    8. );
    9. #课程表
    10. CREATE TABLE course(
    11. cid INT, #课程编号
    12. cname VARCHAR(20) #课程名称
    13. );
    14. #选课表
    15. CREATE TABLE student_course(
    16. id INT,
    17. sid INT, #学号
    18. cid INT, #课程编号
    19. score INT,
    20. UNIQUE KEY(sid,cid) #复合唯一
    21. );
    1. INSERT INTO student VALUES(1,'张三','13710011002','101223199012015623');#成功
    2. INSERT INTO student VALUES(2,'李四','13710011003','101223199012015624');#成功
    3. INSERT INTO course VALUES(1001,'Java'),(1002,'MySQL');#成功
    4. SELECT * FROM student;

    SELECT * FROM course;

    1. INSERT INTO student_course VALUES
    2. (1, 1, 1001, 89),
    3. (2, 1, 1002, 90),
    4. (3, 2, 1001, 88),
    5. (4, 2, 1002, 56);#成功
    6. SELECT * FROM student_course;

     

     因为我们之前设置的学号和课程编号的组合应该是唯一的,所以在下面我们输入了一个重复的组合后就会报错。

    1. #错误:Duplicate entry '2-1002' for key 'student_course.sid'
    2. INSERT INTO student_course VALUES
    3. (5,2,1002,67);

     

    删除唯一性约束

    1. #4.4 删除唯一性约束
    2. -- 添加唯一性约束的列上也会自动创建唯一索引。
    3. -- 删除唯一约束只能通过删除唯一索引的方式删除。
    4. -- 删除时需要指定唯一索引名,唯一索引名就和唯一约束名一样。
    5. -- 如果创建唯一约束时未指定名称,如果是单列,就默认和列名相同;如果是组合列,那么默认和()中排在第一个的列名相同。也可以自定义唯一性约束名。

    这是我们当前的表中的索引。其中sid跟我们上面设置的符合索引中的第一个小括号中的第一个参数是一样的。 

    1. SELECT * FROM information_schema.table_constraints
    2. WHERE table_name = 'student_course';

     

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

     

    DESC test2;

     

    1. #如何删除唯一性索引
    2. ALTER TABLE test2
    3. DROP INDEX last_name;
    4. ALTER TABLE test2
    5. DROP INDEX uk_test2_sal;

     

    四、主键约束

    用来唯一标识表中的一行记录

    关键字
    primary key 

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

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

    主键只能声明一个,如果声明多个就会报错 

    在创建表时添加主键 

    1. # primary key (主键约束)
    2. # 在CREATE TABLE时添加约束
    3. #一个表中最多只能有一个主键约束。
    4. #错误:Multiple primary key defined
    5. CREATE TABLE test3(
    6. id INT PRIMARY KEY, #列级约束
    7. last_name VARCHAR(15) PRIMARY KEY,
    8. salary DECIMAL(10,2),
    9. email VARCHAR(25)
    10. );

     

    1. # 主键约束特征:非空且唯一,用于唯一的标识表中的一条记录。
    2. CREATE TABLE test4(
    3. id INT PRIMARY KEY, #列级约束
    4. last_name VARCHAR(15),
    5. salary DECIMAL(10,2),
    6. email VARCHAR(25)
    7. );
    8. DESC TEST4;

     

     

    1. #MySQL的主键名总是PRIMARY,就算自己命名了主键约束名也没用。
    2. CREATE TABLE test5(
    3. id INT ,
    4. last_name VARCHAR(15),
    5. salary DECIMAL(10,2),
    6. email VARCHAR(25),
    7. #表级约束
    8. CONSTRAINT pk_test5_id PRIMARY KEY(id) #没有必要起名字。
    9. );
    10. SELECT * FROM information_schema.table_constraints
    11. WHERE table_name = 'test5';

     

    1. INSERT INTO test4(id,last_name,salary,email)
    2. VALUES(1,'催逝员',4500,'cuishiyuan@126.com');
    3. SELECT * FROM TEST4;

    id重复,违反主键的唯一性原则 

    1. #错误:Duplicate entry '1' for key 'test4.PRIMARY'
    2. INSERT INTO test4(id,last_name,salary,email)
    3. VALUES(1,'催逝员',4500,'cuishiyuan@126.com');

     

     错误,违反主键非空的原则

    1. #错误:Column 'id' cannot be null
    2. INSERT INTO test4(id,last_name,salary,email)
    3. VALUES(NULL,'催逝员',4500,'cuishiyuan@126.com');

     

    复合主键

    1. CREATE TABLE user1(
    2. id INT,
    3. NAME VARCHAR(15),
    4. PASSWORD VARCHAR(25),
    5. PRIMARY KEY (NAME,PASSWORD)
    6. );
    7. DESC USER1;

    1. #如果是多列组合的复合主键约束,那么这些列都不允许为空值,并且组合的值不允许重复。
    2. INSERT INTO user1
    3. VALUES(1,'催逝员','abc');
    4. INSERT INTO user1
    5. VALUES(1,'穿山甲','abc');
    6. SELECT * from user1;

     

    如果这两个联合形成的主键中有一个为空就报错 

    1. #错误:Column 'name' cannot be null
    2. INSERT INTO user1
    3. VALUES(1,NULL,'abc');
    4. SELECT * FROM user1;

     

    在ALTER TABLE中添加主键

    1. CREATE TABLE test6(
    2. id INT ,
    3. last_name VARCHAR(15),
    4. salary DECIMAL(10,2),
    5. email VARCHAR(25)
    6. );
    7. DESC test6;
    1. ALTER TABLE test6
    2. ADD PRIMARY KEY (id);
    3. DESC test6;

    如何删除主键约束

    虽然我们删除了主键但是其null字段还是要求我们非空的。

    1. #5.3 如何删除主键约束 (在实际开发中,不会去删除表中的主键约束!)
    2. ALTER TABLE test6
    3. DROP PRIMARY KEY;
    4. DESC TEST6;

    五、自增列

    某个字段的值自增

    关键字:auto_increment 

    特点和要求
    (1)一个表最多只能有一个自增长列
    (2)当需要产生唯一标识符或顺序值时,可设置自增长
    (3)自增长列约束的列必须是键列(主键列,唯一键列)
    (4)自增约束的列的数据类型必须是整数类型
    (5)如果自增列指定了 0 和 null,会在当前最大值的基础上自增;如果自增列手动指定了具体值,直接赋值为具体值。

    建表时创建自增列 

    1. # 自增长列:AUTO_INCREMENT
    2. # 在CREATE TABLE时添加
    3. CREATE TABLE test7(
    4. id INT PRIMARY KEY AUTO_INCREMENT,
    5. last_name VARCHAR(15)
    6. );
    7. DESC TEST7;

    1. #开发中,一旦主键作用的字段上声明有AUTO_INCREMENT,则我们在添加数据时,就不要给主键
    2. #对应的字段去赋值了。
    3. INSERT INTO test7(last_name)
    4. VALUES('催逝员');
    5. SELECT * FROM test7;

     

    1. INSERT INTO TEST7(LAST_NAME)
    2. VALUES('老冯');
    3. INSERT INTO TEST7(LAST_NAME)
    4. VALUES('穿山甲');
    5. SELECT * FROM test7;

     

    1. #当我们向主键(含AUTO_INCREMENT)的字段上添加0null时,实际上会自动的往上添加指定的字段的数值
    2. INSERT INTO test7(id,last_name)
    3. VALUES(0,'催逝员');
    4. INSERT INTO test7(id,last_name)
    5. VALUES(NULL,'催逝员');

    我们也可以指定我们的自增值 

    1. INSERT INTO test7(id,last_name)
    2. VALUES(10,'催逝员');
    3. INSERT INTO test7(id,last_name)
    4. VALUES(-10,'催逝员');

     

    如果我们这时候再插入一条不包含ID的值,就会直接在我们原来10的基础上累加,变成11 

    1. INSERT INTO TEST7(LAST_NAME)
    2. VALUES('穿山甲');
    3. SELECT * FROM test7;

    在ALTER TABLE时添加自增列

     

    1. #在ALTER TABLE 时添加
    2. CREATE TABLE test8(
    3. id INT PRIMARY KEY ,
    4. last_name VARCHAR(15)
    5. );
    6. DESC test8;

    1. ALTER TABLE test8
    2. MODIFY id INT AUTO_INCREMENT;
    3. DESC test8;

     

    删除自增列 

    1. #在ALTER TABLE 时删除
    2. ALTER TABLE test8
    3. MODIFY id INT ;
    4. DESC test8;

    自增变量的持久化 

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

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

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

    六、FOREIGN KEY约束 

    限定某个表的某个字段的引用完整性。
    比如:员工表的员工所在部门的选择,必须在部门表能找到对应的部分。

    关键字
    FOREIGN KEY 

    主表和从表/父表和子表
    主表(父表):被引用的表,被参考的表
    从表(子表):引用别人的表,参考别人的表
    例如:员工表的员工所在部门这个字段的值要参考部门表:部门表是主表,员工表是从表
    例如:学生表、课程表、选课表:选课表的学生和课程要分别参考学生表和课程表,学生表和课程表是主表,选课表是从表。 

    特点
    (1)从表的外键列,必须引用/参考主表的主键或唯一约束的列
    为什么?因为被依赖/被参考的值必须是唯一的
    (2)在创建外键约束时,如果不给外键约束命名,默认名不是列名,而是自动产生一个外键名(例如student_ibfk_1;),也可以指定外键约束名。
    (3)创建(CREATE)表时就指定外键约束的话,先创建主表,再创建从表
    (4)删表时,先删从表(或先删除外键约束),再删除主表
    (5)当主表的记录被从表参照时,主表的记录将不允许删除,如果要删除数据,需要先删除从表中依赖该记录的数据,然后才可以删除主表的数据
    (6)在“从表”中指定外键约束,并且一个表可以建立多个外键约束
    (7)从表的外键列与主表被参照的列名字可以不相同,但是数据类型必须一样,逻辑意义一致。如果类型不一样,创建子表时,就会出现错误“ERROR 1005 (HY000): Can't create
    table'database.tablename'(errno: 150)”。 

    (8)当创建外键约束时,系统默认会在所在的列上建立对应的普通索引。但是索引名是列名,不是外键的约束名。(根据外键查询效率很高)。

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

    建表时添加FOREIGN KEY 

    1. #下面的代码中因为没有将dept_id设置为主键,所以会报错
    2. #①先创建主表
    3. CREATE TABLE dept1(
    4. dept_id INT,
    5. dept_name VARCHAR(15)
    6. );
    7. #②再创建从表
    8. CREATE TABLE emp1(
    9. emp_id INT PRIMARY KEY AUTO_INCREMENT,
    10. emp_name VARCHAR(15),
    11. department_id INT,
    12. #表级约束
    13. CONSTRAINT fk_emp1_dept_id FOREIGN KEY (department_id) REFERENCES dept1(dept_id)
    14. );

    1. #上述操作报错,因为主表中的dept_id上没有主键约束或唯一性约束。
    2. #③ 添加
    3. ALTER TABLE dept1
    4. ADD PRIMARY KEY (dept_id);
    5. DESC dept1;
    6. #添加之后把上面创建从表的代码重新运行一下

     

    DESC emp1;

     

    1. SELECT * FROM information_schema.table_constraints
    2. WHERE table_name = 'emp1';

    1. #添加失败
    2. INSERT INTO emp1
    3. VALUES(1001,'催逝员',10);
    4. #

    此时我们呢根本就没有十号部门,当然没有办法添加部门成员 

     

    1. INSERT INTO dept1
    2. VALUES(10,'IT');
    3. #在主表dept1中添加了10号部门以后,我们就可以在从表中添加10号部门的员工
    4. INSERT INTO emp1
    5. VALUES(1001,'催逝员',10);
    6. SELECT * FROM EMP1;

     

    1. #删除失败
    2. #因为有一个外键约束
    3. DELETE FROM dept1
    4. WHERE dept_id = 10;
    5. #更新失败
    6. UPDATE dept1
    7. SET dept_id = 20
    8. WHERE dept_id = 10;

     

    在ALTER TABLE时添加FOREIGN KEY

     

    1. # 在ALTER TABLE时添加外键约束
    2. CREATE TABLE dept2(
    3. dept_id INT PRIMARY KEY,
    4. dept_name VARCHAR(15)
    5. );
    6. CREATE TABLE emp2(
    7. emp_id INT PRIMARY KEY AUTO_INCREMENT,
    8. emp_name VARCHAR(15),
    9. department_id INT
    10. );
    11. ALTER TABLE emp2
    12. ADD CONSTRAINT fk_emp2_dept_id FOREIGN KEY(department_id) REFERENCES dept2(dept_id);
    13. SELECT * FROM information_schema.table_constraints
    14. WHERE table_name = 'emp2';

     

    约束等级 

    Cascade方式 :在父表上update/delete记录时,同步update/delete掉子表的匹配记录
    Set null方式 :在父表上update/delete记录时,将子表上匹配记录的列设为null,但是要注意子表的外键列不能为not null
    No action方式 :如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作
    Restrict方式 :同no action, 都是立即检查外键约束
    Set default方式 (在可视化工具SQLyog中可能显示空白):父表有变更时,子表将外键列设置成一个默认的值,但Innodb不能识别
    如果没有指定等级,就相当于Restrict方式。
    对于外键约束,最好是采用: ON UPDATE CASCADE ON DELETE RESTRICT 的方式。

     Cascade方式 :

    1. #演示:
    2. # on update cascade on delete set null
    3. CREATE TABLE dept(
    4. did INT PRIMARY KEY, #部门编号
    5. dname VARCHAR(50) #部门名称
    6. );
    7. CREATE TABLE emp(
    8. eid INT PRIMARY KEY, #员工编号
    9. ename VARCHAR(5), #员工姓名
    10. deptid INT, #员工所在的部门
    11. FOREIGN KEY (deptid) REFERENCES dept(did) ON UPDATE CASCADE ON DELETE SET NULL
    12. #把修改操作设置为级联修改等级,把删除操作设置为set null等级
    13. );
    1. INSERT INTO dept VALUES(1001,'教学部');
    2. INSERT INTO dept VALUES(1002, '财务部');
    3. INSERT INTO dept VALUES(1003, '咨询部');
    4. SELECT * FROM dept;

     

    1. INSERT INTO emp VALUES(1,'张三',1001); #在添加这条记录时,要求部门表有1001部门
    2. INSERT INTO emp VALUES(2,'李四',1001);
    3. INSERT INTO emp VALUES(3,'王五',1002);
    4. SELECT * FROM emp;

     

     

    1. UPDATE dept
    2. SET did = 1004
    3. WHERE did = 1002;
    4. SELECT * FROM emp;

    我们将dept表中的1002编号改成1004之后,我们的从表emp表中的1002也变成了1004 

     

    1. DELETE FROM dept
    2. WHERE did = 1004;
    3. SELECT * FROM emp;

    我们将主表中的1004删除掉之后,我们从边中的dept就变成了null。

    删除外键约束 

    1. USE dbtest13;
    2. SELECT * FROM information_schema.table_constraints
    3. WHERE table_name = 'emp1';

     

    1. #删除外键约束
    2. ALTER TABLE emp1
    3. DROP FOREIGN KEY fk_emp1_dept_id;

     

    1. #再手动的删除外键约束对应的普通索引
    2. SHOW INDEX FROM emp1;

    1. ALTER TABLE emp1
    2. DROP INDEX fk_emp1_dept_id;

     

    使用场景

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


    问题2:建和不建外键约束有什么区别?
    答:建外键约束,你的操作(创建表、删除表、添加、修改、删除)会受到限制,从语法层面受到限制。例如:在员工表中不可能添加一个员工信息,它的部门的值在部门表中找不到。不建外键约束,你的操作(创建表、删除表、添加、修改、删除)不受限制,要保证数据的 引用完整性 ,只能依 靠程序员的自觉 ,或者是 在Java程序中进行限定 。例如:在员工表中,可以添加一个员工的信息,它的部门指定为一个完全不存在的部门。
    问题3:那么建和不建外键约束和查询有没有关系?


    答:没有

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

    阿里开发规范
    【 强制 】不得使用外键与级联,一切外键概念必须在应用层解决。
    说明:(概念解释)学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于 单机低并发 ,不适合 分布式 、 高并发集群 ;级联更新是强阻塞,存在数据库 更新风暴 的风险;外键影响数据库的 插入速度 。 

    七、CHECK约束

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

     关键字
    CHECK

    说明:MySQL 5.7 不支持
    MySQL5.7 可以使用check约束,但check约束对数据验证没有任何作用。添加数据时,没有任何错误或警告

    但是MySQL 8.0中可以使用check约束了。 

    这里我们指定最低工资要大于2000 

    1. # check 约束
    2. # MySQL5.7 不支持CHECK约束,MySQL8.0支持CHECK约束。
    3. CREATE TABLE test10(
    4. id INT,
    5. last_name VARCHAR(15),
    6. salary DECIMAL(10,2) CHECK(salary > 2000)
    7. );
    8. DESC TEST10;

     

    1. INSERT INTO test10
    2. VALUES(1,'催逝员',2500);
    3. SELECT * FROM TEST10;

     

    如果低于最低工资,就会添加失败 

    1. #添加失败
    2. INSERT INTO test10
    3. VALUES(2,'王大队长',1500);
    4. SELECT * FROM test10;

     

    八、default约束

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

    关键字
    DEFAULT 

    在建表时创建default约束 

    1. # DEFAULT约束
    2. # 在CREATE TABLE添加约束
    3. CREATE TABLE test11(
    4. id INT,
    5. last_name VARCHAR(15),
    6. salary DECIMAL(10,2) DEFAULT 2000
    7. );
    8. DESC test11;

     

    1. INSERT INTO test11(id,last_name,salary)
    2. VALUES(1,'王大队长',3000);
    3. INSERT INTO test11(id,last_name)
    4. VALUES(2,'催逝员');
    5. SELECT *
    6. FROM test11;

     

    在ALTER TABLE中创建DEFAULT约束

    1. # 在ALTER TABLE添加约束
    2. CREATE TABLE test12(
    3. id INT,
    4. last_name VARCHAR(15),
    5. salary DECIMAL(10,2)
    6. );
    7. DESC test12;

    1. ALTER TABLE test12
    2. MODIFY salary DECIMAL(8,2) DEFAULT 2500;
    3. DESC TEST12;

     

    删除DEFAULT约束

    1. # 在ALTER TABLE删除约束
    2. ALTER TABLE test12
    3. MODIFY salary DECIMAL(8,2);
    4. SHOW CREATE TABLE test12;

     

    一些问题

    1、为什么建表时,加 not null default '' 或 default 0
    答:不想让表中出现null值。


    2、为什么不想要 null 的值
    答:(1)不好比较。null是一种特殊值,比较时只能用专门的is null 和 is not null来比较。碰到运算符,通常返回null。
    (2)效率不高。影响提高索引效果。因此,我们往往在建表时 not null default '' 或 default 0


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

    在MySQL中,默认AUTO_INCREMENT的初始
    值是1,每新增一条记录,字段值自动加1。设置自增属性(AUTO_INCREMENT)的时候,还可以指定第一条插入记录的自增字段的值,这样新插入的记录的自增字段值从初始值开始递增,如在表中插入第一条记录,同时指定id值为5,则以后插入的记录的id值就会从6开始往上增加。添加主键约束时,往往需要设置字段自动增加属性。


    4、并不是每个表都可以任意选择存储引擎?

    外键约束(FOREIGN KEY)不能跨引擎使用。MySQL支持多种存储引擎,每一个表都可以指定一个不同的存储引擎,需要注意的是:外键约束是用来保证数据的参照完整性的,如果表之间需要关联外键,却指定了不同的存储引擎,那么这些表之间是不能创建外键约束的。所以说,存储引擎的选择也不完全是随意的。

  • 相关阅读:
    机器学习|KNN和Kmeans
    [0xGame 2023] week1
    智能驾驶功能软件平台设计规范 第二部分:感知融合功能服务接口
    如何确定自己是否适合做程序员?
    ilr normalize isometric log-ratio transformation
    SpringCloud——服务注册——Consul
    对增加LLaMA 3 上下文长度技术的猜测
    记录一次Bitbucket鉴权的坑
    捷诚管理信息系统 SQL注入漏洞复现
    软件测试之TCP、UPD协议详解
  • 原文地址:https://blog.csdn.net/weixin_62684026/article/details/126119432