数据类型规范可以具有显式或隐式默认值。
数据类型规范中的 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
函数作为默认值,无需括号。 参见 第 13.2.5 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新”。
BLOB
、TEXT
、GEOMETRY
和 JSON
数据类型只能在值写成表达式的情况下才能分配默认值,即使表达式值为文字也是如此
这是允许的(文字默认值指定为表达式)
CREATE TABLE t2 (b BLOB DEFAULT ('abc'));
这会产生错误(文字默认值未指定为表达式)
CREATE TABLE t2 (b BLOB DEFAULT 'abc');
表达式默认值必须遵循以下规则。 如果表达式包含不允许的构造,则会发生错误。
允许使用文字、内置函数(确定性和非确定性函数)和运算符。
不允许使用子查询、参数、变量、存储函数和可加载函数。
表达式默认值不能依赖于具有
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 类型转换规则进行到声明类型的隐式强制转换。 参见 第 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);
在这种情况下,i
没有显式默认值,因此在严格模式下,以下每个语句都会产生错误,并且不会插入任何行。 不使用严格模式时,只有第三个语句会产生错误; 前两个语句插入了隐式默认值,但第三个语句失败,因为 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
之外的日期和时间类型,默认值为该类型的相应 “零” 值。如果启用了explicit_defaults_for_timestamp
系统变量(请参阅 第 7.1.8 节“服务器系统变量”),那么TIMESTAMP
也是如此。否则,对于表中的第一个TIMESTAMP
列,默认值为当前日期和时间。请参阅 第 13.2 节“日期和时间数据类型”。