今天小编给大家分享一下Mariadb表约束及三范式是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

数据库三大范式

范式(NF):设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。但是有些时候一昧的追求范式减少冗余,反而会降低数据读写的效率,这个时候就要反范式,利用空间来换时间。可以把它粗略地理解为一张数据表的表结构所符合的某种设计标准的级别。

1NF

即表的列的具有原子性,不可再分解,即列的信息,不能分解, 只要数据库是关系型数据库(mysql/oracle/db2/informix/sysbase/sql server),就自动的满足1NF。数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。如果实体中的某个属性有多个值时,必须拆分为不同的属性 。通俗理解即一个字段只存储一项信息。

以上,就不符合第一范式,因为进货、销售还可以再分为,进货数量、进货单位、销售单位、销售数量等,以下则满足了第一范式。

2NF

第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。满足1NF后,要求表中的所有列,都必须依赖于主键,而不能有任何一列与主键没有关系,也就是说一个表只描述一件事情;

例如:订单表只描述订单相关的信息,所以所有字段都必须与订单id相关;产品表只描述产品相关的信息,所以所有字段都必须与产品id相 关;因此不能在一张表中同时出现订单信息与产品信息;如下图所示:

3NF

必须先满足第二范式(2NF),要求:表中的每一列只与主键直接相关而不是间接相关,表中的每一列只能依赖于主键。

例如:订单表中需要有客户相关信息,在分离出客户表之后,订单表中只需要有一个用户id即可,而不能有其他的客户信息。因为其他的客户信息直接关联于用户id,而不是直接与订单id直接相关。

各种约束

约束是用来限定表中数据准确性、完整性、一致性、联动性的一套规则。在Mysql中,约束保存在information_schema数据库的table_constraints中,可以通过该表查询约束信息。如下图:

Mariadb学习总结(五):数据库表约束及三范式Mariadb学习总结(五):数据库表约束及三范式
NOT NULL

非空约束,是否允许该列的值为NULL,这里有一点很重要,很多字段(除了时间?)默认值如果不指定的话都是NULL,所以除了NULL=NULL,其他值并不等于NULL,比如“”、0等。

修改一个字段为NOT NULL:

MariaDB[mydb]>DESCuser;+----------+-------------+------+-----+---------------------+----------------+|Field|Type|Null|Key|Default|Extra|+----------+-------------+------+-----+---------------------+----------------+|id|int(11)|NO|PRI|NULL|auto_increment||username|varchar(10)|NO||NULL|||password|varchar(10)|NO||NULL|||regtime|timestamp|NO||CURRENT_TIMESTAMP|||logtime|timestamp|NO||0000-00-0000:00:00|||logip|varchar(20)|YES||NULL||+----------+-------------+------+-----+---------------------+----------------+6rowsinset(0.00sec)MariaDB[mydb]>ALTERTABLEuserMODIFYlogipvarchar(20)NOTNULL;QueryOK,5rowsaffected,5warnings(0.04sec)Records:5Duplicates:0Warnings:5MariaDB[mydb]>DESCuser;+----------+-------------+------+-----+---------------------+----------------+|Field|Type|Null|Key|Default|Extra|+----------+-------------+------+-----+---------------------+----------------+|id|int(11)|NO|PRI|NULL|auto_increment||username|varchar(10)|NO||NULL|||password|varchar(10)|NO||NULL|||regtime|timestamp|NO||CURRENT_TIMESTAMP|||logtime|timestamp|NO||0000-00-0000:00:00|||logip|varchar(20)|NO||NULL||+----------+-------------+------+-----+---------------------+----------------+6rowsinset(0.01sec)

这里还有一个问题,对于默认值为NULL但是又没有指定插入这个字段:

MariaDB[mydb]>DESCuser;+----------+-------------+------+-----+---------------------+----------------+|Field|Type|Null|Key|Default|Extra|+----------+-------------+------+-----+---------------------+----------------+|id|int(11)|NO|PRI|NULL|auto_increment||username|varchar(10)|NO||NULL|||password|varchar(10)|NO||NULL|||regtime|timestamp|NO||CURRENT_TIMESTAMP|||logtime|timestamp|NO||0000-00-0000:00:00|||logip|varchar(20)|YES||NULL||+----------+-------------+------+-----+---------------------+----------------+//看username这个字段,默认值为NULL,不允许NULLMariaDB[mydb]>INSERTINTOuser(password)VALUES('test7');QueryOK,1rowaffected,1warning(0.00sec)//这里看到我们插入成功了。MariaDB[mydb]>SELECT*FROMuserWHEREpassword='test7';+----+----------+----------+---------------------+---------------------+-------+|id|username|password|regtime|logtime|logip|+----+----------+----------+---------------------+---------------------+-------+|12||test7|2018-02-2515:25:14|0000-00-0000:00:00|NULL|+----+----------+----------+---------------------+---------------------+-------+1rowinset(0.00sec)

可以看到username这一列的值为空字符,而它的默认值为NULL啊, 而logip默认值为NULL,但是允许插入NULL值,所以这里显示了NULL值。

查了一下~因为NULL为默认值,但是又不允许NULL值,所以,也就是说现在username这个字段没有值,因为SQL_MODE的原因,只会警告一下并不会直接报错,当我们指定SQL_MODE为’STRICT_ALL_TABLES’时,此时插入就会报如下错误:

MariaDB[mydb]>INSERTINTOuser(password)VALUES('test88');ERROR1364(HY000):Field'username'doesn'thaveadefaultvalueUNIQUE

unique代表唯一约束:唯一约束是指定table的列或列组合不能重复,保证数据的唯一性,虽然唯一约束不允许出现重复的值,但是可以为多个null,同一个表可以有多个唯一约束,多个列组合的约束。在创建唯一约束的时候,如果不给唯一约束名称,就默认和列名相同,MySQL会给唯一约束的列上默认创建一个唯一索引。

添加唯一约束:

MariaDB[mydb]>ALTERTABLEuserADDCONSTRAINTuq_usernameUNIQUE(username);//uq_username为约束名称,UNIQUE(可多个字段)//当插入用户名相同的数据事则会直接报错MariaDB[mydb]>INSERTINTOuser(username,password)VALUES('test4','test123');ERROR1062(23000):Duplicateentry'test4'forkey'uq_username'//删除此约束MariaDB[mydb]>ALTERTABLEuserDROPKEYuq_username;//添加两个字段的约束MariaDB[mydb]>ALTERTABLEuserADDCONSTRAINTuq_userUNIQUE(username,password);//测试添加数据MariaDB[mydb]>SELECT*FROMuser;+----+----------+----------+---------------------+---------------------+-------+|id|username|password|regtime|logtime|logip|+----+----------+----------+---------------------+---------------------+-------+|7|test2|test3|2018-02-2416:42:48|0000-00-0000:00:00|||8|test3|test3|2018-02-2416:42:48|0000-00-0000:00:00|||9|test4|test5|2018-02-2416:42:48|0000-00-0000:00:00||+----+----------+----------+---------------------+---------------------+-------+3rowsinset(0.00sec)MariaDB[mydb]>INSERTINTOuser(username,password)VALUES('test4','test123');QueryOK,1rowaffected(0.01sec)//仅当两个字段的数据都相同时才违反唯一约束MariaDB[mydb]>INSERTINTOuser(username,password)VALUES('test4','test5');ERROR1062(23000):Duplicateentry'test4-test5'forkey'uq_user'PRIMARY KEY

主键约束相当于唯一约束+非空约束的组合,主键约束列不允许重复,也不允许出现空值。如果是多列组合的主键约束, 那么这些列都不允许为空值,并且组合的值不允许重复。每个表最多只允许一个主键,建立主键约束可以在列级别创建,也可以在表级别上创建,MySQL的主键名总是PRIMARY, 当创建主键约束时,系统默认会在所在的列和列组合上建立对应的唯一索引。

操作如下:

//因为现在的表中已经有主键了,先把主键删掉MariaDB[mydb]>ALTERTABLEuserDROPPRIMARYKEY;ERROR1075(42000):Incorrecttabledefinition;therecanbeonlyoneautocolumnanditmustbedefinedasakey//告诉我们一张表里只允许有一个字段为自动增长,且这个字段必须是主键,所以,我们要先取消它的自动增长。MariaDB[mydb]>ALTERTABLEuserMODIFYCOLUMNidint(11)NOTNULL;QueryOK,4rowsaffected(0.07sec)Records:4Duplicates:0Warnings:0MariaDB[mydb]>DESCuser;+----------+-------------+------+-----+---------------------+-------+|Field|Type|Null|Key|Default|Extra|+----------+-------------+------+-----+---------------------+-------+|id|int(11)|NO|PRI|NULL||//再次删除主键MariaDB[mydb]>ALTERTABLEuserDROPPRIMARYKEY;QueryOK,4rowsaffected(0.03sec)Records:4Duplicates:0Warnings:0//好了,再让我们把主键加上吧~~~以下两种方式都可以哦~MariaDB[mydb]>ALTERTABLEuserADDCONSTRAINTPRIMARYKEY(id);MariaDB[mydb]>ALTERTABLEuserMODIFYCOLUMNidINT(11)NOTNULLPRIMARYKEYAUTO_INCREMENT;FOREIGN KEY

外键约束是保证一个或两个表之间的参照完整性,外键是构建于一个表的两个字段或是两个表的两个字段之间的参照关系。 也就是说从表的外键值必须在主表中能找到或者为空,当主表的记录被从表参照时,主表的记录将不允许删除,如果要删除数据,需要先删除从表中依赖该记录的数据,然后才可以删除主表的数据,还有一种就是级联删除子表数据。 注意:外键约束的参照列,在主表中引用的只能是主键或唯一键约束的列,假定引用的主表列不是唯一的记录,那么从表引用的数据就不确定记录的位置,同一个表可以有多个外键约束。

现在,我们创建一个GROUP表吧,用于记录用户的分组信息,

CREATETABLE`usergroup`(`id`int(3)NOTNULLAUTO_INCREMENT,`name`varchar(10)NOTNULL,`comment`varchar(100)DEFAULTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf16|

然后呢~为user表添加一个记录,记录用户属于那个组

MariaDB[mydb]>ALTERTABLEuserADDCOLUMNgroupidINT(3);QueryOK,0rowsaffected(0.05sec)Records:0Duplicates:0Warnings:0

//添加一个外键

ALTERTABLEuserADDCONSTRAINTfk_groupidFOREIGNKEY(groupid)REFERENCESusergroup(id);

//验证外键约束

MariaDB[mydb]>INSERTINTOuser(username,password,groupid)VALUES('test99','test00',1);ERROR1452(23000):Cannotaddorupdateachildrow:aforeignkeyconstraintfails(`mydb`.`user`,CONSTRAINT`fk_groupid`FOREIGNKEY(`groupid`)REFERENCES`usergroup`(`id`))

//可以为空,但是不可以为参照表中没有的值

MariaDB[mydb]>INSERTINTOuser(username,password)VALUES('test99','test00');QueryOK,1rowaffected(0.01sec)

外键定义:

reference_definition:REFERENCEStbl_name(index_col_name,...)[MATCHFULL|MATCHPARTIAL|MATCHSIMPLE][ONDELETEreference_option][ONUPDATEreference_option]reference_option:RESTRICT|CASCADE|SETNULL|NOACTION

其中一下级联操作需要注意: ON DELETE CASCADE:当删除父(参照)表中的行时,如果子表中有依赖于被删除父行的子行存在,那么连同子行一起删除,不推荐使用。 ON DELETE SET NULL:当删除父(参照)表中的行时,如果子表中有依赖于被删除父行的子行存在,那么不删除,而是将子行的外键列设置为NULL

CHECK

CHECK约束就是当向表中插入一行或更新一行数据时进行CHECK约束检查,CHECK接受一个表达式,如果这个表达式为TRUE则允许插入,如果这个表达式为FALSE则拒绝插入,在MariaDB10.2版本才开始支持CHECK。

常见的CHECK约束有:

CONSTRAINTnon_empty_nameCHECK(CHAR_LENGTH(name)>0)CONSTRAINTconsistent_datesCHECK(birth_dateISNULLORdeath_dateISNULLORbirth_date

例子:检查用户名长度是否大于0

ALTERTABLEuserADDCONSTRAINTnon_empty_nameCHECK(CHAR_LENGTH(username)>0);INSERTINTOuser(id,username)VALUES(1,'');/*SQL错误(4025):CONSTRAINT`non_empty_name`failedfor`test`.`user`*/

这个东西看起来很鸡肋的样子,好像一般都是在业务层进行数据判断了,而且数据库嘛~就存数据就好了。

以上就是“Mariadb表约束及三范式是什么”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。