MySQL提供了诸多用于约束数据格式与存储条件的语法,也就是表的约束;
实际业务中,可能会考虑到性能等原因,不一定直接在mysql中约束,而是在上层(写业务代码层面)或逻辑上进行约束;虽然不一定在mysql中使用约束,但我们至少通过掌握mysql中的约束,使能更好地在上层理解和运用约束.
空属性有两个值:null(默认的)和not null(不为空)
数据库默认字段基本都是字段为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算。
mysql> select null;
+------+
| NULL |
+------+
| NULL |
+------+
1 row in set (0.00 sec)
mysql> select 1+null;
+--------+
| 1+null |
+--------+
| NULL |
+--------+
1 row in set (0.00 sec)
非空约束是数据库中的一种约束,用于确保某个字段在创建记录时必须有值,不能为空。在MySQL中,这通常通过NOT NULL
约束来实现。
在创建或修改表结构时,可以在字段定义后添加NOT NULL
约束来指定该字段不能为空。
mysql> create table myclass(
-> class_name varchar(20) not null,
-> class_room varchar(10) not null);
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(10) | NO | | NULL | |
+------------+-------------+------+-----+---------+-------+
在MySQL中,默认值(Default Value)是指为表中的列指定的一个特定值,当在插入记录时该列没有提供值时,将自动使用此默认值。默认值可以是数字、字符串、日期或时间等数据类型,具体取决于列的数据类型。
mysql> create table t1(
name varchar(30) not null,
age tinyint unsigned default 18,
gender char(1) not null default '男'
);
mysql> desc t1;
+--------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | 18 | |
| gender | char(1) | NO | | 男 | |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> insert into t1(name) values(1);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+------+------+--------+
| name | age | gender |
+------+------+--------+
| 1 | 18 | 男 |
+------+------+--------+
1 row in set (0.00 sec)
mysql> insert into t1(name,age,gender) values(2,NULL,'男');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+------+------+--------+
| name | age | gender |
+------+------+--------+
| 1 | 18 | 男 |
| 2 | NULL | 男 |
+------+------+--------+
2 rows in set (0.00 sec)
可以主动设置为NULL
插入空:
mysql> insert into t1(name, age,gender) values(NULL,19,'女');
ERROR 1048 (23000): Column 'name' cannot be null
不插入:
mysql> insert into t1(age,gender) values(19,'女');
ERROR 1364 (HY000): Field 'name' doesn't have a default value
再看插入一个没有手动设置约束的,
mysql> alter table t1 add other varchar(10);
Query OK, 0 rows affected (0.06 sec)
mysql> show create table t1 \G;
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`name` varchar(30) NOT NULL, ## 没有默认值
`age` tinyint(3) unsigned DEFAULT '18',
`gender` char(1) NOT NULL DEFAULT '男',
`other` varchar(10) DEFAULT NULL ## 自动生成默认值为NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
说明:
手动设置约束后,不会再自动生成默认值(新覆盖旧)
如果没有显式插入某字段,则用的是缺省值,但如果该字段没有设置缺省值,则会报错(无法插入).
没有实际含义,专门用来描述字段,保存在表创建语句中,用来给程序员或DBA来进行了解,相当于一种软性约束(给人看的,让人觉得应该怎么做,不该怎么做,感性约束)。
show create table 表名; # desc看不见,只能通过show create查看
使用int类型时,发现int后面带了一个括号和数字int(N)
mysql> desc t2;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
1 row in set (0.01 sec)
这个数字就是zerofill属性的值,不过默认是没有设置zerofill的,没有设置zerofill时是无效的.
列 int(N) zerofill
;
mysql> create table myclass(
-> class_name varchar(20) not null,
-> class_room varchar(10) not null);
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(10) | NO | | NULL | |
+------------+-------------+------+-----+---------+-------+
0
mysql> create table myclass(
-> class_name varchar(20) not null,
-> class_room varchar(10) not null);
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(10) | NO | | NULL | |
+------------+-------------+------+-----+---------+-------+
1
可以发现括号内数字就是id的占位个数,占了11个位;其次,0会填充实际数值不够占位的位,缺多少填充多少
mysql> create table myclass(
-> class_name varchar(20) not null,
-> class_room varchar(10) not null);
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(10) | NO | | NULL | |
+------------+-------------+------+-----+---------+-------+
2
够N则没有动作,小于N位会补上足够的0,是一种"不够才会发生"的行为
说明: zerofill不会影响数据的原始类型,只是在显示时以0占位填充方式显示;
默认生成的zerofile数字
默认有符号int是11,无符号是10,因为int类类型的数据范围是40亿和20亿,十进制一共10个数字,所以无符号是10;而有符号还有一个要用于表示符号,因此有符号是11.
用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个主键(唯一标识);
主键所在的列通常是整数类型。
mysql> create table myclass(
-> class_name varchar(20) not null,
-> class_room varchar(10) not null);
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(10) | NO | | NULL | |
+------------+-------------+------+-----+---------+-------+
3
表结构中 key列多了 PRI 属性
查看标准定义语句
mysql> create table myclass(
-> class_name varchar(20) not null,
-> class_room varchar(10) not null);
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(10) | NO | | NULL | |
+------------+-------------+------+-----+---------+-------+
4
因此也可以这样定义
mysql> create table myclass(
-> class_name varchar(20) not null,
-> class_room varchar(10) not null);
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(10) | NO | | NULL | |
+------------+-------------+------+-----+---------+-------+
5
唯一标识,不能重复
mysql> create table myclass(
-> class_name varchar(20) not null,
-> class_room varchar(10) not null);
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(10) | NO | | NULL | |
+------------+-------------+------+-----+---------+-------+
6
mysql> create table myclass(
-> class_name varchar(20) not null,
-> class_room varchar(10) not null);
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(10) | NO | | NULL | |
+------------+-------------+------+-----+---------+-------+
7
mysql> create table myclass(
-> class_name varchar(20) not null,
-> class_room varchar(10) not null);
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(10) | NO | | NULL | |
+------------+-------------+------+-----+---------+-------+
8
注意,添加主键时,需要先保证该字段没有重复的数据出现(因此最好是在 建表前/插入数据前 把主键确定下来)
mysql> create table myclass(
-> class_name varchar(20) not null,
-> class_room varchar(10) not null);
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(10) | NO | | NULL | |
+------------+-------------+------+-----+---------+-------+
9
主键不仅仅能设置一个字段,还能多个字段构成一个主键
复合主键只能使用单独定义主键的方式定义
mysql> create table t1(
name varchar(30) not null,
age tinyint unsigned default 18,
gender char(1) not null default '男'
);
mysql> desc t1;
+--------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | 18 | |
| gender | char(1) | NO | | 男 | |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
0
这种两个以上主键标识的就是复合主键,复合主键的性质和一般主键是一样的,保证列复合结果不重复即可
auto_increment:当对应的字段,不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值
+1操作,得到一个新的不同的值。要搭配主键使用,作为逻辑主键。
自增长的特点:
基本语法
mysql> create table t1(
name varchar(30) not null,
age tinyint unsigned default 18,
gender char(1) not null default '男'
);
mysql> desc t1;
+--------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | 18 | |
| gender | char(1) | NO | | 男 | |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
1
建个带自增长属性的表
mysql> create table t1(
name varchar(30) not null,
age tinyint unsigned default 18,
gender char(1) not null default '男'
);
mysql> desc t1;
+--------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | 18 | |
| gender | char(1) | NO | | 男 | |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
2
给表添加两个数据,全列插入
mysql> create table t1(
name varchar(30) not null,
age tinyint unsigned default 18,
gender char(1) not null default '男'
);
mysql> desc t1;
+--------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | 18 | |
| gender | char(1) | NO | | 男 | |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
3
此时查看表的结构
mysql> create table t1(
name varchar(30) not null,
age tinyint unsigned default 18,
gender char(1) not null default '男'
);
mysql> desc t1;
+--------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | 18 | |
| gender | char(1) | NO | | 男 | |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
4
再插入一个数据,只对name插入,让id自增长
mysql> create table t1(
name varchar(30) not null,
age tinyint unsigned default 18,
gender char(1) not null default '男'
);
mysql> desc t1;
+--------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | 18 | |
| gender | char(1) | NO | | 男 | |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
5
插入一个比较小的数据,全列插入
mysql> create table t1(
name varchar(30) not null,
age tinyint unsigned default 18,
gender char(1) not null default '男'
);
mysql> desc t1;
+--------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | 18 | |
| gender | char(1) | NO | | 男 | |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
6
自增长属性没有发生变化,因此,自增长值是一个max()值,有比他大的就能覆盖,否则不变或自增
mysql> create table t1(
name varchar(30) not null,
age tinyint unsigned default 18,
gender char(1) not null default '男'
);
mysql> desc t1;
+--------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | 18 | |
| gender | char(1) | NO | | 男 | |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
7
mysql> create table t1(
name varchar(30) not null,
age tinyint unsigned default 18,
gender char(1) not null default '男'
);
mysql> desc t1;
+--------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | 18 | |
| gender | char(1) | NO | | 男 | |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
8
mysql> create table t1(
name varchar(30) not null,
age tinyint unsigned default 18,
gender char(1) not null default '男'
);
mysql> desc t1;
+--------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | 18 | |
| gender | char(1) | NO | | 男 | |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
9
mysql> insert into t1(name) values(1);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+------+------+--------+
| name | age | gender |
+------+------+--------+
| 1 | 18 | 男 |
+------+------+--------+
1 row in set (0.00 sec)
0
在插入后获取上次插入的值(批量插入获取的是第一个值);
搭配auto_increment时,得到的就是自增长的值
mysql> insert into t1(name) values(1);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+------+------+--------+
| name | age | gender |
+------+------+--------+
| 1 | 18 | 男 |
+------+------+--------+
1 row in set (0.00 sec)
1
后续用例补充...
索引:
在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。
索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。
索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序。
数据库使用索引以找到特定值,然后顺指针找到包含该值的行。这样可以使对应于表的SQL语句执行得
更快,可快速访问数据库表中的特定信息。
一张表中有往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键:唯一键就可以解决表中有多个字段需要唯一性约束的问题。
唯一键的本质和主键差不多,唯一键允许为空,而且可以多个为空,空字段不做唯一性比较。
面向对象思想中,表的字段等价于对象的属性(表的各类属性 == 对象的属性), 描述表就相当于描述对象
对象有众多属性,而众多属性中一定存在相当一部分是唯一的,这些唯一的属性就是表的唯一键;
对于主键,用于标识一个对象(表),选择主键就是在众多唯一属性中选择一个作为主键;(这个唯一属性就是唯一键)
区别:唯一键可以为空(默认),也可以设置为非空(这样就和主键很像了)
关于唯一键和主键的区别:
我们可以简单理解成,主键更多的是标识唯一性的。而唯一键更多的是保证在业务上,不要和别的信息出现重复。乍一听好像没啥区别
举一个例子
假设一个场景
比如在公司,我们需要一个员工管理系统,系统中有一个员工表,员工表中有两列信息,一个身份证号码,一个是员工工号,我们可以选择身份号码作为主键。而我们设计员工工号的时候,需要一种约束:而所有的员工工号都不能重复。
具体指的是在公司的业务上不能重复,我们设计表的时候,需要这个约束,那么就可以将员工工号设计成为唯一键。
一般而言,我们建议将主键设计成为和当前业务无关的字段,这样,当业务调整的时候,我们可以尽量不会对主键做过大的调整。
mysql> insert into t1(name) values(1);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+------+------+--------+
| name | age | gender |
+------+------+--------+
| 1 | 18 | 男 |
+------+------+--------+
1 row in set (0.00 sec)
2
mysql> insert into t1(name) values(1);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+------+------+--------+
| name | age | gender |
+------+------+--------+
| 1 | 18 | 男 |
+------+------+--------+
1 row in set (0.00 sec)
3
外键外腱,和动物跟腱一样,系联不同对象的跟腱
表与表之间的关联 表与表之间的约束
定义:
外键是数据库中的一个字段,它是另一个表的主键的引用。外键用于在两个表之间建立和维护引用完整性。它确保了表中的数据与另一个表中的数据相关联,并且保持一致性和准确性。
作用:
重要性:
外键是数据库设计中不可或缺的一部分,它们帮助开发者构建和维护数据库的完整性和一致性。通过外键,我们可以确保数据的准确性,防止数据冗余,并优化数据库的查询性能。此外,外键还有助于实现数据库表之间的逻辑关系,使得数据库的结构更加清晰和易于理解。
主表(Parent Table):
在数据库中,主表通常包含其他表所引用的主键。换句话说,如果一个表的主键被其他表的外键所引用,那么这个表就被称为主表。主表在数据库关系中扮演着核心的角色,因为它包含了其他表可能需要的参照数据。
从表(Child Table 或 Dependent Table):
从表,也称为子表或依赖表,是包含外键的表。外键是指向另一个表(即主表)主键的字段。从表通过外键与主表建立关联,从而实现数据的引用和完整性约束。
示例:
假设我们有两个表:students
(学生表)和courses
(课程表)。students
表有一个student_id
作为主键,而courses
表有一个course_id
作为主键。如果我们想要记录每个学生选修的课程,我们可以在courses
表中添加一个student_id
作为外键,它引用了students
表的student_id
主键。
其中students
表就是主表,courses
是从表;因为courses
表引用了students
表的主键;
以学生信息,班级信息,以及学生-班级的关系为例,
首先需要有一张主表(class)
mysql> insert into t1(name) values(1);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+------+------+--------+
| name | age | gender |
+------+------+--------+
| 1 | 18 | 男 |
+------+------+--------+
1 row in set (0.00 sec)
4
默认外键(自动生成外键名) -- 从表(student)
mysql> insert into t1(name) values(1);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+------+------+--------+
| name | age | gender |
+------+------+--------+
| 1 | 18 | 男 |
+------+------+--------+
1 row in set (0.00 sec)
5
自定义外键名(一般默认就够了)
mysql> insert into t1(name) values(1);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+------+------+--------+
| name | age | gender |
+------+------+--------+
| 1 | 18 | 男 |
+------+------+--------+
1 row in set (0.00 sec)
6
实用:谁引用谁,被引用的对象就是主表,引用方是从表
有一个商店的数据,记录客户及购物情况,有以下三个表组成:
要求:
mysql> insert into t1(name) values(1);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+------+------+--------+
| name | age | gender |
+------+------+--------+
| 1 | 18 | 男 |
+------+------+--------+
1 row in set (0.00 sec)
7