暂无图片
暂无图片
1
暂无图片
暂无图片
1
暂无图片

[ACDU 翻译] MySQL 11.6 数据类型默认值

原创 由迪 2022-01-14
347

数据类型规范可以具有显式或隐式默认值。

数据类型规范中的 子句明确指示列的默认值。例子: 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取决于版本,如下所述。

MySQL 8.0.13 的显式默认处理

子句中指定的默认值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()) );
复制

例外是,对于 TIMESTAMPDATETIME列,您可以将CURRENT_TIMESTAMP函数指定为默认值,而不用括起来。请参阅 第 11.2.5 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新”

仅当将值写为表达式时,才能为BLOBTEXTGEOMETRYJSON数据类型分配默认值,即使表达式值是文字:

  • 这是允许的(字面默认值指定为表达式):

    CREATE TABLE t2 (b BLOB DEFAULT ('abc'));
    复制
  • 这会产生一个错误(字面默认值未指定为表达式):

    CREATE TABLE t2 (b BLOB DEFAULT 'abc');
    复制

表达式默认值必须遵守以下规则。如果表达式包含不允许的构造,则会发生错误。

  • 允许使用文字、内置函数(确定性和非确定性)和运算符。

  • 不允许使用子查询、参数、变量、存储函数和可加载函数。

  • 表达式默认值不能依赖于具有该AUTO_INCREMENT属性的列。

  • 一个列的表达式默认值可以引用其他表列,但对生成的列或具有表达式默认值的列的引用必须是表定义中较早出现的列。也就是说,表达式默认值不能包含对生成的列或具有表达式默认值的列的前向引用。

    排序约束也适用于 ALTER TABLE重新排序表列的使用。如果结果表的表达式默认值包含对生成的列或具有表达式默认值的列的前向引用,则语句将失败。

笔记

如果表达式默认值的任何组成部分依赖于 SQL 模式,则表的不同用途可能会出现不同的结果,除非在所有使用过程中 SQL 模式都相同。

对于CREATE TABLE ... LIKECREATE TABLE ... SELECT,目标表保留原始表中的表达式默认值。

如果表达式默认值引用非确定性函数,则导致计算表达式的任何语句对于基于语句的复制都是不安全的。这包括诸如 INSERT和 之类的语句UPDATE。在这种情况下,如果禁用二进制日志记录,则该语句将正常执行。如果启用二进制日志记录并 binlog_format设置为 STATEMENT,则记录并执行该语句,但会在错误日志中写入一条警告消息,因为复制从属服务器可能会出现分歧。当 binlog_format设置为 MIXEDorROW时,语句正常执行。

插入新行时,可以通过省略列名或将列指定为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 类型转换规则对声明的类型进行隐式强制。请参阅 第 12.3 节,“表达式求值中的类型转换”

MySQL 8.0.13 之前的显式默认处理

除了一个例外, DEFAULT子句中指定的默认值必须是字面常量;它不能是函数或表达式。这意味着,例如,您不能将日期列的默认值设置为函数的值,例如NOW() or CURRENT_DATE。例外是,对于TIMESTAMPDATETIME列,您可以指定 CURRENT_TIMESTAMP为默认值。请参阅第 11.2.5 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新”

BLOBTEXT和 数据类型不能分配默认值 GEOMETRYJSON

如果默认值计算的数据类型与声明的列类型不同,则根据通常的 MySQL 类型转换规则对声明的类型进行隐式强制。请参阅 第 12.3 节,“表达式求值中的类型转换”

隐式默认处理

如果数据类型规范不包含显式 DEFAULT值,MySQL 将按如下方式确定默认值:

如果列可以NULL作为值,则使用显式DEFAULT NULL子句定义该列。

如果该列不能NULL作为一个值,MySQL 定义没有显式 DEFAULT子句的列。

NOT NULL对于没有显式DEFAULT子句 的列的数据输入,如果INSERTor 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));
复制

请参阅第 5.1.11 节,“服务器 SQL 模式”

对于给定的表,该SHOW CREATE TABLE语句显示哪些列具有显式DEFAULT子句。

隐式默认值定义如下:

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

墨天轮福利君
暂无图片
3年前
评论
暂无图片 0
您好,您的文章已入选合格奖,10墨值奖励已经到账请查收! ❤️我们还会实时派发您的流量收益。
3年前
暂无图片 点赞
评论
目录
  • MySQL 8.0.13 的显式默认处理
  • MySQL 8.0.13 之前的显式默认处理
  • 隐式默认处理