MySQL表的约束:从基础到核心(附场景+案例)

⭐️个人主页:@小羊 ⭐️所属专栏:MySQL初阶 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~

目录

基础约束:控制字段的基础规则

空属性

  • 作用:限制字段不能为空(默认是NULL);

  • 坑点:空值无法参与运算(比如1+NULL结果还是NULL);

  • 案例:班级表的"班级名"不能空:

    sql 复制代码
    create table myclass(
      class_name varchar(20) not null, -- 必须填
      class_room varchar(10) not null
    );

默认值

  • 作用:字段没填值时,自动用预设值;

  • 案例:用户表的"性别"默认设为"男":

    sql 复制代码
    create table tt10(
      name varchar(20) not null,
      sex char(2) default '男' -- 没填则自动为"男"
    );
  • 小技巧:NOT NULLDEFAULT不用同时加(默认值本身不会空)。

列描述

  • 作用:给字段加"备注"(方便程序员理解);

  • 查看方式:用show create table 表名;才能看到(desc看不到);

  • 案例:

    sql 复制代码
    create table tt12(
      name varchar(20) not null comment '姓名',
      age tinyint unsigned default 0 comment '年龄'
    );

零填充

  • 作用:数字长度不够时,自动补0(仅显示效果,实际存储还是原数);
  • 案例:int(5) zerofill存1会显示00001
  • 注意:只改变显示,不改变实际存储的值。

核心约束:保证数据唯一性/关联性

主键

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

创建表的时候直接在字段上指定主键:


一般都是在使用表之前就要把主键确定下来。

  • 一张表中最多只能有一个主键,并不意味着一个表中的主键,只能添加给一列,一个主键可以被添加到一列,或多列上(复合主键)。

idcourse_id 有一个不冲突,就不会触发主键约束 ;只有 idcourse_id 同时冲突了,才会触发主键约束。

  • 作用:唯一标识一行数据,要求"非空+不重复";
  • 特点:一张表只能有1个主键,通常用整数类型;
  • 用法:
    • 单个字段主键:

      sql 复制代码
      create table tt13(
        id int unsigned primary key, -- 学号作为主键
        name varchar(20) not null
      );
    • 复合主键(多个字段联合唯一):

      sql 复制代码
      create table tt14(
        id int unsigned,
        course char(10),
        primary key(id, course) -- 学号+课程号联合唯一
      );

自增长

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

特点

  • 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)也就是必须是主键;
  • 自增长字段必须是整数;
  • 一张表最多只能有一个自增长;

案例:


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

如何理解索引:

想象你在读一本上千页的编程教材,里面有各种编程概念、代码示例和项目案例。要是没有目录,想找"如何实现数据库索引"这样的知识点,就得从第一页开始一页页翻,特别费时间和精力。

有了目录就不一样了,它按章节和主题列出了重要内容的页码。你直接在目录里找到"数据库索引"相关章节的页码,就能快速翻到对应页面查看内容。

数据库里的索引就像书的目录,表中的数据好比书里的正文。索引给表中的数据构建了类似目录的结构,能让数据库系统快速找到想要的数据,查找效率大大提高。

  • 作用:配合主键,自动生成"递增的整数"(不用手动填);

  • 特点:必须是整数+索引字段+一张表只能有1个;

  • 案例:

    sql 复制代码
    create table tt21(
      id int unsigned primary key auto_increment, -- 自动从1开始递增
      name varchar(10) not null
    );
  • 小技巧:用last_insert_id()可获取最后一次自增的值。

唯一键

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

唯一键的本质和主键差不多,唯一键允许为空,而且可以多个为空 ,空字段不做唯一性比较。

唯一键和主键的区别我们可以简单理解成,主键更多的是标识唯一性的。而唯一键更多的是保证在业务上,不要和别的信息出现重复。

主键就像班级中同学的学号,是唯一且不能为空的;唯一键就像身份证号,也是唯一的,但可能会有同学还没来得及登记身份证号,所以可以为空。

sql 复制代码
mysql> create table student(
    -> id int unsigned unique, 
    -> name varchar(20)
    -> );
Query OK, 0 rows affected (0.11 sec)

mysql> insert into student values (111, '张三');
Query OK, 1 row affected (0.02 sec)

mysql> insert into student values (222, '李四');
Query OK, 1 row affected (0.01 sec)

不能重复,但可以为空:

sql 复制代码
mysql> insert into student values (222, '王五');
ERROR 1062 (23000): Duplicate entry '222' for key 'student.id'
mysql> insert into student (name) values ('王五');
Query OK, 1 row affected (0.01 sec)
  • 作用:保证字段值不重复(但允许为空,空值不参与唯一性比较);

  • 和主键的区别:主键是"标识唯一",唯一键是"业务唯一"(一张表可以有多个);

  • 案例:员工表的"工号"不能重复(但可以为空):

    sql 复制代码
    create table student(
      id char(10) unique, -- 学号唯一
      name varchar(10)
    );

外键

建立和维护数据库中主表和从表之间关联关系的一种约束。

外键约束主要定义在从表上 ,主表则必须 是有主键约束或唯一键约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为NULL。

它是一个表中的一个或多个字段,其值对应于另一个表中的主键或唯一键。通过外键,可以确保相关表中的数据一致性和正确性,维护数据库表的引用完整性。

sql 复制代码
foreign key (字段名) references 主表(列) 

案例:

  • 先创建主键表:
sql 复制代码
mysql> create table class(
    -> id int unsigned primary key,
    -> name varchar(20) not null 
    -> );
Query OK, 0 rows affected (0.38 sec)
  • 再创建从表:
sql 复制代码
mysql> create table student(
    -> id int unsigned primary key,
    -> name varchar(20) not null,
    -> class_id int unsigned,
    -> foreign key (class_id) references class(id)
    -> );
Query OK, 0 rows affected (0.23 sec)
  • 插入合法数据:
sql 复制代码
mysql> insert into class values (1, 'C++班'), (2, 'Java班');
Query OK, 2 rows affected (0.05 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into student values (111, '张三', '1'), (222, '李四', '2');
Query OK, 2 rows affected (0.03 sec)
Records: 2  Duplicates: 0  Warnings: 0
  • 不能插入主表主键列不存在的数据,但可以插入NULL:
sql 复制代码
mysql> insert into student values (333, '王五', '3');
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`d1`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))
mysql> insert into student values (333, '王五', null);
Query OK, 1 row affected (0.00 sec)

如何理解外键约束:

  • 班级表:记录着每个班级的信息,其中"班级编号"是唯一标识每个班级的,它就像班级的身份证号,是班级表的主键 。比如有"1班""2班" ,每个班级对应一个独一无二的编号。
  • 学生表:用来记录每个学生的信息。学生是属于某个班级的,所以学生表中会有一个字段来表示学生所在班级,这个字段就可以设置为外键 。假设"学生表"里有个"所属班级编号"字段,它的值必须是"班级表"里已经存在的"班级编号" 。

如果没有外键约束,可能会出现这样的情况:在"学生表"里录入一个学生信息,把他的"所属班级编号"写成了一个不存在的编号,比如写成了"99班" ,可实际上"班级表"里根本没有这个班级。

但当我们在"学生表"的"所属班级编号"字段上设置了外键约束,并且这个外键约束关联到"班级表"的"班级编号"主键时,数据库就会进行检查。如果要插入一个学生信息,其"所属班级编号"在"班级表"里不存在,数据库就会拒绝这个插入操作,这样就能保证数据的一致性和准确性 。

再比如,如果"班级表"里删除了"3班"这个记录,要是没有外键约束,"学生表"里可能还存在标记为属于"3班"的学生记录,这就不合理了。但有了外键约束,我们可以设置当"班级表"里删除"3班"记录时,"学生表"里相关"3班"学生记录也跟着被删除(级联删除 ),或者把这些学生的"所属班级编号"设置为空(前提是允许为空 )等处理方式,从而维护两个表之间数据的关联和完整 。

  • 作用:关联两张表,保证从表的数据必须在主表中存在(避免无效数据);

  • 用法:主表要有主键/唯一键,从表通过外键关联;

  • 案例:学生表关联班级表(学生的班级ID必须是班级表中存在的):

    sql 复制代码
    -- 主表(班级表)
    create table myclass(
      id int primary key,
      name varchar(30) not null
    );
    -- 从表(学生表)
    create table stu(
      id int primary key,
      name varchar(30) not null,
      class_id int,
      foreign key(class_id) references myclass(id) -- 关联班级表的id
    );
  • 效果:插入学生时,class_id必须是myclass中存在的ID,否则插入失败。

约束怎么选?

  • 字段不能空→NOT NULL
  • 字段有默认值→DEFAULT
  • 唯一标识一行→PRIMARY KEY+AUTO_INCREMENT
  • 业务字段不能重复→UNIQUE
  • 两张表有关联→FOREIGN KEY

本篇文章的分享就到这里了,如果您觉得在本文有所收获,还请留下您的三连支持哦~

相关推荐
东南门吹雪1 小时前
PostgreSQL与MySQL的锁与隔离级别
mysql·postgresql·区块链
Wang's Blog1 小时前
MongoDB小课堂: 文档查询之匹配查询与比较操作符深度解析
数据库·mongodb
cookqq2 小时前
mongodb根据索引IXSCAN 查询记录流程
数据结构·数据库·sql·mongodb·nosql
p***32352 小时前
如何使用C#与SQL Server数据库进行交互
数据库·c#·交互
e***19352 小时前
MySQL-mysql zip安装包配置教程
android·mysql·adb
方白羽2 小时前
Kotlin遇上Java 静态方法
android·java·kotlin
h***34632 小时前
Redis安装教程(Windows版本)
数据库·windows·redis
q***65692 小时前
使用Canal将MySQL数据同步到ES(Linux)
linux·mysql·elasticsearch
蓝色记忆3 小时前
执行计划FirstMatch
mysql