data-type-defaults.md 8.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
## 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 的显式默认处理](data-type-defaults.html#data-type-defaults-explicit)

-   [MySQL 8.0.13 之前的显式默认处理](data-type-defaults.html#data-type-defaults-explicit-old)

-   [隐式默认处理](data-type-defaults.html#data-type-defaults-implicit)

### 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())
);
```

例外是,对于[`时间戳`](datetime.html)[`约会时间`](datetime.html)列,您可以指定[`CURRENT_TIMESTAMP`](date-and-time-functions.html#function_current-timestamp)函数作为默认值,不带括号。看[第 11.2.5 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新”](timestamp-initialization.html).

[`斑点`](blob.html),[`文本`](blob.html),`几何学`, 和[`JSON`](json.html)仅当将值写为表达式时,才能为数据类型分配默认值,即使表达式值是文字:

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

    ```
    CREATE TABLE t2 (b BLOB DEFAULT ('abc'));
    ```

-   这会产生一个错误(字面默认值未指定为表达式):

    ```
    CREATE TABLE t2 (b BLOB DEFAULT 'abc');
    ```

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

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

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

-   表达式默认值不能依赖于具有`自动递增`属性。

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

    排序约束也适用于[`更改表`](alter-table.html)重新排序表列。如果结果表的表达式默认值包含对生成的列或具有表达式默认值的列的前向引用,则语句将失败。

笔记

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

为了[`创建表...喜欢`](create-table-like.html)[`创建表...选择`](create-table-select.html),目标表保留原始表中的表达式默认值。

如果表达式默认值引用非确定性函数,则导致计算表达式的任何语句对于基于语句的复制都是不安全的。这包括诸如[`插入`](insert.html)[`更新`](update.html).在这种情况下,如果禁用二进制日志记录,则该语句将正常执行。如果启用了二进制日志记录并且[`binlog_format`](replication-options-binary-log.html#sysvar_binlog_format)被设定为`陈述`,该语句被记录并执行,但一条警告消息被写入错误日志,因为复制从属服务器可能会分歧。什么时候[`binlog_format`](replication-options-binary-log.html#sysvar_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`*)`](miscellaneous-functions.html#function_default)为命名列指定默认值仅允许用于具有文字默认值的列,而不是用于具有表达式默认值的列。

并非所有存储引擎都允许表达式默认值。对于那些不这样做的人,一个[`ER_UNSUPPORTED_ACTION_ON_DEFAULT_VAL_GENERATED`](https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_unsupported_action_on_default_val_generated)发生错误。

如果默认值评估为不同于声明的列类型的数据类型,则根据通常的 MySQL 类型转换规则对声明的类型进行隐式强制。看[第 12.3 节,“表达式求值中的类型转换”](type-conversion.html).

### MySQL 8.0.13 之前的显式默认处理

除了一个例外,在一个指定的默认值`默认`子句必须是字面常量;它不能是函数或表达式。这意味着,例如,您不能将日期列的默认值设置为函数的值,例如[`现在()`](date-and-time-functions.html#function_now)要么[`当前的日期`](date-and-time-functions.html#function_current-date).例外是,对于[`时间戳`](datetime.html)[`约会时间`](datetime.html)列,您可以指定[`CURRENT_TIMESTAMP`](date-and-time-functions.html#function_current-timestamp)作为默认值。看[第 11.2.5 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新”](timestamp-initialization.html).

[`斑点`](blob.html),[`文本`](blob.html),`几何学`, 和[`JSON`](json.html)不能为数据类型分配默认值。

如果默认值评估为不同于声明的列类型的数据类型,则根据通常的 MySQL 类型转换规则对声明的类型进行隐式强制。看[第 12.3 节,“表达式求值中的类型转换”](type-conversion.html).

### 隐式默认处理

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

如果该列可以采取`空值`作为一个值,该列是用显式定义的`默认空`条款。

如果列不能取`空值`作为一个值,MySQL 定义没有显式的列`默认`条款。

对于数据输入`非空`没有明确的列`默认`子句,如果一个[`插入`](insert.html)要么[`代替`](replace.html)语句不包含列的值,或者[`更新`](update.html)语句将列设置为`空值`,MySQL按照当时生效的SQL模式处理列:

-   如果启用了严格的 SQL 模式,则事务表会发生错误并回滚语句。对于非事务性表,会发生错误,但如果多行语句的第二行或后续行发生这种情况,则会插入前面的行。

-   如果未启用严格模式,MySQL 会将列设置为列数据类型的隐式默认值。

    假设一个表`吨`定义如下:


```
CREATE TABLE t (i INT NOT NULL);
```

在这种情况下,`一世`没有明确的默认值,因此在严格模式下,以下每个语句都会产生错误并且不会插入任何行。不使用严格模式时,只有第三条语句产生错误;前两个语句插入了隐式默认值,但第三个语句失败,因为[`默认(i)`](miscellaneous-functions.html#function_default)不能产生值:

```
INSERT INTO t VALUES();
INSERT INTO t VALUES(DEFAULT);
INSERT INTO t VALUES(DEFAULT(i));
```

[第 5.1.11 节,“服务器 SQL 模式”](sql-mode.html).

对于给定的表,[`显示创建表`](show-create-table.html)语句显示哪些列具有显式`默认`条款。

隐式默认值定义如下:

-   对于数字类型,默认为`0`,但对于使用声明的整数或浮点类型除外`自动递增`属性,默认是序列中的下一个值。

-   对于日期和时间类型以外的[`时间戳`](datetime.html),默认值是该类型的适当“零”值。这也适用于[`时间戳`](datetime.html)如果[`显式默认值for_timestamp`](server-system-variables.html#sysvar_explicit_defaults_for_timestamp)系统变量已启用(请参阅[第 5.1.8 节,“服务器系统变量”](server-system-variables.html))。否则,对于第一个[`时间戳`](datetime.html)表中的列,默认值为当前日期和时间。看[第 11.2 节,“日期和时间数据类型”](date-and-time-types.html).

-   对于字符串类型以外的[`枚举`](enum.html),默认值为空字符串。为了[`枚举`](enum.html),默认为第一个枚举值。