mysql菜鸟教程

专栏导航

8.5 默认值(DEFAULT)

      在插入数据时,我们经常希望某些字段能够自动填充一个合理的值,而不必每次都显式指定。比如,新用户注册时,注册时间自动设为当前时间;新上架的商品,库存默认为0;文章状态默认为“草稿”。这时就需要使用默认值(DEFAULT) 约束,它为列指定一个“后备值”,当插入语句没有为该列提供值时,数据库会自动使用这个默认值。

一、默认值的作用

  1. 简化数据插入:减少重复输入,提高开发效率。

  2. 保证数据完整性:避免因遗漏赋值而产生 NULL 或不合理的值。

  3. 业务逻辑预设:为字段设置符合业务规则的初始值(如状态、计数等)。

  4. 与非空约束配合:当列有 NOT NULL 约束时,默认值可以确保即使插入时未提供值,也不会违反非空规则。

二、默认值的定义与使用

1. 在创建表时指定默认值

在列定义后使用 DEFAULT 关键字指定默认值:

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    age TINYINT DEFAULT 18,                 -- 年龄默认 18
    status ENUM('active', 'inactive') DEFAULT 'active',  -- 状态默认 active
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,       -- 创建时间默认为当前时间
    is_admin BOOLEAN DEFAULT FALSE          -- 默认为普通用户
);

2. 插入数据时观察默认值生效

-- 只提供必需字段,其他使用默认值
INSERT INTO users (username) VALUES ('张三');

-- 查看结果
SELECT * FROM users;
-- id: 1, username: '张三', age: 18, status: 'active', created_at: 当前时间, is_admin: 0

3. 显式使用 DEFAULT 关键字

在插入时,也可以显式地使用 DEFAULT 关键字来引用列的默认值:

INSERT INTO users (username, age, status) 
VALUES ('李四', DEFAULT, DEFAULT);   -- age 和 status 使用默认值

4. 使用表达式作为默认值

MySQL 允许使用某些函数作为默认值,最常用的就是 CURRENT_TIMESTAMP 用于 DATETIME 或 TIMESTAMP 类型。此外,CURRENT_DATECURRENT_TIME 也可以使用。

CREATE TABLE logs (
    id INT PRIMARY KEY AUTO_INCREMENT,
    message TEXT,
    log_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    log_date DATE DEFAULT (CURRENT_DATE)   -- MySQL 8.0.13+ 支持将表达式放在括号内
);

注意:在 MySQL 8.0.13 之前,默认值只能是常量或 CURRENT_TIMESTAMP(针对时间戳)。对于更复杂的表达式,可能需要使用触发器或应用程序层实现。

三、默认值与 NOT NULL 的关系

默认值和 NOT NULL 经常一起使用,理解它们的组合行为很重要:

组合

插入时未指定该列

插入时指定为 NULL

说明

NOT NULL + DEFAULT

使用默认值

错误

(因为 NULL 被拒绝)

最常用组合,保证列始终有非空值。

NOT NULL + 无 DEFAULT

错误

(无默认值且未指定)

错误

插入时必须显式提供值。

允许 NULL + DEFAULT

使用默认值

插入 NULL

默认值在未指定时生效,但允许主动插入 NULL。

允许 NULL + 无 DEFAULT

插入 NULL

插入 NULL

默认值为 NULL(隐式)。

示例对比

CREATE TABLE example (
    a INT NOT NULL DEFAULT 1,   -- NOT NULL + DEFAULT
    b INT NOT NULL,              -- NOT NULL + 无 DEFAULT
    c INT DEFAULT 2,             -- 允许 NULL + DEFAULT
    d INT                        -- 允许 NULL + 无 DEFAULT(隐式 DEFAULT NULL)
);

-- 成功插入
INSERT INTO example (b) VALUES (10);   -- a 使用默认 1,c 使用默认 2,d 为 NULL

-- 错误:b 未提供值且无默认值
INSERT INTO example (a) VALUES (5);    -- 错误:Field 'b' doesn't have a default value

-- 错误:为 NOT NULL 列指定 NULL
INSERT INTO example (a, b) VALUES (NULL, 20);  -- 错误:Column 'a' cannot be null

四、修改与删除默认值

1. 添加或修改默认值

使用 ALTER TABLE ... ALTER COLUMN ... SET DEFAULT 或 MODIFY COLUMN

-- 方式一:ALTER COLUMN(仅修改默认值,不影响其他属性)
ALTER TABLE users ALTER COLUMN age SET DEFAULT 20;

-- 方式二:MODIFY COLUMN(需要完整重数列定义)
ALTER TABLE users MODIFY age TINYINT NOT NULL DEFAULT 20;

2. 删除默认值

使用 ALTER TABLE ... ALTER COLUMN ... DROP DEFAULT

ALTER TABLE users ALTER COLUMN age DROP DEFAULT;

删除默认值后,该列的默认行为变为 NULL(如果列允许 NULL)或插入时必须提供值(如果列有 NOT NULL)。

五、注意事项

  1. 默认值类型必须匹配:指定的默认值必须与列的数据类型兼容。例如,INT 列不能默认 'abc'。

  2. 表达式默认值的限制:在 MySQL 8.0.13 之前,只有 TIMESTAMP 和 DATETIME 类型可以使用 CURRENT_TIMESTAMP 作为默认值,其他列只能使用常量。新版本支持将表达式用括号包裹作为默认值,但仍有部分限制(如不允许引用其他列)。

  3. 与自增列的关系AUTO_INCREMENT 列会自动生成值,通常不需要指定默认值。如果同时指定,默认值会被忽略(除非自增值用尽)。

  4. BLOB/TEXT 类型:BLOB、TEXT 等类型可以设置默认值,但必须是常量,且可能受长度限制。

  5. 默认值不会触发约束检查:默认值本身必须满足列的其他约束(如数据类型、长度),但不会触发外键等检查(外键检查发生在插入时,默认值也会被检查)。

六、最佳实践建议

  1. 为常用的状态字段设置默认值:例如 statusis_deletedcreated_at

  2. 配合 NOT NULL 使用:对于业务上必须存在的字段,建议同时使用 NOT NULL 和 DEFAULT,避免因遗漏而产生错误。

  3. 合理选择默认值:默认值应反映业务上的初始状态(如新订单状态为“待支付”),而不是随意设置。

  4. 使用时间戳默认值created_at 字段通常设为 DEFAULT CURRENT_TIMESTAMPupdated_at 可能需要配合 ON UPDATE CURRENT_TIMESTAMP(这属于额外特性,将在后续介绍)。

  5. 避免使用 NULL 作为默认值:除非业务上确实允许未知,否则尽量用有意义的默认值代替 NULL。

七、实战练习

场景:设计一个“任务管理”表 tasks

要求:

  • 任务名称不能为空,无默认值(必须提供)。

  • 任务描述默认为空字符串('')。

  • 优先级默认为 'medium'(枚举值:'low', 'medium', 'high')。

  • 创建时间默认为当前时间。

  • 是否已完成默认为 FALSE。

  • 完成时间可以为空,无默认值。

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

参考答案

CREATE TABLE tasks (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200) NOT NULL,
    description TEXT NOT NULL DEFAULT '',
    priority ENUM('low', 'medium', 'high') NOT NULL DEFAULT 'medium',
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    is_completed BOOLEAN NOT NULL DEFAULT FALSE,
    completed_at DATETIME NULL
);

-- 插入数据
INSERT INTO tasks (title) VALUES ('学习 MySQL 默认值');   -- 其他字段使用默认值
INSERT INTO tasks (title, priority) VALUES ('重要任务', 'high');

-- 查看结果
SELECT * FROM tasks;
-- 第一条:description = '', priority = 'medium', created_at = 当前时间, is_completed = 0, completed_at = NULL
-- 第二条:description = '', priority = 'high', 其他同上

挑战题

如果要将 tasks 表的 is_completed 默认值改为 TRUE,并且不允许 NULL,写出修改语句。

ALTER TABLE tasks MODIFY is_completed BOOLEAN NOT NULL DEFAULT TRUE;

八、默认值要点总结

方面

说明

作用

为列提供默认值,简化插入,保证完整性。

语法

列名 数据类型 DEFAULT 默认值

常用默认值

常量、CURRENT_TIMESTAMP、CURRENT_DATE(MySQL 8.0.13+ 支持表达式)

修改

ALTER TABLE ... ALTER COLUMN ... SET DEFAULT

 或 

MODIFY COLUMN

删除

ALTER TABLE ... ALTER COLUMN ... DROP DEFAULT

与 NOT NULL

常配合使用,确保列总有非空值。

注意事项

类型匹配、表达式限制、不适用于 AUTO_INCREMENT 等。

默认值是数据库设计中一个简单但极其有用的工具,它能减少重复劳动、防止数据缺失。结合非空约束,我们可以为每个字段定义清晰的行为,让数据录入更加规范和高效。


发表评论

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

所有评论

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