# 11.6 数据类型默认值
数据类型规范可以具有显式或隐式默认值。
一种默认 *
价值*
数据类型规范中的子句明确指示列的默认值。例子:
CREATE TABLE t1 (
i INT DEFAULT -1,
c VARCHAR(10) DEFAULT '',
price DOUBLE(16,2) DEFAULT 0.00
);
序列默认值
是一个特例。在整数列的定义中,它是NOT NULL AUTO_INCREMENT UNIQUE
.
显式的一些方面默认
子句处理取决于版本,如下所述。
# MySQL 8.0.13 的显式默认处理
中指定的默认值默认
子句可以是文字常量或表达式。除了一个例外,将表达式默认值括在括号中以将它们与文字常量默认值区分开来。例子:
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())
);
例外是,对于时间戳
和约会时间
列,您可以指定CURRENT_TIMESTAMP
函数作为默认值,不带括号。看第 11.2.5 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新”.
这斑点
,文本
,几何学
, 和JSON
仅当将值写为表达式时,才能为数据类型分配默认值,即使表达式值是文字:
这是允许的(字面默认值指定为表达式):
CREATE TABLE t2 (b BLOB DEFAULT ('abc'));
这会产生一个错误(字面默认值未指定为表达式):
CREATE TABLE t2 (b BLOB DEFAULT 'abc');
表达式默认值必须遵守以下规则。如果表达式包含不允许的构造,则会发生错误。
允许使用文字、内置函数(确定性和非确定性)和运算符。
不允许使用子查询、参数、变量、存储函数和可加载函数。
表达式默认值不能依赖于具有
自动递增
属性。一个列的表达式默认值可以引用其他表列,但对生成的列或具有表达式默认值的列的引用必须是表定义中较早出现的列。也就是说,表达式默认值不能包含对生成的列或具有表达式默认值的列的前向引用。
排序约束也适用于
更改表
重新排序表列。如果结果表的表达式默认值包含对生成的列或具有表达式默认值的列的前向引用,则语句将失败。
笔记
如果表达式默认值的任何组成部分依赖于 SQL 模式,则表的不同用途可能会出现不同的结果,除非在所有使用过程中 SQL 模式都相同。
为了创建表...喜欢
和创建表...选择
,目标表保留原始表中的表达式默认值。
如果表达式默认值引用非确定性函数,则导致计算表达式的任何语句对于基于语句的复制都是不安全的。这包括诸如插入
和更新
.在这种情况下,如果禁用二进制日志记录,则该语句将正常执行。如果启用了二进制日志记录并且binlog_format
被设定为陈述
,该语句被记录并执行,但一条警告消息被写入错误日志,因为复制从属服务器可能会分歧。什么时候binlog_format
被设定为混合
要么排
,语句正常执行。
插入新行时,可以通过省略列名或将列指定为默认
(就像具有文字默认值的列一样):
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 |
+--------------------------------------+
然而,使用默认(*
col_name*)
为命名列指定默认值仅允许用于具有文字默认值的列,而不是用于具有表达式默认值的列。
并非所有存储引擎都允许表达式默认值。对于那些不这样做的人,一个ER_UNSUPPORTED_ACTION_ON_DEFAULT_VAL_GENERATED
(opens new window)发生错误。
如果默认值评估为不同于声明的列类型的数据类型,则根据通常的 MySQL 类型转换规则对声明的类型进行隐式强制。看第 12.3 节,“表达式求值中的类型转换”.
# MySQL 8.0.13 之前的显式默认处理
除了一个例外,在一个指定的默认值默认
子句必须是字面常量;它不能是函数或表达式。这意味着,例如,您不能将日期列的默认值设置为函数的值,例如现在()
要么当前的日期
.例外是,对于时间戳
和约会时间
列,您可以指定CURRENT_TIMESTAMP
作为默认值。看第 11.2.5 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新”.
这斑点
,文本
,几何学
, 和JSON
不能为数据类型分配默认值。
如果默认值评估为不同于声明的列类型的数据类型,则根据通常的 MySQL 类型转换规则对声明的类型进行隐式强制。看第 12.3 节,“表达式求值中的类型转换”.
# 隐式默认处理
如果数据类型规范不包含显式默认
值,MySQL确定默认值如下:
如果该列可以采取空值
作为一个值,该列是用显式定义的默认空
条款。
如果列不能取空值
作为一个值,MySQL 定义没有显式的列默认
条款。
对于数据输入非空
没有明确的列默认
子句,如果一个插入
要么代替
语句不包含列的值,或者更新
语句将列设置为空值
,MySQL按照当时生效的SQL模式处理列:
如果启用了严格的 SQL 模式,则事务表会发生错误并回滚语句。对于非事务性表,会发生错误,但如果多行语句的第二行或后续行发生这种情况,则会插入前面的行。
如果未启用严格模式,MySQL 会将列设置为列数据类型的隐式默认值。
假设一个表
吨
定义如下:
CREATE TABLE t (i INT NOT NULL);
在这种情况下,一世
没有明确的默认值,因此在严格模式下,以下每个语句都会产生错误并且不会插入任何行。不使用严格模式时,只有第三条语句产生错误;前两个语句插入了隐式默认值,但第三个语句失败,因为默认(i)
不能产生值:
INSERT INTO t VALUES();
INSERT INTO t VALUES(DEFAULT);
INSERT INTO t VALUES(DEFAULT(i));
对于给定的表,显示创建表
语句显示哪些列具有显式默认
条款。
隐式默认值定义如下:
对于数字类型,默认为
0
,但对于使用声明的整数或浮点类型除外自动递增
属性,默认是序列中的下一个值。对于日期和时间类型以外的
时间戳
,默认值是该类型的适当“零”值。这也适用于时间戳
如果显式默认值for_timestamp
系统变量已启用(请参阅第 5.1.8 节,“服务器系统变量”)。否则,对于第一个时间戳
表中的列,默认值为当前日期和时间。看第 11.2 节,“日期和时间数据类型”.