数据类型默认值
数据类型规范可以具有显式或隐式默认值。
在数据类型规范子句显式地指示为列的默认值。例子:DEFAULT value
CREATE TABLE t1 ( i INTDEFAULT -1, c VARCHAR(10)DEFAULT '', price DOUBLE(16,2)DEFAULT 0.00 );
SERIAL DEFAULT VALUE
是一个特例。在整数列的定义中,它是的别名NOT NULL AUTO_INCREMENT UNIQUE
。
显式DEFAULT
子句处理的某些方面取决于版本,如下所述。
- 从MySQL 8.0.13开始的显式默认值的处理
- MySQL 8.0.13之前的显式默认值的处理
- 隐式违约的处理
从MySQL 8.0.13开始的显式默认值的处理
DEFAULT
子句中指定的默认值可以是文字常量或表达式。除一个例外,将表达式默认值放在括号内,以将其与文字常量默认值区分开。例子:
CREATE TABLE t1 ( -- literal defaults i INTDEFAULT 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), pPOINT DEFAULT (Point(0,0)), j JSON DEFAULT (JSON_ARRAY()) );
唯一的例外是,对于TIMESTAMP
和DATETIME
列,您可以将CURRENT_TIMESTAMP
函数指定为默认函数,而不用括号括起来。请参见“ TIMESTAMP和DATETIME的自动初始化和更新”。
BLOB
,TEXT
,GEOMETRY
,和JSON
数据类型可分配仅当值被写入作为表达,即使表情值是一个文字一个缺省值:
这是允许的(将文字默认值指定为表达式):
CREATE TABLE t2 (b BLOB DEFAULT ('abc'));这会产生错误(字面默认值未指定为表达式):
CREATE TABLE t2 (b BLOBDEFAULT 'abc');
表达式默认值必须遵守以下规则。如果表达式包含不允许的构造,则会发生错误。
- 允许使用文字,内置函数(确定性和非确定性)以及运算符。
- 不允许使用子查询,参数,变量,存储的函数和用户定义的函数。
- 表达式默认值不能依赖于具有
AUTO_INCREMENT
属性的列。 一列的表达式默认值可以引用其他表列,但对生成的列或具有表达式默认值的列的引用必须引用表定义中较早出现的列。也就是说,表达式默认值不能包含对生成的列或具有表达式默认值的列的前向引用。
排序约束也适用于对
ALTER TABLE
表列进行重新排序的用法。如果结果表的表达式默认值包含对生成的列或具有表达式默认值的列的前向引用,则该语句将失败。
注意如果表达式默认值的任何组成部分取决于SQL模式,则表的不同用法可能会产生不同的结果,除非在所有用法中SQL模式都相同。
对于CREATE TABLE ... LIKE
和CREATE TABLE ... SELECT
,目标表保留原始表中的表达式默认值。
如果表达式默认值引用的是不确定函数,则任何导致对该表达式求值的语句对于基于语句的复制都是不安全的。这包括语句,如INSERT
,UPDATE
和ALTER TABLE
。在这种情况下,如果禁用了二进制日志记录,则将正常执行该语句。如果启用了二进制日志记录并将binlog_format
其设置为STATEMENT
,则将记录并执行该语句,但是将警告消息写入错误日志,因为复制从站可能会发散。当binlog_format
设置为MIXED
或时ROW
,不执行该语句,并且将错误消息写入错误日志。
插入新行时,可以通过省略列名或将列指定为来插入表达式为default的列的默认值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 uidFROM t4; +-------------------------------------- + | uid | +-------------------------------------- + | f1109174 -94c9 -11e8 -971d -3bf1095aa633 | | f110cf9a -94c9 -11e8 -971d -3bf1095aa633 | +-------------------------------------- +
但是,仅允许使用具有文字默认值的列,而不能使用具有表达式默认值的列为指定的列指定默认值。DEFAULT(col_name)
并非所有存储引擎都允许表达式默认值。否则,将ER_UNSUPPORTED_ACTION_ON_DEFAULT_VAL_GENERATED
发生错误。
如果默认值计算出的数据类型与声明的列类型不同,则根据通常的MySQL类型转换规则,对声明的类型进行隐式强制转换。请参见“表达式评估中的类型转换”。
MySQL 8.0.13之前的显式默认值的处理
除了一个例外,DEFAULT
子句中指定的默认值必须是文字常量;它不能是函数或表达式。例如,这意味着您不能将日期列的默认值设置为诸如NOW()
或函数的值CURRENT_DATE
。唯一的例外是,对于TIMESTAMP
和DATETIME
列,您可以将其指定CURRENT_TIMESTAMP
为默认值。请参见“ TIMESTAMP和DATETIME的自动初始化和更新”。
在BLOB
,TEXT
,GEOMETRY
,和JSON
数据类型不能指定一个默认值。
如果默认值计算出的数据类型与声明的列类型不同,则根据通常的MySQL类型转换规则,对声明的类型进行隐式强制转换。请参见“表达式评估中的类型转换”。
隐式违约的处理
如果数据类型规范不包含任何显式DEFAULT
值,则MySQL将按以下方式确定默认值:
如果该列可以NULL
作为值,则使用显式DEFAULT NULL
子句定义该列。
如果该列不能NULL
作为值,则MySQL定义没有显式DEFAULT
子句的列。例外:如果将该列定义为的一部分,PRIMARY KEY
但未明确定义为NOT NULL
,则MySQL将其创建为一NOT NULL
列(因为PRIMARY KEY
column必须为NOT NULL
)。
对于将数据输入到NOT NULL
没有显式DEFAULT
子句的列中,如果INSERT
or REPLACE
语句不包含该列的值,或者一条UPDATE
语句将该列设置为NULL
,则MySQL根据当时有效的SQL模式处理该列:
- 如果启用了严格的SQL模式,则事务表将发生错误,并且该语句将回滚。对于非事务处理表,会发生错误,但是如果此错误发生在多行语句的第二行或后续行中,则会插入前面的行。
- 如果未启用严格模式,则MySQL将列设置为列数据类型的隐式默认值。
假设表t
定义如下:
CREATE TABLE t (i INT NOT NULL);
在这种情况下,i
没有明确的默认值,因此在严格模式下,以下每个语句都会产生错误,并且不会插入任何行。当不使用严格模式时,只有第三条语句会产生错误。为前两个语句插入了隐式默认值,但是第三个语句失败,因为DEFAULT(i)
无法产生值:
INSERT INTO tVALUES ();INSERT INTO tVALUES (DEFAULT );INSERT INTO tVALUES (DEFAULT(i));
请参见“服务器SQL模式”。
对于给定的表,该SHOW CREATE TABLE
语句显示哪些列具有显式DEFAULT
子句。
隐式默认值定义如下:
- 对于数字类型,默认值为
0
,但对于使用AUTO_INCREMENT
属性声明的整数或浮点类型,默认值为序列中的下一个值。 - 对于除以外的日期和时间类型
TIMESTAMP
,默认值为该类型的相应“零”值。TIMESTAMP
如果explicit_defaults_for_timestamp
启用了系统变量,也是如此(请参见“服务器系统变量”)。否则,对于TIMESTAMP
表中的第一列,默认值为当前日期和时间。请参见“日期和时间数据类型”。 - 对于除以外
ENUM
的其他字符串类型,默认值为空字符串。对于ENUM
,默认值为第一个枚举值。