在设计数据库表结构时,有些字段并不希望出现空值,比如用户注册时间、订单状态、逻辑删除标记等。这类字段如果在插入数据时被遗漏,没有默认值的话就会变成NULL,后续查询和统计都要额外处理。SQL提供的DEFAULT关键字正是为了解决这个问题,它允许我们预先为字段设定一个默认值,当INSERT语句中没有为该字段提供值时,数据库会自动使用这个默认值填充。

DEFAULT关键字的基本语法与使用方式
DEFAULT关键字的作用是定义字段的默认值,它通常出现在CREATE TABLE语句的字段定义中,也可以通过ALTER TABLE语句为已存在的字段补充默认值。基本语法形式是在字段类型和约束之后加上DEFAULT,再跟上具体的值或表达式。
先看建表时的写法,下面这个例子创建了一张用户表,其中注册时间和状态字段都设置了默认值:
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
status TINYINT DEFAULT 1, -- 状态默认为1,表示正常
created_at DATETIME DEFAULT CURRENT_TIMESTAMP -- 默认为当前时间
);如果表已经存在,想在后期补充或修改默认值,可以使用ALTER TABLE语句。写法略有差异,MySQL中可以这样写:
-- 修改已有字段的默认值 ALTER TABLE users ALTER COLUMN status SET DEFAULT 1; -- SQL Server 的写法 ALTER TABLE users ADD CONSTRAINT df_status DEFAULT 1 FOR status;
需要注意的是,MySQL中还可以在INSERT时显式使用DEFAULT关键字,表示让数据库填入默认值,例如INSERT INTO users (id, username, status) VALUES (1, 'tom', DEFAULT);,这样即使知道字段有默认值,也可以不用硬编码具体的数值。
不同数据类型的默认值设置示例
默认值并不限于简单的数字,几乎所有常见数据类型都可以设置默认值,但不同类型在写法上有一些细节要注意。
数值类型的默认值直接写数字即可,比如商品数量默认为0、折扣默认为1。字符串类型的默认值需要用引号包裹,比如默认姓名写为DEFAULT '未知用户'。日期时间类型则常配合函数使用,MySQL中CURRENT_TIMESTAMP可以作为DATETIME或TIMESTAMP字段的默认值,这在记录创建时间时特别常用。下面是一个综合示例:
CREATE TABLE products (
id INT PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) DEFAULT 0.00, -- 数值默认值
category VARCHAR(20) DEFAULT '未分类', -- 字符串默认值
stock INT DEFAULT 0, -- 库存默认为0
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间默认当前
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP -- 更新时自动刷新
);PostgreSQL还支持更灵活的表达式默认值,例如DEFAULT now()、DEFAULT uuid_generate_v4(),可以为字段自动生成UUID。SQL Server从较新版本开始也支持序列和函数作为默认值。总体而言,常量、系统函数返回值都可以作为默认值,但不能引用同一张表中的其他字段。
默认值与NOT NULL约束的配合关系
默认值和NOT NULL约束经常一起使用,但两者的含义完全不同,不少初学者会把它们混为一谈。NOT NULL是约束,禁止字段出现NULL;DEFAULT是填充规则,告诉数据库在没传值时填什么。一个字段可以只有默认值而不禁止NULL,这样显式插入NULL时依然是NULL;也可以只有NOT NULL而没有默认值,这样不传值又没默认值时INSERT会直接报错。
两者配合使用的典型场景是这样的:状态字段既要保证不为空,又要有合理的初始状态,写法为status TINYINT NOT NULL DEFAULT 1。这样无论插入语句是否携带该字段,status永远是一个有效的数字。
还有一个容易忽略的细节:如果把字段设置为允许NULL并且设置了默认值,当INSERT语句中显式给字段传NULL时,数据库不会用默认值,而是老老实实存入NULL。只有字段完全不出现在INSERT语句中,默认值才会生效。这一点在有ORM框架自动补全字段的项目中尤其要注意,有些ORM会把未赋值的字段自动填成NULL发给数据库,导致默认值形同虚设。
修改默认值时的注意事项与常见坑
实际项目中经常需要调整默认值,比如把新用户的初始状态从1改为0。这里有几个容易踩坑的地方值得提前了解。
第一,修改默认值只影响之后的新插入数据,不会更新表中已有的历史数据。想要把存量数据也改过来,需要额外执行UPDATE语句:
-- 先把存量 NULL 数据补上 UPDATE users SET status = 1 WHERE status IS NULL; -- 再调整默认值(MySQL 写法) ALTER TABLE users MODIFY COLUMN status TINYINT DEFAULT 1;
第二,MySQL中用MODIFY COLUMN修改字段时,如果没有把原有的其他属性一并写上(比如NOT NULL、注释等),这些属性会被丢弃,导致字段定义被意外改变。稳妥的做法是先执行SHOW CREATE TABLE users;查看完整的字段定义,在原有基础上只改默认值部分。
第三,TIMESTAMP类型的默认值在不同数据库和不同时区配置下行为可能不同,MySQL中TIMESTAMP会随时区转换而DATETIME不会,做国际化系统时要留意这个差异。另外,如果要删除默认值,MySQL的写法是ALTER TABLE users ALTER COLUMN status DROP DEFAULT;,删除后字段再没有默认值时,插入不传值就会存入NULL(前提是字段允许NULL)。
掌握好DEFAULT关键字的用法,能让数据库层主动承担一部分数据完整性保障工作,减少应用层重复的判空和填充逻辑,让表结构设计更加健壮清晰。
SQL默认值DEFAULT关键字数据库表设计修改时间:2026-09-04 17:30:38