MYSQL-表的约束(下)

目录

自增长

唯一键

外键


自增长

MySQL自增长(Auto-Increment) 是一种字段属性,用于为表中的记录自动生成唯一的连续整数,常作为主键或唯一标识字段使用,避免手动输入重复值。

**核心特性

  1. 自动赋值:插入数据时,无需指定该字段值,MySQL会自动分配比当前最大值大1的整数。
  2. 唯一性保障:默认情况下,自增长值唯一(需配合主键或唯一索引使用,否则可能报错)。
  3. 初始值与步长:默认从 1 开始,每次递增 1 ,也可手动修改初始值和步长。
  4. 不可回滚:删除数据后,自增长值不会自动回退(如删除ID=5的记录,下次插入仍会是6而非5)。**

常见使用场景与语法

  1. 创建表时设置自增长(常用)

通常将自增长字段设为主键,语法如下:

sql 复制代码
CREATE TABLE 表名 (
    字段名 INT AUTO_INCREMENT PRIMARY KEY,  -- 自增长+主键
    其他字段 数据类型,
    ...
);

示例:创建"学生表",用 student_id 作为自增长主键

sql 复制代码
CREATE TABLE students (
    student_id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50),
    age INT
);
  1. 插入数据(无需指定自增长字段)
sql 复制代码
INSERT INTO students (name, age) VALUES ('张三', 20), ('李四', 21);

插入后 student_id 会自动生成 1 和 2 。

  1. 修改自增长初始值/步长
sql 复制代码
- 修改初始值(需确保新值大于当前最大自增长值):
  
ALTER TABLE students AUTO_INCREMENT = 100;  -- 下次插入从100开始
 
- 修改步长(需先修改会话变量或全局变量,仅对新表生效):
  
SET @@auto_increment_increment = 2;  -- 步长改为2,下次插入依次为100、102...

注意事项

**- 支持的数据类型:仅支持整数类型(如 INT 、 BIGINT ),不支持字符串、浮点型等。

  • 一张表仅一个:每个表只能有一个 AUTO_INCREMENT 字段,且该字段必须是主键或唯一索引的一部分。
  • 批量插入与自增长:批量插入时,自增长值会按插入条数连续分配,即使部分插入失败,已占用的自增长值也不会复用。**

唯一键

MySQL唯一键(Unique Key) 是一种约束,用于确保表中指定字段或字段组合的值在所有记录中唯一不重复,但允许字段值为 NULL (且多个 NULL 值不视为重复),常用来标识非主键但需唯一的信息。

核心特性

**- 唯一性约束:约束字段的所有非 NULL 值必须唯一,例如"用户表"中的"手机号""邮箱"。

  • 允许NULL值:与主键(非空+唯一)不同,唯一键字段可包含 NULL ,且一张表中同一唯一键字段可存在多个 NULL (因 NULL 在MySQL中视为"未知",不与其他 NULL 比较)。
  • 自动创建索引:MySQL会为唯一键自动创建唯一索引,提升基于该字段的查询效率,同时避免重复值插入。
  • 数量无限制:一张表可创建多个唯一键(主键仅能有一个),满足多维度的唯一性需求。**

常见使用场景与语法

  1. 创建表时定义唯一键

可通过两种方式指定,直接在字段后加 UNIQUE ,或单独用 UNIQUE KEY 子句(适合复合唯一键)。

示例1:单一字段唯一键(如用户手机号)

cpp 复制代码
CREATE TABLE users (
    user_id INT AUTO_INCREMENT PRIMARY KEY,  -- 主键
    phone VARCHAR(20) UNIQUE,  -- 单一字段唯一键(手机号唯一)
    email VARCHAR(50),
    UNIQUE KEY uk_email (email)  -- 单独定义唯一键(邮箱唯一,指定约束名uk_email)
);

示例2:复合唯一键(多字段组合唯一,如"课程表"的"学期+课程号")

需多字段组合才能唯一标识时使用,例如同一学期内课程号不能重复,但不同学期可重复。

sql 复制代码
CREATE TABLE courses (
    course_id INT AUTO_INCREMENT PRIMARY KEY,
    term VARCHAR(20),  -- 学期(如"2024春")
    course_no VARCHAR(20),  -- 课程号(如"CS101")
    course_name VARCHAR(50),
    UNIQUE KEY uk_term_course_no (term, course_no)  -- 复合唯一键
);
  1. 给已有表添加唯一键

通过 ALTER TABLE 语句为现有表新增唯一键:

sql 复制代码
-- 给users表的"身份证号"字段加唯一键
ALTER TABLE users ADD UNIQUE KEY uk_id_card (id_card);

-- 给courses表加"学期+教师ID"的复合唯一键
ALTER TABLE courses ADD UNIQUE KEY uk_term_teacher (term, teacher_id);
 
  1. 删除唯一键

需通过唯一键的约束名删除(若创建时未指定,可通过 SHOW CREATE TABLE 表名 查看默认名):

cpp 复制代码
-- 删除users表中名为uk_email的唯一键
ALTER TABLE users DROP INDEX uk_email;

唯一键与主键的核心区别

|------|-------------------|------------------|
| 对比维度 | 唯一键(Unique Key) | 主键(Primary Key) |
| 非空性 | 允许字段值为 NULL (可多个) | 不允许为 NULL (必须非空) |
| 数量限制 | 一张表可创建多个 | 一张表仅能有一个 |
| 主要作用 | 约束非主键字段的唯一性(如手机号) | 唯一标识表中每条记录(核心标识) |
| 索引类型 | 自动创建唯一索引 | 自动创建主键索引(查询效率更高) |

外键

一、外键是干啥的?

一句话总结:外键是"表与表之间的关联锁" ,用来约束两张表的数据必须"合理关联",避免存一堆"无效/错误关联"的数据。

例子:

  • 班级表(myclass) :存班级信息, id 是主键(比如 10 对应"c++大牛班", 20 对应"java大神班" )。

  • 学生表(stu) :存学生信息, class_id 是外键,用来关联"班级表的 id "。

用外键约束后,学生表的 class_id 必须是班级表 id 里有的值 ,否则不让存!

二、外键怎么用?

  1. 先建"主表"(被关联的表,必须有主键/唯一键)

比如先建班级表 myclass , id 是主键(主键自带"唯一、非空"约束,适合被外键关联):

sql 复制代码
  create table myclass (
    id int primary key,  -- 主键,班级唯一标识
    name varchar(30) not null comment '班级名'
);
  1. 再建"从表"(关联主表的表,通过外键约束)

建学生表 stu 时,用 foreign key (class_id) references myclass(id) 声明:

  • class_id 是外键字段,要关联 myclass 表的 id 字段。
sql 复制代码
create table stu (
    id int primary key,
    name varchar(30) not null comment '学生名',
    class_id int,  -- 用来关联班级表的id
    foreign key (class_id) references myclass(id)  -- 外键约束!
);
  1. 插入数据,看外键咋"管事儿"
  • 正常插入(主表有对应数据) :

先往班级表插班级 (10, 'c++大牛班'), (20, 'java大神班') ,再往学生表插 (100, '张三', 10), (101, '李四', 20) ,因为 class_id ( 10 、 20 )在班级表 id 里存在,所以能成功。

  • 插"无效班级"(主表没对应数据) :

想插 (102, 'wangwu', 30) ,但班级表根本没有 id=30 的班级,直接报错!

(报错内容: Cannot add or update a child row: a foreign key constraint fails ,意思是"外键约束失败,不让插" )

  • 插 NULL (还没分班的学生) :
    外键允许 class_id 为 NULL ,所以能插 (102, 'wangwu', null) (表示学生还没分班,关联关系暂时"空着" )。

三、为啥要用外键?(解决啥问题?)

防"数据冗余 + 无效关联" !

  • 不用外键的话,你可以随便往学生表插 class_id=100 (但班级表根本没这个班),时间长了数据就乱套------"学生说自己是100班的,但系统里根本没这个班" 。

  • 用了外键,MySQL 会帮你"把关" :学生表的 class_id 必须在班级表 id 里存在 ,否则直接拦截,保证数据关联"合理" 。

四、外键的核心规则(必记!)

  1. 主表必须有"主键/唯一键" :外键要关联的字段(比如班级表 id ),得是主键( primary key )或唯一键( unique ),保证"被关联的值是唯一的"。

  2. 外键字段的值,要么在主表存在,要么为 NULL :如果不想关联任何主表数据,就设为 NULL (但字段本身得允许 NULL ,像class_id 没写 not null ,所以能插 NULL )。

  3. 删主表数据要小心 :如果主表数据被从表关联(比如班级表 id=10 ,学生表有学生关联它),直接删主表数据会报错!(得先删从表关联数据,或设置"级联删除" ,简单场景先记住"主表数据被关联时不能直接删" )

一句话总结外键 :它是表与表之间的"关联保镖",让 MySQL 帮你管着"谁能关联谁",避免存一堆"瞎关联"的数据,让表关系更清晰、数据更靠谱!