mysql菜鸟教程
8.5 默认值(DEFAULT)
在插入数据时,我们经常希望某些字段能够自动填充一个合理的值,而不必每次都显式指定。比如,新用户注册时,注册时间自动设为当前时间;新上架的商品,库存默认为0;文章状态默认为“草稿”。这时就需要使用默认值(DEFAULT) 约束,它为列指定一个“后备值”,当插入语句没有为该列提供值时,数据库会自动使用这个默认值。
一、默认值的作用
简化数据插入:减少重复输入,提高开发效率。
保证数据完整性:避免因遗漏赋值而产生 NULL 或不合理的值。
业务逻辑预设:为字段设置符合业务规则的初始值(如状态、计数等)。
与非空约束配合:当列有 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: 03. 显式使用 DEFAULT 关键字
在插入时,也可以显式地使用 DEFAULT 关键字来引用列的默认值:
INSERT INTO users (username, age, status)
VALUES ('李四', DEFAULT, DEFAULT); -- age 和 status 使用默认值4. 使用表达式作为默认值
MySQL 允许使用某些函数作为默认值,最常用的就是 CURRENT_TIMESTAMP 用于 DATETIME 或 TIMESTAMP 类型。此外,CURRENT_DATE、CURRENT_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 经常一起使用,理解它们的组合行为很重要:
示例对比
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)。
五、注意事项
默认值类型必须匹配:指定的默认值必须与列的数据类型兼容。例如,INT 列不能默认 'abc'。
表达式默认值的限制:在 MySQL 8.0.13 之前,只有 TIMESTAMP 和 DATETIME 类型可以使用 CURRENT_TIMESTAMP 作为默认值,其他列只能使用常量。新版本支持将表达式用括号包裹作为默认值,但仍有部分限制(如不允许引用其他列)。
与自增列的关系:AUTO_INCREMENT 列会自动生成值,通常不需要指定默认值。如果同时指定,默认值会被忽略(除非自增值用尽)。
BLOB/TEXT 类型:BLOB、TEXT 等类型可以设置默认值,但必须是常量,且可能受长度限制。
默认值不会触发约束检查:默认值本身必须满足列的其他约束(如数据类型、长度),但不会触发外键等检查(外键检查发生在插入时,默认值也会被检查)。
六、最佳实践建议
为常用的状态字段设置默认值:例如 status、is_deleted、created_at。
配合 NOT NULL 使用:对于业务上必须存在的字段,建议同时使用 NOT NULL 和 DEFAULT,避免因遗漏而产生错误。
合理选择默认值:默认值应反映业务上的初始状态(如新订单状态为“待支付”),而不是随意设置。
使用时间戳默认值:created_at 字段通常设为 DEFAULT CURRENT_TIMESTAMP,updated_at 可能需要配合 ON UPDATE CURRENT_TIMESTAMP(这属于额外特性,将在后续介绍)。
避免使用 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;
八、默认值要点总结
默认值是数据库设计中一个简单但极其有用的工具,它能减少重复劳动、防止数据缺失。结合非空约束,我们可以为每个字段定义清晰的行为,让数据录入更加规范和高效。

发表评论
所有评论