MySQL表的约束

1. 空属性

  • 两个值:null(默认的)和 not null(不为空)
  • 数据为空没法参与运算
  • not null则是插入时不能插入null
bash 复制代码
mysql> select 1+null;
+--------+
| 1+null |
+--------+
|   NULL |
+--------+

案例:

bash 复制代码
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> insert into myclass(class_name) values('class1');
ERROR 1364 (HY000): Field 'class_room' doesn't have a default value

2. 默认值

bash 复制代码
mysql> create table tt10 (
   -> name varchar(20) not null,
   -> age tinyint unsigned default 0,
   -> sex char(2) default '男'
   -> );
Query OK, 0 rows affected (0.00 sec)
mysql> desc tt10;
+-------+---------------------+------+-----+---------+-------+
| Field | Type               | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| name | varchar(20)         | NO   |     | NULL   |       |
| age   | tinyint(3) unsigned | YES |     | 0       |       |
| sex   | char(2)             | YES |     | 男     |       |
+-------+---------------------+------+-----+---------+-------+

默认值的生效:数据在插入的时候不给该字段赋值,就使用默认值

bash 复制代码
mysql> insert into tt10(name) values('zhangsan');
Query OK, 1 row affected (0.00 sec)
mysql> select * from tt10;
+----------+------+------+
| name     | age | sex |
+----------+------+------+
| zhangsan |    0 | 男   |
+----------+------+------+
--注意:只有设置了default的列,才可以在插入值的时候,对列进行省略

3. 列描述

列描述:comment,没有实际含义,专门用来描述字段,会根据表创建语句保存,用来给程序员或DBA 来进行了解

bash 复制代码
mysql> create table tt12 (
   -> name varchar(20) not null comment '姓名',
   -> age tinyint unsigned default 0 comment '年龄',
   -> sex char(2) default '男' comment '性别'
   -> );
    
--注意:not null和defalut一般不需要同时出现,因为default本身有默认值,不会为空

通过show可以看到:

bash 复制代码
mysql> show create table tt12\G
*************************** 1. row ***************************
       Table: tt12
Create Table: CREATE TABLE `tt12` (
 `name` varchar(20) NOT NULL COMMENT '姓名',
 `age` tinyint(3) unsigned DEFAULT '0' COMMENT '年龄',
 `sex` char(2) DEFAULT '男' COMMENT '性别'
) ENGINE=MyISAM DEFAULT CHARSET=gbk
1 row in set (0.00 sec)

4. zerofill

bash 复制代码
mysql> show create table tt3\G
 ***************** 1. row *****************
       Table: tt3
 Create Table: CREATE TABLE `tt3` (
 `a` int(10) unsigned DEFAULT NULL,
 `b` int(10) unsigned DEFAULT NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=gbk
 1 row in set (0.00 sec)

mysql> alter table tt3 change a a int(5) unsigned zerofill;
mysql> show create table tt3\G
*************************** 1. row ***************************
       Table: tt3
Create Table: CREATE TABLE `tt3` (
 `a` int(5) unsigned zerofill DEFAULT NULL,  --具有了zerofill
 `b` int(10) unsigned DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=gbk
1 row in set (0.00 sec)

对a列添加了zerofill属性,再进行查找,返回如下结果:

bash 复制代码
mysql> select * from tt3;
+-------+------+
| a     | b   |
+-------+------+
| 00001 |    2 |
+-------+------+

可以看到a的值由原来的1变成00001,这就是zerofill属性的作用,如果宽度小于设定的宽度,自动填充0。要注意的是,这只是最后显示的结果,在MySQL中实际存储的还是1。为什么?可以用hex函数来证明

bash 复制代码
mysql> select a, hex(a) from tt3;
+-------+--------+
| a     | hex(a) |
+-------+--------+
| 00001 | 1     |
+-------+--------+

数据库内部存储的还是1,00001只是设置了zerofill属性后的一种格式化输出

5. 主键

主键:

  • primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个 主键;
  • 主键所在的列通常是整数类型
bash 复制代码
mysql> create table tt13 (
-> id int unsigned primary key comment '学号不能为空',
-> name varchar(20) not null);
Query OK, 0 rows affected (0.00 sec)
mysql> desc tt13;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id   | int(10) unsigned | NO   | PRI | NULL   |       | 
| name | varchar(20)     | NO   |     | NULL   |       |
+-------+------------------+------+-----+---------+-------+
  • 主键约束:主键对应的字段中不能重复,一旦重复,操作失败

    bash 复制代码
    mysql> insert into tt13 values(1, 'aaa');
    Query OK, 1 row affected (0.00 sec)
    
    mysql> insert into tt13 values(1, 'aaa');
    ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
  • 当表创建好以后但是没有主键的时候,可以再次追加主键

    bash 复制代码
    alter table 表名 add primary key(字段列表
  • 删除主键

    bash 复制代码
    alter table 表名 drop primary key;
  • 复合主键 :在创建表的时候,在所有字段之后,使用primary key(主键字段列表)来创建主键,如果有多个字段作为主键,可以使用复合主键

bash 复制代码
mysql> create table tt14(
-> id int unsigned,
-> course char(10) comment '课程代码',
-> score tinyint unsigned default 60 comment '成绩',
-> primary key(id, course) -- id和course为复合主键
-> );
Query OK, 0 rows affected (0.01 sec)

mysql> desc tt14;
+--------+---------------------+------+-----+---------+-------+
| Field | Type               | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| id     | int(10) unsigned   | NO   | PRI | 0       |       | <= 这两列合成主键
| course | char(10)           | NO   | PRI |         |       |
| score | tinyint(3) unsigned | YES |     | 60     |       |
+--------+---------------------+------+-----+---------+-------+

mysql> insert into tt14 (id,course)values(1, '123');
Query OK, 1 row affected (0.02 sec)

mysql> insert into tt14 (id,course)values(1, '123');
ERROR 1062 (23000): Duplicate entry '1-123' for key 'PRIMARY' -- 主键冲突
两个都冲突才算冲突

6. 自增长

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

自增长的特点:

  • 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
  • 自增长字段必须是整数
  • 一张表最多只能有一个自增长
bash 复制代码
mysql> create table tt21(
   -> id int unsigned primary key auto_increment,
   -> name varchar(10) not null default ''
   -> );
mysql> insert into tt21(name) values('a');
mysql> insert into tt21(name) values('b');
mysql> select * from tt21;
+----+------+
| id | name |
+----+------+
|  1 | a   |
|  2 | b   |
+----+------+

在插入后获取上次插入的 AUTO_INCREMENT 的值(批量插入获取的是第一个值)

bash 复制代码
mysql > select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
|                1 |
+------------------+

7. 唯一键

  • 一张表中有往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键:唯一键就可以解决表中有多个字段需要唯一性约束的问题
  • 唯一键的本质和主键差不多,唯一键允许为空,而且可以多个为空,空字段不做唯一性比较。
  • 关于唯一键和主键的区别: 主键更多的是标识唯一性的。而唯一键更多的是保证在业务上,不要和别的信息出现重复
bash 复制代码
mysql> create table student (
   -> id char(10) unique comment '学号,不能重复,但可以为空',
   -> name varchar(10)
   -> );
Query OK, 0 rows affected (0.01 sec)
mysql> insert into student(id, name) values('01', 'aaa');

Query OK, 1 row affected (0.00 sec)
mysql> insert into student(id, name) values('01', 'bbb'); --唯一约束不能重复

ERROR 1062 (23000): Duplicate entry '01' for key 'id'
mysql> insert into student(id, name) values(null, 'bbb'); -- 但可以为空
Query OK, 1 row affected (0.00 sec)

mysql> select * from student;
+------+------+
| id   | name |
+------+------+
| 01   | aaa |
| NULL | bbb |
+------+------+

8. 外键

外键用于定义主表和从表之间的关系:

  • 外键约束主要定义在从表上,主表则必须是有主键约束或unique 约束
  • 当定义外键后,要求外键列数据 必须 主表的主键列存在或为null
  • 语法**:foreign key (字段名) references 主表(列)**

案例:

bash 复制代码
create table myclass (
 id int primary key,
 name varchar(30) not null comment'班级名'
 );

create table stu (
 id int primary key,
 name varchar(30) not null comment '学生名',
 class_id int,
 foreign key (class_id) references myclass(id)
 );

mysql> insert into myclass values(10, '1'),(20, '2');
Query OK, 2 rows affected (0.03 sec)
Records: 2 Duplicates: 0 Warnings: 0

mysql> insert into stu values(100, '张三', 10),(101, '李四',20);
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0

-插入一个班级号为30的学生,因为没有这个班级,所以插入不成功
mysql> insert into stu values(102, 'wangwu',30);
ERROR 1452 (23000): Cannot add or update a child row: 
a foreign key constraint fails (mytest.stu, CONSTRAINT stu_ibfk_1 
FOREIGN KEY (class_id) REFERENCES myclass (id))

-插入班级id为null,比如来了一个学生,目前还没有分配班级
mysql> insert into stu values(102, 'wangwu', null);
相关推荐
sugarzhangnotes2 小时前
应用服务OOM引发GC异常,导致Redis请求超时失败的问题分析与解决
数据库·redis·测试工具
SelectDB2 小时前
面向 Agent 的高并发分析:Doris vs. Snowflake vs. ClickHouse
数据库·apache·agent
alien爱吃蛋挞2 小时前
【JavaEE】Spring Boot日志
java·数据库·spring boot
zjeweler2 小时前
redis tools gui ---Redis图形化漏洞利用工具
数据库·redis·web安全·缓存
时光不弃青栀2 小时前
MySQL中的条件判断语句:除了CASE WHEN还有哪些选择?
mysql
Leon-Ning Liu2 小时前
Oracle 19c RAC ASM 密码文件恢复方案四:创建新密码文件覆盖恢复
数据库·oracle
思成不止于此2 小时前
【MySQL 零基础入门】DCL 核心语法全解析:用户管理与权限控制篇
数据库·笔记·sql·学习·mysql
武子康2 小时前
Java-192 深入拆解 EVCache 内部原理:Memcached 架构、Slab 分配与 LRU 过期机制全解析
数据库·redis·缓存·架构·memcached·guava·evcache
你好,帅哥3 小时前
sqlcipher 编译
数据库