13.6 数据类型默认值
数据类型指定可以有明确或隐式的默认值。
在数据类型指定中,DEFAULT
子句明确地指示了一个列的默认值。例如:value
CREATE TABLE t1 (
i INT DEFAULT -1,
c VARCHAR(10) DEFAULT '',
price DOUBLE(16,2) DEFAULT 0.00
);
SERIAL DEFAULT VALUE
是一种特殊情况。在整数列的定义中,它是 NOT NULL AUTO_INCREMENT UNIQUE
的别名。
一些明确DEFAULT
子句处理方面是版本相关的,以下描述了这些方面。
在 DEFAULT
子句中指定的默认值可以是一个字面常量或一个表达式。除了一个例外,需要将表达式默认值括在圆括号内以区分它们与字面常量默认值。例如:
CREATE TABLE t1 (
-- literal defaults
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
函数作为默认值,without enclosing parentheses。见第13.2.5节,“TIMESTAMP和DATETIME的自动初始化和更新”。
BLOB
、TEXT
、GEOMETRY
和JSON
数据类型只能在将值写作表达式时指定默认值,即使该表达式值是字面量:
-
这是允许的(字面量默认指定为表达式):
CREATE TABLE t2 (b BLOB DEFAULT ('abc'));
-
这产生错误(字面量默认不指定为表达式):
CREATE TABLE t2 (b BLOB DEFAULT 'abc');
expression默认值必须遵守以下规则。如果一个表达式包含禁止的构造,会出现错误。
-
字面量、内置函数(确定性和非确定性)和操作符是允许的。
-
子查询、参数、变量、存储函数和可加载函数不允许。
-
expression默认值不能依赖具有
AUTO_INCREMENT
属性的列。 -
一个表列的表达式默认值可以引用其他表列,除了对生成列或具有表达式默认值的列之外,该引用只能是该表定义中的早于当前列的列。也就是说,表达式默认值不能包含对生成列或具有表达式默认值的列的前向引用。
ALTER TABLE
语句也遵守同样的顺序约束。如果结果表中包含对生成列或具有表达式默认值的列的前向引用,语句将失败。
如果一个表达式默认值的某个组件依赖于 SQL 模式,那么在不同的使用场景下可能会出现不同结果,除非在所有使用场景中都保持相同的 SQL 模式。
CREATE TABLE ... LIKE
和 CREATE TABLE ... SELECT
,目标表将保留原始表的表达式默认值。
如果表达式默认值引用非确定性函数,任何导致表达式被评估的语句都不是安全的语句基于语句复制。包括像INSERT
和 UPDATE
等语句。在这种情况下,如果二进制日志禁用,语句将被执行为正常。如果启用二进制日志且binlog_format
设置为 STATEMENT
,语句将被记录和执行,但写入错误日志警告信息,因为副本可能会分歧。设置binlog_format
为 MIXED
或 ROW
,语句将被执行为正常。
当插入新行时,表达式默认值的列可以通过省略列名或指定列名为DEFAULT
(与字面值默认值相同)来插入:
mysql> CREATE TABLE t4 (uid BINARY(16) DEFAULT (UUID_TO_BIN(UUID())));
mysql> INSERT INTO t4 () VALUES();
mysql> INSERT INTO t4 () VALUES(DEFAULT);
mysql> SELECT BIN_TO_UUID(uid) AS uid FROM t4;
+--------------------------------------+
| uid |
+--------------------------------------+
| f1109174-94c9-11e8-971d-3bf1095aa633 |
| f110cf9a-94c9-11e8-971d-3bf1095aa633 |
+--------------------------------------+
然而,使用DEFAULT(
指定命名列的默认值,只允许在有字面值默认值的列上,不允许在表达式默认值的列上。col_name
)
不所有存储引擎都允许表达式默认值。对于不允许的,一个ER_UNSUPPORTED_ACTION_ON_DEFAULT_VAL_GENERATED
错误发生。
如果默认值计算结果与声明的列类型不同,MySQL根据通常的 MySQL 类型转换规则隐式将其转换为声明的类型。见第14.3节,“表达式求值中的类型转换”。
如果数据类型指定不包含明确的DEFAULT
值,MySQL按以下方式确定默认值:
如果列可以取NULL
值,则将列定义为明确的DEFAULT NULL
子句。
如果列不能取NULL
值,MySQL将列定义为无明确的DEFAULT
子句。
对于无明确DEFAULT
子句的NOT NULL
列,如果INSERT
或REPLACE
语句不包含该列值,或者UPDATE
语句将该列设置为NULL
,MySQL根据生效的 SQL 模式处理该列:
-
如果严格 SQL 模式启用,事务表中发生错误,语句回滚;非事务表中发生错误,但如果是多行语句的第二行或后续行,则前面的行被插入。
-
如果不启用严格模式,MySQL 将该列设置为该列数据类型的隐式默认值。
假设表 t
定义如下:
CREATE TABLE t (i INT NOT NULL);
在严格模式下,每个以下语句都产生错误,不插入任何行;不使用严格模式时,只有第三个语句产生错误,前两个语句隐式默认值被插入,但第三个失败,因为 DEFAULT(i)
无法生成值:
INSERT INTO t VALUES();
INSERT INTO t VALUES(DEFAULT);
INSERT INTO t VALUES(DEFAULT(i));
对于给定的表,SHOW CREATE TABLE
语句显示哪些列具有明确的 DEFAULT
子句。
隐式默认值定义如下:
-
对于数字类型,默认值为
0
,除非是使用了AUTO_INCREMENT
属性的整数或浮点类型,那么默认值是序列中的下一个值。 -
对于除
TIMESTAMP
之外的日期和时间类型,默认值是该类型对应的“零”值。对于TIMESTAMP
,如果启用了explicit_defaults_for_timestamp
系统变量(见第7.1.8节,“服务器系统变量”),则同样是“零”值。否则,对于表中的第一个TIMESTAMP
列,默认值是当前日期和时间。见第13.2节,“日期和时间数据类型”。