【MySQL】表的约束

目录

一、概念

二、空属性

三、默认值

四、列描述

五、zerofill

六、主键

七、自增长

八、唯一键

九、外键


一、概念

        表的约束是数据库设计中用于确保数据完整性、有效性和一致性的规则集合,通过限制字段的取值范围或关系来防止非法数据的插入或更新。真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合 法性,从业务逻辑角度保证数据的正确性。本文主要介绍以下介个:null/not null,default, comment, zerofill,primary key,auto_increment,unique key。

二、空属性

        数据库默认字段是可以为空,但实际在业务开发中,表中的字段应尽不为空。

//建立表结构 name字段不为空 room字段可为空
mysql> create table t1( class_name varchar(10) not null, class_room varchar(10) );
Query OK, 0 rows affected (0.02 sec)
//插入数据
mysql> insert into t1(class_name, class_room) values('计算机1班','201');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1(class_name) values('计算机2班');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1(class_room) values('203');
ERROR 1364 (HY000): Field 'class_name' doesn't have a default value
//查询表数据
mysql> select * from t1;
+---------------+------------+
| class_name    | class_room |
+---------------+------------+
| 计算机1班     | 201        |
| 计算机2班     | NULL       |
+---------------+------------+
2 rows in set (0.00 sec)

        由上述内容可知,当字段存在为空约束时,在插入数据中该字段必须得有值,否则会报错插入失败。在上例中,name字段不为空,因此在第三次插入数据只有room字段时会报错Field 'class_name' doesn't have a default value。表中的字段默认值为NULL,如果有not null约束且未指明该字段的默认值时,在插入数据时必须给出该字段的值。

三、默认值

        默认值:某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候, 用户可以选择性的使用默认值。

//创建表结构
mysql> create table t2( 
    -> class_name varchar(10) not null,
    -> class_room varchar(10) default '301'
    -> );
Query OK, 0 rows affected (0.02 sec)
//插入表数据
mysql> insert into t2(class_name, class_room) values ('计算机1班','201');
Query OK, 1 row affected (0.01 sec)
mysql> insert into t2(class_name) values ('计算机2班');
Query OK, 1 row affected (0.01 sec)
mysql> insert into t2(class_name, class_room) values ('计算机3班', null);
Query OK, 1 row affected (0.01 sec)
//查询表数据
mysql> select * from t2;
+---------------+------------+
| class_name    | class_room |
+---------------+------------+
| 计算机1班     | 201        |
| 计算机2班     | 301        |
| 计算机3班     | NULL       |
+---------------+------------+
3 rows in set (0.00 sec)

        在上例中,name字段不为空,room字段默认值为'301',当插入数据只有name字段时,room字段将使用默认值进行数据插入。room字段指定了默认值,但是是可以插入null值的。

        这里需要注意的是,非空约束和默认值约束并不冲突

        非空约束指的是字段不能为NULL,在数据库中若没有指明字段的默认值则为NULL,因此在插入数据时必须显式给出该字段的值(不可为NULL);默认值约束指的是若没有显式给出该字段的值,则采用默认值进行插入,即使给出了默认值约束,也可以显式插入NULL值。非空约束和默认值约束可同时存在。    

//创建表结构
mysql> create table t3(
    -> class_name varchar(10),
    -> class_room varchar(10) not null default '301'
    -> );
Query OK, 0 rows affected (0.01 sec)
//插入表数据
mysql> insert into t3 values('计算机1班','201');
Query OK, 1 row affected (0.01 sec)
mysql> insert into t3(class_name) values('计算机2班');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t3(class_name, class_room) values('计算机3班', null);
ERROR 1048 (23000): Column 'class_room' cannot be null
//查询表数据
mysql> select * from t3;
+---------------+------------+
| class_name    | class_room |
+---------------+------------+
| 计算机1班     | 201        |
| 计算机2班     | 301        |
+---------------+------------+
2 rows in set (0.00 sec)

四、列描述

        列描述:没有实际含义,专门用于描述字段。

mysql> create table t4(
    -> name varchar(10) not null comment '姓名',
    -> age tinyint default 0 comment '年龄'
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> show create table t4 \g
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                             |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------+
| t4    | CREATE TABLE `t4` (
  `name` varchar(10) NOT NULL COMMENT '姓名',
  `age` tinyint(4) DEFAULT '0' COMMENT '年龄'
) ENGINE=InnoDB DEFAULT CHARSET=utf8     |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

五、zerofill

        在数据库中一些数字类型后可以带长度。

//创建表结构
mysql> create table t5(
    -> a int(5),
    -> b int(5)
    -> );
Query OK, 0 rows affected (0.01 sec)
//插入表数据
mysql> insert into t5 values(1, 2);
Query OK, 1 row affected (0.00 sec)
//查询表数据
mysql> select * from t5;
+------+------+
| a    | b    |
+------+------+
|    1 |    2 |
+------+------+
1 row in set (0.00 sec)

        在上例中,字段a和b的类型后面都带有数字5,通过查询表数据发现并没有任何意义,但如果带有zerofill属性,显式结果就会有所不同。

//创建表结构
mysql> create table t6(
    -> a int(5) zerofill, 
    -> b int(5) zerofill
    -> );
Query OK, 0 rows affected (0.02 sec)
//插入表数据
mysql> insert into t6 values(1, 2);
Query OK, 1 row affected (0.00 sec)
//查询表数据
mysql> select * from t6;
+-------+-------+
| a     | b     |
+-------+-------+
| 00001 | 00002 |
+-------+-------+
1 row in set (0.00 sec)

        实际zerofill属性的作用是当插入数据长度小于设定的长度时采用0进行填充,只会改变显示结果,不会影响值本身。

六、主键

        主键:primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个主键;主键所在的列通常是整数类型。

//创建表结构
mysql> create table t7( sno int primary key, name varchar(6) not null );
Query OK, 0 rows affected (0.02 sec)
//插入表数据
mysql> insert into t7 values(1, '张三');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t7(name) values('李四');
ERROR 1364 (HY000): Field 'sno' doesn't have a default value
mysql> insert into t7(sno, name) values(null ,'王五');
ERROR 1048 (23000): Column 'sno' cannot be null
mysql> insert into t7(sno, name) values(1 ,'赵六');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
//查询表结构
mysql> select * from t7;
+-----+--------+
| sno | name   |
+-----+--------+
|   1 | 张三   |
+-----+--------+
1 row in set (0.00 sec)

        由上述代码中可以看出,身为主键的字段不可重复且不能为NULL。

        当表创建好后也可以追加或者删除主键。

//创建表结构
mysql> create table t8(sno int, name varchar(6));
Query OK, 0 rows affected (0.02 sec)
//追求主键
mysql> alter table t8 add primary key(sno);
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> show create table t8 \g;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                               |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------+
| t8    | CREATE TABLE `t8` (
  `sno` int(11) NOT NULL,
  `name` varchar(6) DEFAULT NULL,
  PRIMARY KEY (`sno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
//删除主键
mysql> alter table t8 drop primary key;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> show create table t8 \g;
+-------+---------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                        |
+-------+---------------------------------------------------------------------------------------------------------------------+
| t8    | CREATE TABLE `t8` (
  `sno` int(11) NOT NULL,
  `name` varchar(6) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+---------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

        在创建表时,主键只能有一个,但可以使用多个字段作为主键,也就是复合主键。

//创建表结构
mysql> create table t9(sno int,
    -> course tinyint,
    -> score decimal(3,1),
    -> primary key(sno, course)
    -> );
//查询表结构
mysql> desc t9;
+--------+--------------+------+-----+---------+-------+
| Field  | Type         | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| sno    | int(11)      | NO   | PRI | NULL    |       |
| course | tinyint(4)   | NO   | PRI | NULL    |       |
| score  | decimal(3,1) | YES  |     | NULL    |       |
+--------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

七、自增长

        auto_increment:当对应的字段,不显示给值会自动的被系统触发,系统会从当前字段中已经有的最大值 +1操作,得到一个新的不同的值。通常和主键搭配使用,作为逻辑主键。

//创建表结构
mysql> create table t10( id int primary key auto_increment, name varchar(6) );
Query OK, 0 rows affected (0.01 sec)
//插入表数据
mysql> insert into t10(name) values('张三');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t10(name) values('李四');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t10 values(10, '王五');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t10(name) values('赵六');
Query OK, 1 row affected (0.00 sec)
//查询表结构
mysql> select * from t10;
+----+--------+
| id | name   |
+----+--------+
|  1 | 张三   |
|  2 | 李四   |
| 10 | 王五   |
| 11 | 赵六   |
+----+--------+
4 rows in set (0.00 sec)

八、唯一键

       在一些场景中例如学校登记学生信息时,将学生的学号作为主键,相应的每一个学生的手机号也应该是不重复唯一的,但是主键只有一个,那么如何保证学生的手机号也具有唯一性呢?

        在数据库中往往有很多字段是需要唯一性的,但是一张表只能有一个主键,因此唯一键就可以解决表中有多个字段需要唯一性约束的问题。

        唯一键的本质和主键差不多,但是唯一键允许为空,空字段不参与唯一性的比较。主键主要标识记录在表中的唯一性,而唯一键属性则确保该记录的字段不与其他记录的字段重复。

//创建表结构
mysql> create table t11(
    -> sno int(10) primary key,
    -> name varchar(6) not null,
    -> tell int unique
    -> );
Query OK, 0 rows affected (0.02 sec)
//插入表数据
mysql> insert into t11 values(1, '张三', 12345);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t11 values(2, '李四', 12345);
ERROR 1062 (23000): Duplicate entry '12345' for key 'tell'
mysql> insert into t11 values(2, '李四', 12346);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t11(sno, name) values(3, '王五');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t11(sno, name) values(4, '赵六', null);
Query OK, 1 row affected (0.01 sec)
//查询表结构
mysql> select * from t11;
+-----+--------+-------+
| sno | name   | tell  |
+-----+--------+-------+
|   1 | 张三   | 12345 |
|   2 | 李四   | 12346 |
|   3 | 王五   |  NULL |
|   4 | 赵六   |  NULL |
+-----+--------+-------+
4 rows in set (0.00 sec)

        由上述内容可知,唯一键属性确保了字段在表中数据不存在重复项,也验证了NULL不参与唯一性的比较。

九、外键

        在一些场景中例如选课中,假如只开设了数据结构、操作系统和计算机网络三门课程,但在学生选课中出现了计算机组成原理课程,这显然是不合理的,因此就需要外键属性约束。

        外键用于定义主表和从表之间的关系:外键约束主要定义在从表上,主表则必须是有主键约束或unique 约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null

mysql> create table class(
    -> id int primary key,
    -> name varchar(10) not null unique
    -> );
Query OK, 0 rows affected (0.02 sec)
mysql> create table stu(
    -> id int primary key,
    -> name varchar(10) not null,
    -> class_id int,
    -> foreign key (class_id) references class(id)
    -> );
Query OK, 0 rows affected (0.02 sec)

        首先创建了两个表,一个课程表和一个选课表。

mysql> insert into class values(1, '数据结构');
Query OK, 1 row affected (0.00 sec)
mysql> insert into class values(2, '操作系统');
Query OK, 1 row affected (0.01 sec)
mysql> insert into class values(3, '计算机网络');
Query OK, 1 row affected (0.00 sec)
mysql> select * from class;
+----+-----------------+
| id | name            |
+----+-----------------+
|  2 | 操作系统        |
|  1 | 数据结构        |
|  3 | 计算机网络      |
+----+-----------------+
3 rows in set (0.00 sec)

        首先往课程表中插入数据数据结构、操作系统和计算机网络三门课程以及对应的id。此时往选课表中插入数据时必须时在课程表中含有的课程。对于选课表中的外键课程id可以为null(可以添加非空约束)。

mysql> insert into stu values (1, '张三', 1);
Query OK, 1 row affected (0.01 sec)
mysql> insert into stu values (2, '张三', 3);
Query OK, 1 row affected (0.00 sec)
mysql> insert into stu values (3, '李四', 2);
Query OK, 1 row affected (0.00 sec)
mysql> insert into stu values (4, '李四', 3);
Query OK, 1 row affected (0.00 sec)
mysql> insert into stu values (5, '王五', 4);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`stu`, CONSTRAINT `stu_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))
mysql> insert into stu values (5, '王五', null);
Query OK, 1 row affected (0.00 sec)
mysql> insert into stu(id, name) values (6, '赵六');
Query OK, 1 row affected (0.00 sec)

mysql> select * from stu;
+----+--------+----------+
| id | name   | class_id |
+----+--------+----------+
|  1 | 张三   |        1 |
|  2 | 张三   |        3 |
|  3 | 李四   |        2 |
|  4 | 李四   |        3 |
|  5 | 王五   |     NULL |
|  6 | 赵六   |     NULL |
+----+--------+----------+
6 rows in set (0.00 sec)

你可能感兴趣的:(mysql,数据库)