LLEARNING NOTES

技术 · 思考 · 实践 · 成长

首页/MySQL8专栏/正文

MySQL 8 的约束(Constraint):从分类基础、典型案例,到很多教程没讲透的底层细节

MySQL8专栏9 次阅读

一、约束是什么&怎么分类

约束是写在表结构里、由存储引擎强制执行的“数据完整性规则”。和“应用层校验”的本质区别是:约束在数据库这一层兜底,应用绕不过去。

从功能维度,MySQL8分为三大类:

image.png

二、约束详解

1、NOT NULL -- 禁止空值

最基础的域约束,保证列必须有值。

CREATE TABLE user (
  id   BIGINT PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  email VARCHAR(100)         -- 允许为 NULL
);

注意:NOT NULL 与“空字符串”不是一回事,‘ ’是合法的非NULL值。

2、Default -- 默认值

插入未指定该列时自动填入。MySQL8支持表达式默认值(DEFAULT(expr)),这是8.0相对旧版本的增强。

CREATE TABLE orders (
  id        BIGINT PRIMARY KEY,
  created_at DATETIME DEFAULT (NOW()),        -- 8.0 表达式默认值
  status    VARCHAR(20) DEFAULT 'PENDING'
);

3、UNIQUE -- 唯一但允许空

保证列 值 不重复,但 NULL 例外:

CREATE TABLE user (
  id   BIGINT PRIMARY KEY,
  email VARCHAR(100) NOT NULL UNIQUE
);

4、PRIMARY KEY  -- 主键

= NOT NULL + UNIQUE ,且全表唯一、只能有一个(但可以是多列组合)

CREATE TABLE order_item (
  order_id  BIGINT,
  product_id BIGINT,
  qty       INT,
  PRIMARY KEY (order_id, product_id)   -- 复合主键
);

5、FOREIGN KEY -- 外键

保证子表某列的值必须在父表存在,维护表间引用一致性:


CREATE TABLE customer (
  id   BIGINT PRIMARY KEY,
  name VARCHAR(50) NOT NULL
);
CREATE TABLE `order` (
  id          BIGINT PRIMARY KEY,
  customer_id BIGINT NOT NULL,
  amount      DECIMAL(10,2),
  CONSTRAINT fk_order_cust
    FOREIGN KEY (customer_id) REFERENCES customer(id)
    ON DELETE CASCADE ON UPDATE RESTRICT
);

6、CHECK -- 取值范围校验(8.0真正生效)

CREATE TABLE product (
  id    BIGINT PRIMARY KEY,
  price DECIMAL(10,2) NOT NULL,
  stock INT NOT NULL,
  CONSTRAINT chk_price CHECK (price > 0),
  CONSTRAINT chk_stock CHECK (stock >= 0)
);
-- 以下插入将被拒绝:
INSERT INTO product VALUES (1, -5, 10);  -- ERROR 3819 (HY000): Check constraint failed


三、深入理解

1、约束不等于索引,但强相关

PRIMARY KEY 和 UNIQUE 会自动创建唯一索引(InnoDB 下)。所以唯一约束的查找走索引,速度快。

FOREIGN KEY 不会自动给子表外键建索引,但要求父表被引用列必须有索引(通常是主键/唯一键)。

子表外键列建议手动加索引,否则级联更新/删除会全表扫描父表、易锁表。


2. NULL 在 UNIQUE 中的特殊性

InnoDB 的 UNIQUE 索引允许插入多个 NULL(因为 NULL 被视为"未知",彼此不相等,所以不违反唯一)。

这与主键不同——主键列本身隐含 NOT NULL,不可能有 NULL。

CREATE TABLE t (a INT UNIQUE);
INSERT INTO t VALUES (NULL), (NULL);  -- 成功,两条 NULL 都被接受


知识是抵御一切灾祸的盾牌

评论交流

理性讨论,共同进步
验证码

相关文章

继续阅读