mysql菜鸟教程

专栏导航

8.4 非空约束(NOT NULL)必须填写

      在创建表时,我们经常需要明确规定某些字段是必须填写的,不能为空。例如,用户注册时用户名不能为空、订单金额不能为空、商品名称不能为空。这时就需要使用非空约束(NOT NULL),它强制指定列的值不能为 NULL(未知或缺失)。

一、非空约束的作用

非空约束 非常简单直接:它要求该列在插入或更新记录时必须提供一个非 NULL 的值。如果试图将 NULL 插入到有 NOT NULL 约束的列中,数据库会拒绝操作并报错。

为什么需要非空约束?

  1. 保证数据完整性:确保关键字段都有值,避免出现“空记录”。

  2. 业务逻辑强制:例如,用户名、订单金额等字段在业务上必须存在,不应缺失。

  3. 避免程序错误:应用程序假设某些字段有值,如果数据库中出现 NULL 可能导致程序异常或计算错误。

  4. 便于查询和分析NULL 的处理需要特殊语法(IS NULL),尽量避免过多的 NULL 可以简化查询逻辑。

二、非空约束的创建与使用

1. 在建表时指定 NOT NULL

直接在列定义后面添加 NOT NULL 关键字:

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,    -- 用户名不能为空
    email VARCHAR(100) NOT NULL,      -- 邮箱不能为空
    age TINYINT NULL                  -- 年龄可以为空(如果不写 NULL,默认也是允许 NULL)
);

注意:如果不显式指定 NOT NULL,默认是允许 NULL 的(即 NULL 约束)。

2. 组合使用 NOT NULL 与 DEFAULT

NOT NULL 常与 DEFAULT 配合使用,为列指定一个默认值,这样即使插入时未提供值,也会自动填充默认值,从而避免违反非空约束。

CREATE TABLE products (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(200) NOT NULL,
    price DECIMAL(10,2) NOT NULL DEFAULT 0.00,  -- 默认价格为0,且不能为空
    stock INT NOT NULL DEFAULT 0
);

3. 修改表添加 NOT NULL 约束

如果表已经存在,可以使用 ALTER TABLE 添加非空约束。但必须确保现有数据中该列没有 NULL 值,否则操作会失败。

-- 假设已有表 users,现在要将 phone 列设为 NOT NULL
-- 第一步:先检查是否有 NULL 值
SELECT * FROM users WHERE phone IS NULL;

-- 如果有 NULL,需要先处理(更新为默认值或删除这些记录)
UPDATE users SET phone = '' WHERE phone IS NULL;  -- 或设为默认值

-- 第二步:修改列,添加 NOT NULL
ALTER TABLE users MODIFY phone VARCHAR(20) NOT NULL;

4. 删除 NOT NULL 约束

如果需要取消非空约束,允许列为空,可以使用 ALTER TABLE ... MODIFY 去掉 NOT NULL

ALTER TABLE users MODIFY phone VARCHAR(20) NULL;

或直接不指定 NOT NULL(默认就是允许 NULL):

ALTER TABLE users MODIFY phone VARCHAR(20);  -- 等价于允许 NULL

三、NULL 与空字符串的区别

初学者容易混淆 NULL 和 空字符串('')。它们在数据库中是两个完全不同的概念:

概念

含义

示例

是否为空?

NULL

值未知、不存在或未定义

phone = NULL

是(缺失)

空字符串 ''

一个长度为0的字符串值

phone = ''

否(有值,只是内容为空)

  • NULL 不能参与常规的比较运算(如 =<>),必须用 IS NULL 判断。

  • 空字符串是一个普通的值,可以用 = 比较,也会占用存储空间(虽然很小)。

非空约束只禁止 NULL,不禁止空字符串。所以如果业务上要求“手机号不能为空”,但允许空字符串作为占位符,那么 NOT NULL 约束仍然有效,因为空字符串不是 NULL。

四、非空约束的注意事项

  1. 默认值的影响:如果一个列既有 NOT NULL 又有 DEFAULT,插入时若未指定该列,则使用默认值填充,不会违反约束。如果没有 DEFAULT,则必须显式提供值。

  2. 与主键的关系:主键列自动具有 NOT NULL 和 UNIQUE 属性,无需重复指定。

  3. 修改已有列时的风险:向已有表添加 NOT NULL 约束前,必须确保现有数据没有 NULL,否则修改会失败。务必先检查和清理数据。

  4. 存储引擎差异NOT NULL 是 SQL 标准,所有存储引擎都支持。

  5. 性能影响NOT NULL 本身对性能几乎没有影响,但它可以让索引更高效(因为索引不需要存储 NULL 值)。

五、最佳实践建议

  1. 在业务上必须存在的字段都加上 NOT NULL,例如:用户名、邮箱、创建时间、状态等。

  2. 合理使用 DEFAULT:对于有明确默认值的字段,如 create_time 默认当前时间、status 默认 1,可以简化插入操作。

  3. 避免不必要的 NULL:过多的 NULL 会让查询复杂化,也占用存储空间(虽然 MySQL 中 NULL 的存储开销很小,但逻辑上复杂)。能用空字符串或 0 代替的,尽量使用这些默认值。

  4. 设计时考虑:在设计表结构时,就明确每个字段是否允许为空,而不是事后匆忙添加约束。

六、实战练习

场景:设计一个“文章表” articles

要求:

  • 文章标题不能为空。

  • 文章内容不能为空。

  • 作者 ID 不能为空(外键)。

  • 发布时间默认当前时间,且不能为空。

  • 阅读量默认为 0,可以为空(但建议非空,这里练习用 NULL)。

  • 状态默认为“草稿”,不能为空。

请写出建表语句,并尝试插入几条数据测试。

参考答案

CREATE TABLE articles (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200) NOT NULL,
    content TEXT NOT NULL,
    author_id INT NOT NULL,
    publish_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    views INT DEFAULT 0,                    -- 允许 NULL,但设置了默认值后插入时可省略
    status ENUM('draft', 'published', 'archived') NOT NULL DEFAULT 'draft'
);

-- 正常插入
INSERT INTO articles (title, content, author_id) 
VALUES ('MySQL 教程', '这是一篇关于 MySQL 的文章...', 1);

-- 尝试插入 NULL 标题(应失败)
INSERT INTO articles (title, content, author_id) VALUES (NULL, '内容', 1);
-- 错误:Column 'title' cannot be null

-- 尝试省略必填字段(应失败)
INSERT INTO articles (content, author_id) VALUES ('内容', 1);
-- 错误:Field 'title' doesn't have a default value

-- 插入默认值演示
INSERT INTO articles (title, content, author_id, status) 
VALUES ('高级 SQL', '内容...', 2, DEFAULT);  -- status 使用默认值 'draft'

挑战题

假设你有一个 employees 表,包含 nameemailphone 三列。现在需要将 email 改为 NOT NULL,但表中可能已经存在 email 为 NULL 的记录。请写出操作步骤。

步骤

  1. 查询是否有 NULL:SELECT * FROM employees WHERE email IS NULL;

  2. 处理 NULL 值:将 NULL 更新为默认值,例如 UPDATE employees SET email = '' WHERE email IS NULL; 或设置一个占位符。

  3. 修改列:ALTER TABLE employees MODIFY email VARCHAR(100) NOT NULL;

七、非空约束要点总结

方面

说明

作用

确保列的值不能为 NULL。

创建

建表时在列后加 

NOT NULL

;或 

ALTER TABLE MODIFY

 添加。

配合 DEFAULT

常用组合,为列提供默认值,避免插入时必须显式赋值。

NULL 与空字符串

不同,非空约束只禁止 NULL,不禁止空字符串。

修改表前准备

必须处理现有数据中的 NULL,否则无法添加 NOT NULL。

应用场景

所有业务上必须存在的字段。

非空约束是数据库设计中最基础也最重要的约束之一。它帮助我们确保关键数据不会缺失,为后续的数据处理打下坚实基础。


发表评论

昵称:
联系方式:
评论内容:

所有评论

关于我 备案号:蜀ICP备2023042032号-1