默认值介绍
数据类型规范可以有显式或隐式的默认值。默认值用来指定某列的值,在表中插入或更新一条新记录时,如果没有为某个字段赋值,系统就会自动为这个字段插入默认值。当然也可以通过DDL命令删除默认值。
默认值特点如下:
- 一个表可以有很多的默认值约束
- 默认值只能针对某一个Column字段
- 默认值约束该字段如果没有手动赋值,会按默认值处理
1.数据类型规范中的DEFAULT值子句显式地指示列的默认值,在default子句中指定的默认值可以是文字常量或表达式
MySQL> CREATE TABLE t1 (
i INT DEFAULT 0,
c VARCHAR(10) DEFAULT '',
-- expression defaults
f FLOAT DEFAULT (RAND() * RAND()),
b BINARY(16) DEFAULT (UUID_TO_BIN(UUID())),
d DATE DEFAULT (CURRENT_DATE + INTERVAL 1 YEAR),
p POINT DEFAULT (Point(0,0)),
j JSON DEFAULT (JSON_ARRAY())
);
- 对于TIMESTAMP和DATETIME列,可以指定CURRENT_TIMESTAMP函数作为默认值,不需要括号.
MySQL> CREATE TABLE `t2` (
`ID` int(11) NOT NULL,
`CREATE_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UPDATE_TIME` timestamp NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB;
- 只有当BLOB、TEXT、GEOMETRY和JSON数据类型被写为表达式时,才能被赋值为默认值
MySQL> CREATE TABLE t2 (b BLOB DEFAULT ('abc'));
- 表达式默认值必须遵守以下规则:
-
允许使用文字、内置函数(包括确定性函数和非确定性函数)和操作符
-
子查询、参数、变量、存储函数和可加载函数是不允许的。
-
表达式默认值不能依赖于具有AUTO_INCREMENT属性的列。
-
表达式默认值不能包含对生成的列或具有表达式默认值的列的前向引用。
-
排序约束也适用于使用ALTER TABLE对表列进行重新排序。如果结果表具有表达式默认值,其中包含对生成的列或具有表达式默认值的列的前向引用,则语句失败。
-
CREATE TABLE … LIKE and CREATE TABLE … SELECT 目标表保留原始表中的表达式默认值
-
对于复制环境,binlog禁用或则 binlog_format设置为STATEMENT会提示警告同时无法保证数据一致,索引binlog模式设置为MIXED或ROW。
-
BLOB、TEXT、GEOMETRY和JSON数据类型不能分配默认值。
-
日期 对于TIMESTAMP和DATETIME列,可以指定CURRENT_TIMESTAMP为默认值。
- 默认值插入方式
MySQL> CREATE TABLE t3 (uid BINARY(16) DEFAULT (UUID_TO_BIN(UUID())));
MySQL> INSERT INTO t3 () VALUES();
MySQL> INSERT INTO t3 () VALUES(DEFAULT);
MySQL> SELECT BIN_TO_UUID(uid) AS uid FROM t3;
+--------------------------------------+
| uid |
+--------------------------------------+
| 16653083-f8e3-11ec-8198-00163e23e2cc |
| 1c34bb68-f8e3-11ec-8198-00163e23e2cc |
+--------------------------------------+
2 rows in set (0.00 sec)
#查看默认值方式
MySQL> DESC `t2`;
MySQL> SHOW CREATE TABLE `t2`;
#查询单独某个字段的默认值
MySQL> SELECT default(CREATE_time) FROM t2;
+----------------------+
| default(CREATE_time) |
+----------------------+
| 0000-00-00 00:00:00 |
+----------------------+
1 row in set (0.00 sec)
注意:使用DEFAULT(col_name)为命名列指定默认值只允许具有文字默认值的列使用,而不允许具有表达式默认值的列使用。
常见问题
1.sql_mode严格模式
参数sql_mode的STRICT_TRANS_TABLES(严格模式,非法数据值被拒绝)影响Default值插入
数值类型,默认值是0,字符串是空。
MySQL> CREATE TABLE t4 (a INT NOT NULL);
Query OK, 0 rows affected (0.01 sec)
#默认值插入失败
MySQL> INSERT INTO t4 VALUES();
ERROR 1364 (HY000): Field 'i' doesn't have a default value
#模式更改正常插入类型对应的默认值
MySQL> SET SESSION sql_mode="";
Query OK, 0 rows affected (0.00 sec)
MySQL> INSERT INTO t4 VALUES();
Query OK, 1 row affected, 1 warning (0.00 sec)
MySQL> select * from t4;
+---+
| a |
+---+
| 0 |
+---+
1 row in set (0.00 sec)
#string类型
MySQL> CREATE TABLE t5 (b varchar(20) NOT NULL);
MySQL> SET SESSION sql_mode="";
MySQL> INSERT INTO t5 VALUES(DEFAULT);
MySQL> select b, length(b)from t5;
+---+-----------+
| b | length(b) |
+---+-----------+
| | 0 |
+---+-----------+
1 row in set (0.00 sec)
2)AUTO_INCREMENT属性字段, 序列中的下一个值
MySQL> CREATE TABLE t5 (
b INT AUTO_INCREMENT ,
key(b) );
Query OK, 0 rows affected (0.01 sec)
MySQL> INSERT INTO t5(b) VALUES(5);
Query OK, 1 row affected (0.00 sec)
MySQL> set sql_mode="";
Query OK, 0 rows affected (0.00 sec)
MySQL> INSERT INTO t5(b) VALUES(default);
Query OK, 1 row affected (0.00 sec)
MySQL> select *from t5;
+---+
| b |
+---+
| 5 |
| 6 |
+---+
2 rows in set (0.00 sec)
2.TIMESTAMP变量explicit_defaults_for_timestamp
对于TIMESTAMP以外的日期和时间类型,默认值是该类型的适当“零”值。如果启用explicit_defaults_for_timestamp系统变量,默认值是当前日期和时间。
CREATE TABLE t6 (
-> t TIME NOT NULL,
-> ts TIMESTAMP NOT NULL);
Query OK, 0 rows affected (0.01 sec)
#explicit_defaults_for_timestamp默认开启
MySQL> SHOW VARIABLES LIKE '%explicit_defaults_for_timestamp%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| explicit_defaults_for_timestamp | ON |
+---------------------------------+-------+
1 row in set (0.00 sec)
MySQL> INSERT INTO t6(t,ts) VALUES(NOW(),NULL);
ERROR 1048 (23000): Column 'ts' cannot be null
#explicit_defaults_for_timestamp关闭
MySQL> SET explicit_defaults_for_timestamp=OFF;
Query OK, 0 rows affected, 1 warning (0.00 sec)
MySQL> SHOW VARIABLES LIKE '%explicit_defaults_for_timestamp%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| explicit_defaults_for_timestamp | OFF |
+---------------------------------+-------+
1 row in set (0.00 sec)
MySQL> INSERT INTO t6(t,ts) VALUES(NOW(),NULL);
Query OK, 1 row affected (0.00 sec)
MySQL> SELECT * FROM t6;
+----------+---------------------+
| t | ts |
+----------+---------------------+
| 10:36:13 | 2022-07-05 10:36:13 |
+----------+---------------------+
1 row in set (0.00 sec)
总结
设计字段的时候,默认值能便利解决一些初始化数据问题,但默认值也需要使用注意。
- 非空字段设置默认值可以预防插入报错。
- 默认值同样可设置在可为 null 字段。
- sql_mode严谨模式 影响默认值的选择
- timestamp 类型不同参数下影响默认值
- CREATE TABLE … LIKE and CREATE TABLE … SELECT保留原有默认值