Mysql(8)约束
提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档文章目录约束约束的作用约束的类型表级约束和列级约束约束和索引非空约束指定非空约束删除非空约束示例唯一性约束指定唯一键约束复合唯一查看唯一键约束删除唯一键约束主键约束唯一键约束和主键约束区别指定主键约束复合主键删除主键约束自增约束指定自增约束删除自增约束默认值约束指定默认值约束删除默认值约束检查约束指定检查约束删除检查约束外键约束指定外键约束查看外键约束查看外键字段索引删除外键约束设置外键约束等级总结**一、约束的作用****二、约束的分类**1. 按约束类型划分2. 按约束级别划分**三、约束与索引的区别易错点高频区****四、各类约束详细说明**1. 非空约束NOT NULL2. 唯一性约束UNIQUE3. 主键约束PRIMARY KEY4. 自增约束AUTO_INCREMENT5. 默认值约束DEFAULT6. 检查约束CHECK7. 外键约束FOREIGN KEY约束约束的作用约束是为了保证数据的完整性数据完整性Data Integrity是指数据的精确性Accuracy和可靠性Reliability。它是应防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息而提出的。数据的完整性要从以下四个方面考虑实体完整性Entity Integrity例如同一个表中不能存在两条完全相同无法区分的记录域完整性Domain Integrity例如年龄范围0-120性别范围“男/女”引用完整性Referential Integrity例如员工所在部门在部门表中要能找到这个部门用户自定义完整性User-defined Integrity例如用户名唯一、密码不能为空等本部门经理的工资不得高于本部门职工的平均工资的5倍可以在创建表时规定约束通过create table语句或者在表创建之后也可以添加约束通过alter table语句。约束的类型键约束主键约束、外键约束、唯一键约束Not NULL约束非空约束Check约束检查约束Default约束默认值约束自增是键约束字段的一个额外的属性表级约束和列级约束表级约束不仅要看约束字段当前单元格的数据还要看其他单元格的数据。键约束和检查约束是表级约束。列级约束约束字段只看当前单元格的数据即可和其他单元格无关。非空约束和默认值约束是列级约束。所有的表级约束都可以在“information_schema.table_constraints”表中查看。select*frominformation_schema.table_constraints where table_name表名;约束和索引在MySQL中键约束会自动创建索引提高查询效率。约束和索引不同约束是一个逻辑概念不会占用物理空间索引是一个物理概念会占用物理空间例如字典里面有要求不能有重复的字字一样读音也一样这是约束。字典里面有“目录”它可以快速的查找某个字目录需要占用单独的页这是索引。非空约束not null限定某个字段/某列的值不允许为空。只能某个列单独限定非空不能组合非空一个表可以有很多列都分别限定了非空指定非空约束1建表时create table 表名(字段名 数据类型notnull,字段名 数据类型notnull);2建表后alter table 表名 modify 字段名 数据类型notnull;--如果该字段已经有值了给该字段增加非空约束要求该字段的值不能有NULL值--否则需要先处理NULL值才能加上非空约束删除非空约束alter table 表名 modify 字段名 数据类型;--如果使用modify修改有非空约束的字段时想要保留非空约束必须带上notnull--否则会在修改时把非空约束丢掉示例若是此时依然强行插入则会报这个错误插值方式和之前依然是一样insert into not_null_demo(id,name)values(1,张三);insert into not_null_demo values(4,赵六,null);--给birthday字段添加非空约束 alter table not_null_demo modify column birthday datenotnull;失败的原因是因为birthday字段现在有NULL值添加不上非空约束删除表重新修改便能成功或者将其null填上一个值然后再进行修改--删除birthday字段的非空约束 alter table not_null_demo modify column birthday date;desc not_null_demo;唯一性约束unique key用来限制某列的值或几个字段的值组合不能重复。一个表可以有很多个唯一键约束每一个唯一键约束字段都会自动创建索引唯一键约束允许为空唯一键约束也可以是复合唯一删除唯一键约束的索引来删除唯一键约束索引名默认是字段名复合唯一默认是第一个字段名指定唯一键约束1建表时create table 表名(字段名 数据类型 unique key,字段名 数据类型 unique key);create table 表名(字段名1数据类型,字段名2数据类型,unique key(字段名1),unique key(字段名2));2建表后其实和之前有些像复合唯一– 多个字段的组合是唯一create table 表名(字段名1数据类型,字段名2数据类型,字段名3数据类型,unique key(字段名1,字段名2,字段名3));示例create table unique_key(name char(4),gender char(1),idcardint,unique key(name,idcard))多个共同构成唯一键约束的时候使用第一个作为索引如下添加数据第二句可以插入但是第三段不能插入主键字段相同不能插入但是若是为空则可以插入insert into unique_key VALUES(孙晓明,男,12345);insert into unique_key(name)VALUES(孙晓明);insert into unique_key(name,idcard)VALUES(孙晓明,12345)查看唯一键约束desc 表名;show create table 表名;show indexfrom表名;--查看表的索引信息 select*frominformation_schema.table_constraints where table_name表名;对于某一个字段可以重复添加唯一键约束不过没意义删除唯一键约束删除表结构中的某一个字段是这样的--删除唯一键约束需要手动删除对应的索引多了一个index alter table 表名 drop index 索引名;主键约束primary key用来唯一的确定一条记录唯一并且非空一个表最多只能有一个主键约束如果主键是由多列组成可以使用复合主键主键列会自动创建索引能够根据主键查询的就根据主键查询效率更高mysql会给每个表的主键列创建索引会开辟单独的物理空间来存储每一个主键的目录表Btree结构。这样可以根据主键快速查询到某一行的记录如果删除主键约束了主键约束对应的索引就自动删除了唯一键约束和主键约束区别唯一键约束一个表可以有好几个但是主键约束只有一个。唯一键约束本身不带非空限制如果需要非空需要单独定义。主键约束不用再定义not null自身就带非空限制。指定主键约束1建表时create table 表名(字段名 数据类型 primary key,字段名 数据类型);--或 create table 表名(字段名1数据类型,字段名2数据类型,primary key(字段名1));2建表后alter table 表名 add primary key(字段列表);复合主键create table 表名(字段名1数据类型,字段名2数据类型,字段名3数据类型,primary key(字段名1,字段名2));删除主键约束这里和删除唯一键约束不同因为唯一键约束可能有多个而主键约束只有一个alter table 表名 drop primary key;自增约束auto_increment给某个字段自动赋值这个值如无干扰每次1。一个表只能有一个自增字段因为一个表只有一个AUTO_INCREMENT属性记录自增字段值自增字段只能是key字段即定义了主键、唯一键等键约束的字段自增字段应该是数值类型一般都是整数类型如果自增列指定了 0 和 null会在当前最大值的基础上自增如果自增列手动指定了具体值直接赋值为具体值如果手动修改AUTO_INCREMENT属性值 必须 当前自增字段的最大值指定自增约束1建表时create table 表名(字段名 数据类型 primary key auto_increment,字段名 数据类型 unique keynotnull);2建表后alter table 表名 modify 字段名 数据类型 auto_increment;删除自增约束alter table 表名 modify 字段名 数据类型;示例下面这个代码不对auto_increment必须放在主键、唯一键后面,drop tableifexists emp;create table emp(eidintauto_increment,ename varchar(20));所以需要修改为下面这种create table emp(eidintprimary key auto_increment,ename varchar(20));即使不进行赋值也是会有值insert into emp(ename)values(李四);--不给自增字段指定值也是自增 insert into emp values(null,张三);--给自增字段赋值NULL也是自增当手动给自增字段赋值时如果这个值大于当前 AUTO_INCREMENT 属性记录的自增值时会修改 AUTO_INCREMENT 属性值下次就从这个值基础上自增如果这个值小于当前 AUTO_INCREMENT 属性记录的自增值时不会修改 AUTO_INCREMENT 属性值建议不要随意修改 AUTO_INCREMENT 的值让他自动维护insert into emp values(9,田七);insert into emp values(-5,王五);默认值约束default给某个字段/某列指定默认值当添加时或修改时可以使用默认值。指定默认值约束1建表时 create table 表名(字段名 数据类型 primary key,字段名 数据类型 unique keynotnull,字段名 数据类型 unique key,字段名 数据类型notnull default 默认值);--默认值约束一般不在唯一键和主键列上加2建表后alter table 表名 modify 字段名 数据类型 default 默认值;删除默认值约束alter table 表名 modify 字段名 数据类型;--如果使用modify修改有默认值约束的字段时想要保留默认值约束必须带上default 默认值--否则会在修改时把默认值约束丢掉示例drop tableifexists emp;create table emp(eidintprimary key,ename varchar(20)notnull,gender enum(男,女)default男notnull,--非空并且有默认值 address varchar(100)default不详--可以指定为null);insert into emp values(2,李四,default,default);insert into emp values(3,王五,default,null);select*fromemp;--删除emp表的address的默认值约束 alter table emp modify column address varchar(100);desc emp;--给emp表address增加 不详 默认值 alter table emp modify column address varchar(100)default不详;desc emp;检查约束check检查约束用于限制字段中的值的范围。如果对单个字段定义检查约束那么该字段只允许特定范围的值。如果对一个表定义检查约束那么此约束会基于行中其他字段的值在特定的字段中对值进行限制。指定检查约束1建表时create table 表名(字段名 数据类型 check(条件),--在字段后面直接加检查约束 字段名 数据类型,字段名 数据类型,check(条件)enforced--可以限定两个字段之间的取值条件);--如果省略或指定为enforced则会强制执行约束不满足约束的数据行不能插入成功--如果写notenforced则不满足检查约束也没关系2建表后alter table 表名 add check(条件);alter table 表名 modify 字段名 字段类型 check(条件);删除检查约束alter table 表名 drop check 检查约束名;示例drop tableifexists emp;create table emp(idintprimary key auto_increment,name varchar(20)notnull,ageint,birthday datenotnull,--出生日期 hiredate datenotnull,--入职日期 check(year(hiredate)-year(birthday)18)--入职时18岁);年龄为8的时候不能插入只有18才能使用这种方式不行 alter table emp modify age int; 还是需要使用alter table emp drop check emp_chk_1;alter table emp drop check emp_chk_1;外键约束foreign key限定某个表的某个字段的引用完整性比如员工表的员工所在部门的选择必须在部门表能找到对应的部分。外键约束会影响性能效率所以很多人不愿意加外键约束。1建和不建外键约束有什么区别建外键约束操作创建表、删除表、添加、修改、删除会受到限制从语法层面受到限制。例如在员工表中不可能添加一个员工信息它的部门的值在部门表中找不到。不建外键约束操作创建表、删除表、添加、修改、删除不受限制要保证数据的引用完整性只能依靠程序员的自觉或者是在程序中进行限定。例如在员工表中可以添加一个员工的信息它的部门指定为一个完全不存在的部门。2主表和从表/父表和子表主表父表被引用的表被参考的表从表子表引用别人的表参考别人的表例如员工表与部门表。员工表的员工所在部门这个字段的值要参考部门表部门表是主表员工表是从表。例如学生表、课程表、选课表。选课表的学生和课程要分别参考学生表和课程表学生表和课程表是主表选课表是从表。3外键约束的特点在从表中指定外键约束并且一个表可以建立多个外键约束创建表时就指定外键约束的话先创建主表再创建从表删表时先删从表或先删除外键约束再删除主表。或者先解除关系再各自删除从表的外键列必须引用/参考主表的键列主键或唯一键因为被依赖/被参考的值必须是唯一的从表的外键列的数据类型要与主表被参考/被引用的列的数据类型一致并且逻辑意义一致。例如都是表示部门编号都是int类型外键列也会自动建立索引根据外键查询效率更快外键约束删除后索引不会自动删除如果要删除对应的索引必须手动删除指定外键约束1建表时create table 主表(字段1数据类型 primary key,字段2数据类型);create table 从表(字段1数据类型 primary key,字段2数据类型,foreign key(从表的某个字段)references 主表(被参考字段));--(从表的某个字段)的数据类型必须与主表(被参考字段)的数据类型一致逻辑意义也一样--(从表的某个字段)的字段名可以与主表(被参考字段)的字段名不同2建表后alter table 从表 add foreign key (从表的字段) references 主表(被引用字段) [on update xx] [on delete xx];查看外键约束desc 从表;--可以看到外键约束但看不到外键约束名 show create table 从表;--可以看到外键约束名 select*frominformation_schema.table_constraints where table_name表名;--information_schema数据库名(系统库)--table_constraints表名(专门存储各个表的约束)查看外键字段索引show index from 表名;删除外键约束--先查看约束名和删除外键约束 select*frominformation_schema.table_constraints where table_name表名;alter table 从表 drop foreign key 外键约束名;--查看索引名和删除索引 show indexfrom表名;alter table 从表 drop index 索引名;示例drop tableifexists dept;create table dept(didintprimary key auto_increment,dname varchar(50)unique keynotnull);drop tableifexists emp;create table emp(idintprimary key auto_increment,name varchar(20)notnull,departmentidint,--外键约束只能在字段列表下面单独定义不能在字段后面直接定义 foreign key(departmentid)references dept(did));desc dept;desc emp;show create table dept;show create table emp;--查看系统库的约束表 select*frominformation_schema.table_constraints where table_nameemp;--添加父表数据没有影响 insert into dept values(null,财务),(null,教学),(null,咨询),(null,后勤);select*fromdept;--添加子表数据有影响受到约束 insert into emp values(null,张三,1);--成功 insert into emp values(null,李四,1);--成功 insert into emp values(null,王五,2);--成功 insert into emp values(null,赵六,6);--失败--departmentid6在父表dept中找不到对应部门 select*fromemp;--修改子表的外键字段的信息有影响受到约束 update empsetdepartmentid3whereid1;--成功 update empsetdepartmentid6whereid3;--失败--departmentid6在父表dept中找不到对应部门 select*fromemp;--修改父表的被引用字段的值受约束 update deptsetdid6where did1;--失败--did1的部门被子表引用 update deptsetdid6where did4;--成功--did4的部门没有被子表引用 select*fromdept;--删除父表的记录受约束 deletefromdept where did6;--成功--did6的部门没有被子表引用 deletefromdept where did1;--失败--did1的部门被子表引用--删除子表的数据不受约束 deletefromemp where name王五;select*fromemp;--删除父表受约束 drop table dept;--失败--删除子表不受约束 drop table emp;--建表后添加外键约束 create table emp(idintprimary key auto_increment,name varchar(20)notnull,departmentidint);--给emp表(子表)增加外键约束 alter table emp add foreign key(departmentid)references dept(did);--查看emp的约束信息 select*frominformation_schema.table_constraints where table_nameemp;--键约束(主键、唯一键、外键)都会自动创建索引--查看emp表的索引 show indexfromemp;--主键字段索引名是PRIMARY删除主键时会自动删除对应索引--唯一键字段索引名是字段名删除唯一键时就是通过删除对应的索引方式来删除唯一键约束--外键字段索引名是字段名删除外键约束时不会自动删除外键字段的索引因为它们的命名不一样--删除emp表的departmentid字段的外键约束 alter table emp drop foreign key emp_ibfk_1;show indexfromemp;--删除emp表的departmentid字段的索引 alter table emp drop index departmentid;show indexfromemp;设置外键约束等级Cascade方式在父表上update/delete记录时同步update/delete子表的匹配记录Set null方式在父表上update/delete记录时将子表上匹配记录的列设为null但是要注意子表的外键列不能为not nullNo action方式如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作Restrict方式同no action, 都是立即检查外键约束如果没有指定等级就相当于Restrict方式。create table 主表(字段1数据类型 primary key,字段2数据类型);create table 从表(字段1数据类型 primary key,字段2数据类型,foreign key(从表的某个字段)references 主表(被参考字段)on updata(Cascade/Set null)on delete(Cascade/Set null));--(从表的某个字段)的数据类型必须与主表(被参考字段)的数据类型一致逻辑意义也一样--(从表的某个字段)的字段名可以与主表(被参考字段)的字段名不同总结一、约束的作用约束Constraint是为了保证数据的完整性Data Integrity而设计的。数据完整性包括精确性和可靠性目的是防止数据库中出现不符合业务规则的数据。数据完整性从四个方面考虑实体完整性Entity Integrity表中不能有完全相同的两条记录主键实现域完整性Domain Integrity字段值必须在合理范围内如年龄 0~120引用完整性Referential Integrity外键必须引用主表中已存在的值用户自定义完整性由用户自己定义的业务规则如用户名唯一、经理工资不得超过部门平均工资5倍可以在创建表时CREATE TABLE或建表后ALTER TABLE添加约束。二、约束的分类1. 按约束类型划分键约束主键约束PRIMARY KEY、唯一键约束UNIQUE、外键约束FOREIGN KEY非空约束NOT NULL默认值约束DEFAULT检查约束CHECK自增AUTO_INCREMENT属于键约束的附加属性不是独立约束2. 按约束级别划分列级约束只针对当前字段本身与其他字段无关→ 非空约束、默认值约束表级约束需要看当前字段和其他字段的关联关系→ 主键约束、唯一键约束、外键约束、检查约束所有表级约束都可以在系统表中查看SELECT*FROMinformation_schema.table_constraintsWHEREtable_name表名;三、约束与索引的区别易错点高频区维度约束Constraint索引Index概念逻辑概念用于保证数据规则物理概念用于加快查询速度是否占用空间不占用物理空间占用物理空间BTree结构目的保证数据完整性提升查询性能创建方式CREATE TABLE / ALTER TABLECREATE INDEX 或自动创建重要说明键约束主键、唯一键、外键在创建时MySQL会自动创建索引。但约束和索引是两个不同的概念。四、各类约束详细说明1. 非空约束NOT NULL作用限定字段值不能为空特点只能是列级约束不能组合非空语法-- 建表时CREATETABLE表名(字段名 类型NOTNULL,);-- 建表后ALTERTABLE表名MODIFY字段名 类型NOTNULL;-- 删除非空约束ALTERTABLE表名MODIFY字段名 类型;-- 注意不写 NOT NULL 就是删除易错点修改字段时如果不重新写NOT NULL原来的非空约束会被去掉。已有 NULL 值的字段无法直接加上非空约束必须先处理 NULL 值。2. 唯一性约束UNIQUE作用保证字段值不能重复特点允许为空一个表可有多个唯一约束会自动创建索引支持复合唯一多个字段组合唯一语法-- 建表时CREATETABLE表名(nameVARCHAR(20)UNIQUE,idcardVARCHAR(18),UNIQUEKEYuk_name_idcard(name,idcard)-- 复合唯一);-- 建表后ALTERTABLE表名ADDUNIQUEKEY索引名(字段列表);-- 删除唯一约束必须删除对应的索引ALTERTABLE表名DROPINDEX索引名;易错点同一个字段可以重复写多个UNIQUE KEY语法不报错但完全冗余无意义。复合唯一键的索引名默认为第一个字段名。唯一约束允许 NULL多个 NULL 不算重复。3. 主键约束PRIMARY KEY作用唯一确定一条记录唯一 非空特点一个表只能有一个主键可以是单列或多列复合主键会自动创建聚簇索引。语法-- 建表时CREATETABLE表名(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(20));-- 建表后ALTERTABLE表名ADDPRIMARYKEY(字段列表);-- 删除主键ALTERTABLE表名DROPPRIMARYKEY;易错点主键不能为 NULL而唯一键允许 NULL。删除主键会自动删除对应的索引。自增字段必须定义在主键或唯一键上。4. 自增约束AUTO_INCREMENT特点一个表只能有一个自增字段必须是 Key 列主键或唯一键。传入NULL或0都会触发自增。手动指定具体正整数时会使用该值并可能修改自增起点。易错点AUTO_INCREMENT必须跟在PRIMARY KEY或UNIQUE KEY后面不能单独使用。不要随意手动修改自增列的值容易导致自增混乱。5. 默认值约束DEFAULT作用当插入或更新时未指定值则使用默认值。语法字段名 类型DEFAULT默认值;ALTERTABLE表名MODIFY字段名 类型DEFAULT默认值;易错点修改字段时如果不重新写DEFAULT原来的默认值约束会被清除。6. 检查约束CHECK作用限制字段值的范围或多个字段之间的关系。MySQL 8.0.16 版本开始才真正生效。推荐写法CHECK(TIMESTAMPDIFF(YEAR,birthday,hiredate)18)易错点YEAR(hiredate)-YEAR(birthday)18不严谨忽略月份和日期。低版本 MySQL 中 CHECK 约束不生效只是语法通过。7. 外键约束FOREIGN KEY作用保证引用完整性从表的外键必须在主表中存在。会自动在外键列创建普通索引显示为MUL。语法FOREIGNKEY(dept_id)REFERENCESdept(dept_id)ONDELETECASCADE-- 级联删除ONUPDATERESTRICT;-- 默认行为易错点删除主表前必须先删除从表或先删除外键约束。.删除唯一键 删除对应的索引删除外键约束不会自动删除对应的索引需要手动DROP INDEX。外键会影响INSERT、UPDATE、DELETE性能很多公司不推荐在生产环境使用外键改用程序控制。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2520923.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!