MySQL8 中文参考(四十六)
13.4.11 使用空间索引
原文:
dev.mysql.com/doc/refman/8.0/en/using-spatial-indexes.html
优化器会检查是否可以利用可用的空间索引来搜索使用WHERE子句中的函数如MBRContains()或MBRWithin()的查询。以下查询找到所有在给定矩形内的对象:
mysql> SET @poly =
-> 'Polygon((30000 15000,
31000 15000,
31000 16000,
30000 16000,
30000 15000))';
mysql> SELECT fid,ST_AsText(g) FROM geom WHERE
-> MBRContains(ST_GeomFromText(@poly),g);
+-----+---------------------------------------------------------------+
| fid | ST_AsText(g) |
+-----+---------------------------------------------------------------+
| 21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30 ... |
| 22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8, ... |
| 23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4, ... |
| 24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4, ... |
| 25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882\. ... |
| 26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4, ... |
| 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946\. ... |
| 1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136\. ... |
| 2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136, ... |
| 3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,3016 ... |
| 4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30 ... |
| 5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4, ... |
| 6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,3024 ... |
| 7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8, ... |
| 10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6, ... |
| 11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2, ... |
| 13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,3011 ... |
| 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30 ... |
| 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30 ... |
| 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4, ... |
+-----+---------------------------------------------------------------+
20 rows in set (0.00 sec)
使用EXPLAIN来检查这个查询的执行方式:
mysql> SET @poly =
-> 'Polygon((30000 15000,
31000 15000,
31000 16000,
30000 16000,
30000 15000))';
mysql> EXPLAIN SELECT fid,ST_AsText(g) FROM geom WHERE
-> MBRContains(ST_GeomFromText(@poly),g)\G
*************************** 1\. row ***************************
id: 1
select_type: SIMPLE
table: geom
type: range
possible_keys: g
key: g
key_len: 32
ref: NULL
rows: 50
Extra: Using where 1 row in set (0.00 sec)
检查没有空间索引会发生什么:
mysql> SET @poly =
-> 'Polygon((30000 15000,
31000 15000,
31000 16000,
30000 16000,
30000 15000))';
mysql> EXPLAIN SELECT fid,ST_AsText(g) FROM g IGNORE INDEX (g) WHERE
-> MBRContains(ST_GeomFromText(@poly),g)\G
*************************** 1\. row ***************************
id: 1
select_type: SIMPLE
table: geom
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 32376
Extra: Using where 1 row in set (0.00 sec)
在没有空间索引的情况下执行SELECT语句会得到相同的结果,但执行时间从 0.00 秒上升到 0.46 秒:
mysql> SET @poly =
-> 'Polygon((30000 15000,
31000 15000,
31000 16000,
30000 16000,
30000 15000))';
mysql> SELECT fid,ST_AsText(g) FROM geom IGNORE INDEX (g) WHERE
-> MBRContains(ST_GeomFromText(@poly),g);
+-----+---------------------------------------------------------------+
| fid | ST_AsText(g) |
+-----+---------------------------------------------------------------+
| 1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136\. ... |
| 2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136, ... |
| 3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,3016 ... |
| 4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30 ... |
| 5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4, ... |
| 6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,3024 ... |
| 7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8, ... |
| 10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6, ... |
| 11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2, ... |
| 13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,3011 ... |
| 21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30 ... |
| 22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8, ... |
| 23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4, ... |
| 24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4, ... |
| 25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882\. ... |
| 26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4, ... |
| 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30 ... |
| 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30 ... |
| 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4, ... |
| 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946\. ... |
+-----+---------------------------------------------------------------+
20 rows in set (0.46 sec)
13.5 JSON 数据类型
-
创建 JSON 值
-
JSON 值的规范化、合并和自动包装
-
搜索和修改 JSON 值
-
JSON 路径语法
-
JSON 值的比较和排序
-
JSON 和非 JSON 值之间的转换
-
JSON 值的聚合
MySQL 支持由RFC 7159定义的本机JSON数据类型,可实现对 JSON(JavaScript 对象表示)文档中数据的高效访问。JSON数据类型相对于在字符串列中存储 JSON 格式字符串具有以下优势:
-
存储在
JSON列中的 JSON 文档的自动验证。无效文档会产生错误。 -
优化的存储格式。存储在
JSON列中的 JSON 文档会转换为内部格式,以便快速读取文档元素。当服务器后续必须从此二进制格式中读取存储的 JSON 值时,无需从文本表示中解析值。二进制格式被设计为使服务器能够直接通过键或数组索引查找子对象或嵌套值,而无需在文档中读取它们之前或之后的所有值。
MySQL 8.0 还支持RFC 7396中定义的JSON 合并补丁格式,使用JSON_MERGE_PATCH()函数。请参阅此函数的描述,以及 JSON 值的规范化、合并和自动包装,获取示例和更多信息。
注意
本讨论中使用单调字体的JSON表示特定的 JSON 数据类型,JSON使用常规字体表示一般的 JSON 数据。
存储 JSON 文档所需的空间大致与 LONGBLOB 或 LONGTEXT 相同;有关更多信息,请参见 第 13.7 节,“数据类型存储要求”。重要的是要记住,存储在 JSON 列中的任何 JSON 文档的大小受限于 max_allowed_packet 系统变量的值。(当服务器在内存中内部操作 JSON 值时,它可以比这个值更大;限制适用于服务器存储它时。)您可以使用 JSON_STORAGE_SIZE() 函数获取存储 JSON 文档所需空间的量;请注意,对于 JSON 列,存储大小——因此此函数返回的值——是在对其执行的任何部分更新之前使用的列的大小(请参见本节后面关于 JSON 部分更新优化的讨论)。
在 MySQL 8.0.13 之前,JSON 列不能有非NULL默认值。
除了 JSON 数据类型外,还提供了一组 SQL 函数,用于对 JSON 值进行操作,如创建、操作和搜索。以下讨论展示了这些操作的示例。有关各个函数的详细信息,请参见 第 14.17 节,“JSON 函数”。
还提供了一组用于操作 GeoJSON 值的空间函数。请参见 第 14.16.11 节,“空间 GeoJSON 函数”。
JSON 列,就像其他二进制类型的列一样,不能直接索引;相反,您可以在生成的列上创建索引,从 JSON 列中提取标量值。有关详细示例,请参见 在生成的列上创建索引以提供 JSON 列索引。
MySQL 优化器还会查找与匹配 JSON 表达式的虚拟列上的兼容索引。
在 MySQL 8.0.17 及更高版本中,InnoDB 存储引擎支持对 JSON 数组进行多值索引。请参见 多值索引。
MySQL NDB Cluster 8.0 支持 JSON 列和 MySQL JSON 函数,包括在从 JSON 列生成的列上创建索引,作为无法对 JSON 列进行索引的解决方法。每个 NDB 表支持最多 3 个 JSON 列。
JSON 值的部分更新
在 MySQL 8.0 中,优化器可以对JSON列执行部分、原地更新,而不是删除旧文档并将新文档完全写入列。此优化可用于满足以下条件的更新:
-
正在更新的列被声明为
JSON。 -
UPDATE语句使用三个函数中的任何一个JSON_SET(),JSON_REPLACE(), 或JSON_REMOVE()来更新列。不能像直接赋值列值(例如,UPDATE mytable SET jcol = '{"a": 10, "b": 25}')这样进行部分更新。在单个
UPDATE语句中更新多个JSON列可以通过这种方式进行优化;MySQL 可以仅对使用刚才列出的三个函数更新值的列进行部分更新。 -
输入列和目标列必须是同一列;不能像
UPDATE mytable SET jcol1 = JSON_SET(jcol2, '$.a', 100)这样进行部分更新。更新可以使用前一项中列出的任何函数的嵌套调用,以任何组合,只要输入和目标列是相同的。
-
所有更改都用新值替换现有数组或对象值,并且不向父对象或数组添加任何新元素。
-
被替换的值必须至少和替换值一样大。换句话说,新值不能比旧值更大。
当之前的部分更新留下足够空间容纳更大值时,可能会有一个例外。您可以使用函数
JSON_STORAGE_FREE()查看通过对JSON列进行任何部分更新而释放了多少空间。
可以使用紧凑格式将这种部分更新写入二进制日志,以节省空间;可以通过将binlog_row_value_options系统变量设置为PARTIAL_JSON来启用此功能。
重要的是要区分表中存储的JSON列值的部分更新与将行的部分更新写入二进制日志。当前面列表中的最后两个条件中的任一条件(或两者)不满足但其他条件满足时,可以将JSON列的完整更新记录为部分更新。
参见binlog_row_value_options的描述。
接下来的几节提供有关创建和操作 JSON 值的基本信息。
创建 JSON 值
JSON 数组包含由逗号分隔并在[和]字符内包围的值列表:
["abc", 10, null, true, false]
JSON 对象包含一组由逗号分隔并在{和}字符内封装的键值对:
{"k1": "value", "k2": 10}
正如示例所示,JSON 数组和对象可以包含作为字符串或数字的标量值,JSON null 字面值,或 JSON 布尔 true 或 false 字面值。JSON 对象中的键必须是字符串。也允许使用时间(日期、时间或日期时间)标量值:
["12:18:29.000000", "2015-07-29", "2015-07-29 12:18:29.000000"]
JSON 数组元素和 JSON 对象键值内允许嵌套:
[99, {"id": "HK500", "cost": 75.99}, ["hot", "cold"]]
{"k1": "value", "k2": [10, 20]}
您还可以通过 MySQL 提供的许多用于此目的的函数(请参阅第 14.17.2 节,“创建 JSON 值的函数”)以及通过将其他类型的值转换为JSON类型使用CAST(*value* AS JSON)(请参阅在 JSON 和非 JSON 值之间转换)来获取 JSON 值。接下来的几段描述了 MySQL 如何处理提供的 JSON 值作为输入。
在 MySQL 中,JSON 值被写为字符串。MySQL 解析任何在需要 JSON 值的上下文中使用的字符串,并在其无效为 JSON 时产生错误。这些上下文包括将值插入具有JSON数据类型的列中以及将参数传递给期望 JSON 值的函数(通常在 MySQL JSON 函数文档中显示为*json_doc或json_val*),如以下示例所示:
-
尝试将值插入
JSON列成功,如果该值是有效的 JSON 值,则失败,如果不是则失败:mysql> CREATE TABLE t1 (jdoc JSON); Query OK, 0 rows affected (0.20 sec) mysql> INSERT INTO t1 VALUES('{"key1": "value1", "key2": "value2"}'); Query OK, 1 row affected (0.01 sec) mysql> INSERT INTO t1 VALUES('1, 2,'); ERROR 3140 (22032) at line 2: Invalid JSON text: "Invalid value." at position 6 in value (or column) '[1, 2,'.在这种错误消息中,“在位置*
N*处”表示基于 0 的位置,但应该被视为值中实际问题发生位置的粗略指示。 -
[
JSON_TYPE()函数期望一个 JSON 参数并尝试将其解析为 JSON 值。如果有效则返回该值的 JSON 类型,否则产生错误:mysql> SELECT JSON_TYPE('["a", "b", 1]'); +----------------------------+ | JSON_TYPE('["a", "b", 1]') | +----------------------------+ | ARRAY | +----------------------------+ mysql> SELECT JSON_TYPE('"hello"'); +----------------------+ | JSON_TYPE('"hello"') | +----------------------+ | STRING | +----------------------+ mysql> SELECT JSON_TYPE('hello'); ERROR 3146 (22032): Invalid data type for JSON data in argument 1 to function json_type; a JSON string or JSON type is required.
MySQL 处理在 JSON 上下文中使用的字符串时,使用utf8mb4字符集和utf8mb4_bin排序规则。其他字符集中的字符串会根据需要转换为utf8mb4。(对于ascii或utf8mb3字符集中的字符串,不需要转换,因为ascii和utf8mb3是utf8mb4的子集。)
作为使用文字字符串编写 JSON 值的替代方法,存在用于从组件元素组合 JSON 值的函数。JSON_ARRAY()接受一个(可能为空)值列表,并返回包含这些值的 JSON 数组:
mysql> SELECT JSON_ARRAY('a', 1, NOW());
+----------------------------------------+
| JSON_ARRAY('a', 1, NOW()) |
+----------------------------------------+
| ["a", 1, "2015-07-27 09:43:47.000000"] |
+----------------------------------------+
JSON_OBJECT()接受一个(可能为空)键值对列表,并返回包含这些对的 JSON 对象:
mysql> SELECT JSON_OBJECT('key1', 1, 'key2', 'abc');
+---------------------------------------+
| JSON_OBJECT('key1', 1, 'key2', 'abc') |
+---------------------------------------+
| {"key1": 1, "key2": "abc"} |
+---------------------------------------+
JSON_MERGE_PRESERVE()接受两个或多个 JSON 文档并返回合并的结果:
mysql> SELECT JSON_MERGE_PRESERVE('["a", 1]', '{"key": "value"}');
+-----------------------------------------------------+
| JSON_MERGE_PRESERVE('["a", 1]', '{"key": "value"}') |
+-----------------------------------------------------+
| ["a", 1, {"key": "value"}] |
+-----------------------------------------------------+
1 row in set (0.00 sec)
关于合并规则的信息,请参见 JSON 值的规范化、合并和自动包装。
(MySQL 8.0.3 及更高版本还支持JSON_MERGE_PATCH(),其行为略有不同。有关这两个函数之间差异的信息,请参见 JSON_MERGE_PATCH()与 JSON_MERGE_PRESERVE()的比较 compared with JSON_MERGE_PRESERVE()")。)
JSON 值可以分配给用户定义的变量:
mysql> SET @j = JSON_OBJECT('key', 'value');
mysql> SELECT @j;
+------------------+
| @j |
+------------------+
| {"key": "value"} |
+------------------+
然而,用户定义的变量不能是JSON数据类型,因此,尽管前面示例中的@j看起来像一个 JSON 值,并且具有与 JSON 值相同的字符集和校对规则,但它不具有JSON数据类型。相反,当分配给变量时,JSON_OBJECT()的结果会被转换为字符串。
通过转换 JSON 值生成的字符串具有utf8mb4字符集和utf8mb4_bin校对规则:
mysql> SELECT CHARSET(@j), COLLATION(@j);
+-------------+---------------+
| CHARSET(@j) | COLLATION(@j) |
+-------------+---------------+
| utf8mb4 | utf8mb4_bin |
+-------------+---------------+
因为utf8mb4_bin是一个二进制校对规则,所以 JSON 值的比较是区分大小写的。
mysql> SELECT JSON_ARRAY('x') = JSON_ARRAY('X');
+-----------------------------------+
| JSON_ARRAY('x') = JSON_ARRAY('X') |
+-----------------------------------+
| 0 |
+-----------------------------------+
区分大小写也适用于 JSON 的null、true和false字面量,它们必须始终以小写形式编写:
mysql> SELECT JSON_VALID('null'), JSON_VALID('Null'), JSON_VALID('NULL');
+--------------------+--------------------+--------------------+
| JSON_VALID('null') | JSON_VALID('Null') | JSON_VALID('NULL') |
+--------------------+--------------------+--------------------+
| 1 | 0 | 0 |
+--------------------+--------------------+--------------------+
mysql> SELECT CAST('null' AS JSON);
+----------------------+
| CAST('null' AS JSON) |
+----------------------+
| null |
+----------------------+
1 row in set (0.00 sec)
mysql> SELECT CAST('NULL' AS JSON);
ERROR 3141 (22032): Invalid JSON text in argument 1 to function cast_as_json:
"Invalid value." at position 0 in 'NULL'.
JSON 字面量的大小写敏感性与 SQL 的NULL、TRUE和FALSE字面量的大小写敏感性不同,后者可以以任何大小写形式编写:
mysql> SELECT ISNULL(null), ISNULL(Null), ISNULL(NULL);
+--------------+--------------+--------------+
| ISNULL(null) | ISNULL(Null) | ISNULL(NULL) |
+--------------+--------------+--------------+
| 1 | 1 | 1 |
+--------------+--------------+--------------+
有时可能需要或希望将引号字符("或')插入 JSON 文档中。假设为此示例,您想要插入一些包含表示关于 MySQL 的一些事实的句子的 JSON 对象,每个句子都与适当的关键字配对,插入到使用下面显示的 SQL 语句创建的表中:
mysql> CREATE TABLE facts (sentence JSON);
在这些关键字-句子对中,有这样一个:
mascot: The MySQL mascot is a dolphin named "Sakila".
将此作为 JSON 对象插入facts表中的一种方法是使用 MySQL 的JSON_OBJECT()函数。在这种情况下,必须使用反斜杠转义每个引号字符,如下所示:
mysql> INSERT INTO facts VALUES
> (JSON_OBJECT("mascot", "Our mascot is a dolphin named \"Sakila\"."));
如果将值作为 JSON 对象字面量插入,则不能以相同方式工作,在这种情况下,必须使用双反斜杠转义序列,就像这样:
mysql> INSERT INTO facts VALUES
> ('{"mascot": "Our mascot is a dolphin named \\"Sakila\\"."}');
使用双反斜杠可以阻止 MySQL 执行转义序列处理,而是导致将字符串字面量传递给存储引擎进行处理。在刚刚展示的任一方式中插入 JSON 对象后,可以通过简单的SELECT查看 JSON 列值中存在反斜杠,就像这样:
mysql> SELECT sentence FROM facts;
+---------------------------------------------------------+
| sentence |
+---------------------------------------------------------+
| {"mascot": "Our mascot is a dolphin named \"Sakila\"."} |
+---------------------------------------------------------+
要查找使用mascot作为关键字的特定句子,可以使用列路径运算符->,如下所示:
mysql> SELECT col->"$.mascot" FROM qtest;
+---------------------------------------------+
| col->"$.mascot" |
+---------------------------------------------+
| "Our mascot is a dolphin named \"Sakila\"." |
+---------------------------------------------+
1 row in set (0.00 sec)
这会保留反斜杠,以及周围的引号。要使用mascot作为键显示所需的值,但不包括周围的引号或任何转义字符,请使用内联路径运算符->>,如下所示:
mysql> SELECT sentence->>"$.mascot" FROM facts;
+-----------------------------------------+
| sentence->>"$.mascot" |
+-----------------------------------------+
| Our mascot is a dolphin named "Sakila". |
+-----------------------------------------+
注意
如果启用了NO_BACKSLASH_ESCAPES服务器 SQL 模式,则前面的示例不会按照所示方式工作。如果设置了此模式,则可以使用单个反斜杠而不是双反斜杠来插入 JSON 对象文字,并且反斜杠会被保留。如果在执行插入时使用JSON_OBJECT()函数并设置了此模式,则必须交替使用单引号和双引号,如下所示:
mysql> INSERT INTO facts VALUES
> (JSON_OBJECT('mascot', 'Our mascot is a dolphin named "Sakila".'));
有关此模式对 JSON 值中转义字符的影响的更多信息,请参阅JSON_UNQUOTE()函数的描述。
JSON 值的规范化、合并和自动包装
当解析字符串并发现其为有效的 JSON 文档时,也会进行规范化。这意味着具有与后面在文档中找到的重复键的成员,从左到右阅读,将被丢弃。以下JSON_OBJECT()调用生成的对象值仅包含第二个key1元素,因为该键名在值中较早出现,如下所示:
mysql> SELECT JSON_OBJECT('key1', 1, 'key2', 'abc', 'key1', 'def');
+------------------------------------------------------+
| JSON_OBJECT('key1', 1, 'key2', 'abc', 'key1', 'def') |
+------------------------------------------------------+
| {"key1": "def", "key2": "abc"} |
+------------------------------------------------------+
当值插入 JSON 列时也会执行规范化,如下所示:
mysql> CREATE TABLE t1 (c1 JSON);
mysql> INSERT INTO t1 VALUES
> ('{"x": 17, "x": "red"}'),
> ('{"x": 17, "x": "red", "x": [3, 5, 7]}');
mysql> SELECT c1 FROM t1;
+------------------+
| c1 |
+------------------+
| {"x": "red"} |
| {"x": [3, 5, 7]} |
+------------------+
这种“最后一个重复键胜出”的行为是由RFC 7159建议的,并且大多数 JavaScript 解析器都实现了这种行为。(Bug #86866,Bug #26369555)
在 MySQL 8.0.3 之前的版本中,具有与文档中较早找到的键重复的成员将被丢弃。以下JSON_OBJECT()调用生成的对象值不包含第二个key1元素,因为该键名在值中较早出现:
mysql> SELECT JSON_OBJECT('key1', 1, 'key2', 'abc', 'key1', 'def');
+------------------------------------------------------+
| JSON_OBJECT('key1', 1, 'key2', 'abc', 'key1', 'def') |
+------------------------------------------------------+
| {"key1": 1, "key2": "abc"} |
+------------------------------------------------------+
在 MySQL 8.0.3 之前,插入 JSON 列时也执行了这种“第一个重复键胜出”的规范化。
mysql> CREATE TABLE t1 (c1 JSON);
mysql> INSERT INTO t1 VALUES
> ('{"x": 17, "x": "red"}'),
> ('{"x": 17, "x": "red", "x": [3, 5, 7]}');
mysql> SELECT c1 FROM t1;
+-----------+
| c1 |
+-----------+
| {"x": 17} |
| {"x": 17} |
+-----------+
MySQL 还会丢弃原始 JSON 文档中键、值或元素之间的额外空格,并在显示时在每个逗号(,)或冒号(:)后留下(或在必要时插入)一个空格。这样做是为了增强可读性。
生成 JSON 值的 MySQL 函数(请参阅第 14.17.2 节,“创建 JSON 值的函数”)始终返回规范化值。
为了使查找更有效率,MySQL 还对 JSON 对象的键进行排序。您应该注意,此排序的结果可能会发生变化,并且不能保证在不同版本之间保持一致。
合并 JSON 值
MySQL 8.0.3(以及更高版本)支持两种合并算法,由函数JSON_MERGE_PRESERVE()和JSON_MERGE_PATCH()实现。它们在处理重复键时有所不同:JSON_MERGE_PRESERVE()保留重复键的值,而JSON_MERGE_PATCH()丢弃除最后一个值之外的所有值。接下来的几段将解释这两个函数如何处理不同组合的 JSON 文档(即对象和数组)的合并。
注意
JSON_MERGE_PRESERVE()与 MySQL 先前版本中的JSON_MERGE()函数相同(在 MySQL 8.0.3 中更名)。JSON_MERGE()在 MySQL 8.0 中仍作为JSON_MERGE_PRESERVE()的别名受支持,但已被弃用,并可能在将来的版本中被移除。
合并数组。 在合并多个数组的上下文中,这些数组会合并为一个单一的数组。JSON_MERGE_PRESERVE()通过将后面命名的数组连接到第一个数组的末尾来实现这一点。JSON_MERGE_PATCH()将每个参数视为由单个元素组成的数组(因此其索引为 0),然后应用“最后重复键获胜”的逻辑,仅选择最后一个参数。您可以通过此查询比较所示的结果:
mysql> SELECT
-> JSON_MERGE_PRESERVE('[1, 2]', '["a", "b", "c"]', '[true, false]') AS Preserve,
-> JSON_MERGE_PATCH('[1, 2]', '["a", "b", "c"]', '[true, false]') AS Patch\G
*************************** 1\. row ***************************
Preserve: [1, 2, "a", "b", "c", true, false]
Patch: [true, false]
多个对象合并后产生一个单一对象。JSON_MERGE_PRESERVE()通过将具有相同键的多个对象的所有唯一值组合为一个数组来处理这些对象;然后该数组被用作结果中该键的值。JSON_MERGE_PATCH()丢弃发现重复键的值,从左到右工作,因此结果仅包含该键的最后一个值。以下查询说明了对重复键a的结果差异:
mysql> SELECT
-> JSON_MERGE_PRESERVE('{"a": 1, "b": 2}', '{"c": 3, "a": 4}', '{"c": 5, "d": 3}') AS Preserve,
-> JSON_MERGE_PATCH('{"a": 3, "b": 2}', '{"c": 3, "a": 4}', '{"c": 5, "d": 3}') AS Patch\G
*************************** 1\. row ***************************
Preserve: {"a": [1, 4], "b": 2, "c": [3, 5], "d": 3}
Patch: {"a": 4, "b": 2, "c": 5, "d": 3}
在需要数组值的上下文中使用非数组值时,会自动包装:该值会被[和]字符包围以转换为数组。在下面的语句中,每个参数都被自动包装为一个数组([1],[2])。然后这些数组被合并为一个单一的结果数组;与前两种情况一样,JSON_MERGE_PRESERVE()会合并具有相同键的值,而JSON_MERGE_PATCH()会丢弃所有重复键的值,除了最后一个,如下所示:
mysql> SELECT
-> JSON_MERGE_PRESERVE('1', '2') AS Preserve,
-> JSON_MERGE_PATCH('1', '2') AS Patch\G
*************************** 1\. row ***************************
Preserve: [1, 2]
Patch: 2
数组和对象值通过将对象自动包装为数组并根据合并函数的选择(JSON_MERGE_PRESERVE()或JSON_MERGE_PATCH())合并数组中的值或“最后重复键获胜”来进行合并,如本例所示:
mysql> SELECT
-> JSON_MERGE_PRESERVE('[10, 20]', '{"a": "x", "b": "y"}') AS Preserve,
-> JSON_MERGE_PATCH('[10, 20]', '{"a": "x", "b": "y"}') AS Patch\G
*************************** 1\. row ***************************
Preserve: [10, 20, {"a": "x", "b": "y"}]
Patch: {"a": "x", "b": "y"}
搜索和修改 JSON 值
JSON 路径表达式选择 JSON 文档中的值。
路径表达式在提取或修改 JSON 文档的部分的函数中非常有用,用于指定在文档中的哪个位置操作。例如,以下查询从 JSON 文档中提取具有name键的成员的值:
mysql> SELECT JSON_EXTRACT('{"id": 14, "name": "Aztalan"}', '$.name');
+---------------------------------------------------------+
| JSON_EXTRACT('{"id": 14, "name": "Aztalan"}', '$.name') |
+---------------------------------------------------------+
| "Aztalan" |
+---------------------------------------------------------+
路径语法使用一个前导$字符来表示正在考虑的 JSON 文档,可选地跟随指示逐渐更具体部分的选择器:
-
一个点后跟一个键名命名对象中具有给定键的成员。如果不带引号的键名在路径表达式中不合法(例如,包含空格),则必须在双引号内指定键名。
-
[*N*]附加到选择数组的*path上,命名数组中位置为N的值。数组位置是从零开始的整数。如果path没有选择一个数组值,path[0]会评估为与path*相同的值:mysql> SELECT JSON_SET('"x"', '$[0]', 'a'); +------------------------------+ | JSON_SET('"x"', '$[0]', 'a') | +------------------------------+ | "a" | +------------------------------+ 1 row in set (0.00 sec) -
[*M* to *N*]指定从位置*M开始,到位置N*结束的数组值的子集或范围。last被支持作为最右边数组元素的索引的同义词。也支持数组元素的相对寻址。如果*path没有选择一个数组值,path[last]会评估为与path*相同的值,如本节后面所示(参见最右边数组元素)。 -
路径可以包含
*或**通配符:-
.[*]评估为 JSON 对象中所有成员的值。 -
[*]评估为 JSON 数组中所有元素的值。 -
*prefix****suffix*评估为所有以指定前缀开头并以指定后缀结尾的路径。
-
-
一个在文档中不存在的路径(评估为不存在的数据)会评估为
NULL。
让$指代这个具有三个元素的 JSON 数组:
[3, {"a": [5, 6], "b": 10}, [99, 100]]
然后:
-
$[0]评估为3。 -
$[1]评估为{"a": [5, 6], "b": 10}。 -
$[2]评估为[99, 100]。 -
$[3]评估为NULL(它指代第四个数组元素,但不存在)。
因为$[1]和$[2]评估为非标量值,它们可以作为更具体路径表达式的基础,选择嵌套值。例如:
-
$[1].a评估为[5, 6]。 -
$[1].a[1]评估为6。 -
$[1].b评估为10。 -
$[2][0]评估为99。
如前所述,命名键的路径组件在路径表达式中不合法时必须加引号。让$指代这个值:
{"a fish": "shark", "a bird": "sparrow"}
两个键都包含空格,必须加引号:
-
$."a fish"评估为shark。 -
$."a bird"评估为sparrow。
使用通配符的路径会评估为一个可以包含多个值的数组:
mysql> SELECT JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.*');
+---------------------------------------------------------+
| JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.*') |
+---------------------------------------------------------+
| [1, 2, [3, 4, 5]] |
+---------------------------------------------------------+
mysql> SELECT JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.c[*]');
+------------------------------------------------------------+
| JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.c[*]') |
+------------------------------------------------------------+
| [3, 4, 5] |
+------------------------------------------------------------+
在下面的例子中,路径$**.b评估为多个路径($.a.b和$.c.b)并产生匹配路径值的数组:
mysql> SELECT JSON_EXTRACT('{"a": {"b": 1}, "c": {"b": 2}}', '$**.b');
+---------------------------------------------------------+
| JSON_EXTRACT('{"a": {"b": 1}, "c": {"b": 2}}', '$**.b') |
+---------------------------------------------------------+
| [1, 2] |
+---------------------------------------------------------+
来自 JSON 数组的范围。 您可以使用to关键字与范围一起指定 JSON 数组的子集。例如,$[1 to 3]包括数组的第二、第三和第四个元素,如下所示:
mysql> SELECT JSON_EXTRACT('[1, 2, 3, 4, 5]', '$[1 to 3]');
+----------------------------------------------+
| JSON_EXTRACT('[1, 2, 3, 4, 5]', '$[1 to 3]') |
+----------------------------------------------+
| [2, 3, 4] |
+----------------------------------------------+
1 row in set (0.00 sec)
语法是*M* to *N*,其中*M和N分别是 JSON 数组中一系列元素的第一个和最后一个索引。N必须大于M;M*必须大于或等于 0。数组元素从 0 开始索引。
您可以在支持通配符的上下文中使用范围。
最右侧的数组元素。 last关键字可用作数组中最后一个元素的索引的同义词。形式为last - *N*的表达式可用于相对寻址,以及在范围定义中,如下所示:
mysql> SELECT JSON_EXTRACT('[1, 2, 3, 4, 5]', '$[last-3 to last-1]');
+--------------------------------------------------------+
| JSON_EXTRACT('[1, 2, 3, 4, 5]', '$[last-3 to last-1]') |
+--------------------------------------------------------+
| [2, 3, 4] |
+--------------------------------------------------------+
1 row in set (0.01 sec)
如果路径针对的值不是数组,则评估的结果与将该值包装在单元素数组中的结果相同:
mysql> SELECT JSON_REPLACE('"Sakila"', '$[last]', 10);
+-----------------------------------------+
| JSON_REPLACE('"Sakila"', '$[last]', 10) |
+-----------------------------------------+
| 10 |
+-----------------------------------------+
1 row in set (0.00 sec)
您可以使用*column*->*path*作为 JSON 列标识符和 JSON 路径表达式的同义词,用于JSON_EXTRACT(*column*, *path*)。有关更多信息,请参见第 14.17.3 节,“搜索 JSON 值的函数”。另请参见为提供 JSON 列索引而对生成列进行索引。
一些函数接受现有的 JSON 文档,在某种方式上对其进行修改,并返回结果修改后的文档。路径表达式指示在文档中何处进行更改。例如,JSON_SET()、JSON_INSERT()和JSON_REPLACE()函数分别接受一个 JSON 文档,以及一个或多个描述在何处修改文档以及要使用的值的路径-值对。这些函数在处理文档中的现有值和不存在的值方面有所不同。
考虑这个文档:
mysql> SET @j = '["a", {"b": [true, false]}, [10, 20]]';
JSON_SET()替换存在的路径的值,并为不存在的路径添加值:
mysql> SELECT JSON_SET(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+--------------------------------------------+
| JSON_SET(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+--------------------------------------------+
| ["a", {"b": [1, false]}, [10, 20, 2]] |
+--------------------------------------------+
在这种情况下,路径$[1].b[0]选择了一个现有值(true),该值将被路径参数后面的值(1)替换。路径$[2][2]不存在,因此将值(2)添加到由$[2]选择的值中。
JSON_INSERT()添加新值,但不替换现有值:
mysql> SELECT JSON_INSERT(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+-----------------------------------------------+
| JSON_INSERT(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+-----------------------------------------------+
| ["a", {"b": [true, false]}, [10, 20, 2]] |
+-----------------------------------------------+
JSON_REPLACE()替换现有值并忽略新值:
mysql> SELECT JSON_REPLACE(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+------------------------------------------------+
| JSON_REPLACE(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+------------------------------------------------+
| ["a", {"b": [1, false]}, [10, 20]] |
+------------------------------------------------+
路径-值对从左到右进行评估。通过评估一个对产生的文档成为下一个对要评估的新值。
JSON_REMOVE()接受一个 JSON 文档和一个或多个指定要从文档中移除的值的路径。返回值是原始文档减去由文档内存在的路径选择的值:
mysql> SELECT JSON_REMOVE(@j, '$[2]', '$[1].b[1]', '$[1].b[1]');
+---------------------------------------------------+
| JSON_REMOVE(@j, '$[2]', '$[1].b[1]', '$[1].b[1]') |
+---------------------------------------------------+
| ["a", {"b": [true]}] |
+---------------------------------------------------+
这些路径具有以下效果:
-
$[2]匹配[10, 20]并将其移除。 -
第一个实例
$[1].b[1]匹配b元素中的false并将其移除。 -
第二个实例
$[1].b[1]匹配不到任何内容:该元素已被移除,路径不再存在,也不产生任何效果。
JSON 路径语法
MySQL 支持的许多 JSON 函数在本手册的其他地方有描述(请参见第 14.17 节,“JSON 函数”,在ECMAScript 语言规范中)。路径表达式和 JSON 文本应使用ascii,utf8mb3或utf8mb4字符集进行编码。其他字符编码将被隐式强制转换为utf8mb4。完整的语法如下所示:
*pathExpression*:
*scope*[(*pathLeg*)*]
*pathLeg*:
*member* | *arrayLocation* | *doubleAsterisk*
*member*:
*period* ( *keyName* | *asterisk* )
*arrayLocation*:
*leftBracket* ( *nonNegativeInteger* | *asterisk* ) *rightBracket*
*keyName*:
*ESIdentifier* | *doubleQuotedString*
*doubleAsterisk*:
'**'
*period*:
'.'
*asterisk*:
'*'
*leftBracket*:
'['
*rightBracket*:
']'
正如前面所述,在 MySQL 中,路径的范围始终是操作的文档,表示为$。您可以在 JSON 路径表达式中使用'$'作为文档的同义词。
注意
一些实现支持 JSON 路径范围的列引用;MySQL 8.0 不支持这些功能。
通配符*和**标记的使用如下:
-
.*代表对象中所有成员的值。 -
[*]代表数组中所有单元格的值。 -
[*前缀*]***后缀*代表以*前缀开头并以后缀结尾的所有路径。前缀是可选的,而后缀*是必需的;换句话说,路径不能以**结尾。另外,路径中不能包含序列
***。
有关路径语法示例,请参阅各种接受路径作为参数的 JSON 函数的描述,例如JSON_CONTAINS_PATH(),JSON_SET()和JSON_REPLACE()。有关包含*和**通配符的示例,请参阅JSON_SEARCH()函数的描述。
MySQL 8.0 还支持使用to关键字对 JSON 数组的子集进行范围表示(例如$[2 to 10]),以及使用last关键字作为数组最右侧元素的同义词。有关更多信息和示例,请参见搜索和修改 JSON 值。
JSON 值的比较和排序
可以使用=、<、<=、>、>=、<>、!=和<=>运算符来比较 JSON 值。
尚不支持以下比较运算符和函数与 JSON 值一起使用:
-
BETWEEN -
IN() -
GREATEST() -
LEAST()
对于刚刚列出的比较运算符和函数的解决方法是将 JSON 值转换为本机 MySQL 数值或字符串数据类型,以便它们具有一致的非 JSON 标量类型。
JSON 值的比较分为两个级别。第一级别的比较基于所比较值的 JSON 类型。如果类型不同,则比较结果仅由具有更高优先级的类型确定。如果两个值具有相同的 JSON 类型,则使用特定于类型的规则进行第二级别的比较。
下面的列表显示了 JSON 类型的优先级,从最高优先级到最低优先级。(类型名称是由JSON_TYPE()函数返回的。)在同一行上显示的类型具有相同的优先级。任何具有列表中较早 JSON 类型的值都比具有列表中较晚 JSON 类型的值大。
BLOB
BIT
OPAQUE
DATETIME
TIME
DATE
BOOLEAN
ARRAY
OBJECT
STRING
INTEGER, DOUBLE
NULL
对于具有相同优先级的 JSON 值,比较规则是特定于类型的:
-
BLOB比较两个值的前*
N字节,其中N是较短值中的字节数。如果两个值的前N*字节相同,则较短值在较长值之前排序。 -
BIT与
BLOB相同的规则。 -
OPAQUE与
BLOB相同的规则。OPAQUE值是未分类为其他类型的值。 -
DATETIME代表较早时间点的值在代表较晚时间点的值之前。如果两个值最初分别来自 MySQL 的
DATETIME和TIMESTAMP类型,则如果它们表示相同的时间点,则它们相等。 -
TIME两个时间值中较小的一个在较大的一个之前排序。
-
DATE较早日期在较近日期之前。
-
ARRAY如果两个 JSON 数组具有相同的长度,并且数组中对应位置的值相等,则它们是相等的。
如果数组不相等,则它们的顺序由第一个出现差异的位置的元素确定。在该位置上值较小的数组被排在前面。如果较短数组的所有值都等于较长数组中对应的值,则较短数组被排在前面。
例子:
[] < ["a"] < ["ab"] < ["ab", "cd", "ef"] < ["ab", "ef"] -
BOOLEANJSON 中的 false 文字小于 JSON 中的 true 文字。
-
OBJECT如果两个 JSON 对象具有相同的键集,并且每个键在两个对象中具有相同的值,则它们是相等的。
例子:
{"a": 1, "b": 2} = {"b": 2, "a": 1}两个不相等的对象的顺序是未指定的,但是确定的。
-
STRING字符串在比较时按照两个字符串的
utf8mb4表示的前*N个字节的词法顺序排序,其中N是较短字符串的长度。如果两个字符串的前N*个字节相同,则较短的字符串被认为比较长的字符串小。例子:
"a" < "ab" < "b" < "bc"这种排序等同于具有
utf8mb4_bin排序规则的 SQL 字符串的排序。因为utf8mb4_bin有一个二进制排序规则,所以 JSON 值的比较是区分大小写的:"A" < "a" -
INTEGER,DOUBLEJSON 值可以包含精确值和近似值数字。有关这些类型数字的一般讨论,请参见第 11.1.2 节,“数字文字”。
讨论了比较本机 MySQL 数值类型的规则在第 14.3 节,“表达式求值中的类型转换”中,但是比较 JSON 值中的数字的规则略有不同:
-
在比较使用本机 MySQL
INT- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT") 和DOUBLE- FLOAT, DOUBLE") 数值类型的两列时,已知所有比较涉及整数和双精度数,因此整数被转换为双精度以用于所有行。也就是说,精确值数字被转换为近似值数字。 -
另一方面,如果查询比较包含数字的两个 JSON 列,无法事先知道数字是整数还是双精度。为了在所有行中提供最一致的行为,MySQL 将近似值数字转换为精确值数字。结果的排序是一致的,并且对于精确值数字不会丢失精度。例如,给定标量 9223372036854775805、9223372036854775806、9223372036854775807 和 9.223372036854776e18,顺序如下:
9223372036854775805 < 9223372036854775806 < 9223372036854775807 < 9.223372036854776e18 = 9223372036854776000 < 9223372036854776001
如果 JSON 比较使用非 JSON 数值比较规则,可能会导致不一致的排序。通常的 MySQL 数值比较规则产生以下排序:
-
整数比较:
9223372036854775805 < 9223372036854775806 < 9223372036854775807(未定义为 9.223372036854776e18)
-
双精度比较:
9223372036854775805 = 9223372036854775806 = 9223372036854775807 = 9.223372036854776e18
-
任何 JSON 值与 SQL NULL 的比较结果为UNKNOWN。
对于 JSON 和非 JSON 值的比较,根据以下表中的规则将非 JSON 值转换为 JSON,然后按照先前描述的方式进行比较。
在 JSON 值和非 JSON 值之间转换
以下表格总结了 MySQL 在 JSON 值和其他类型值之间转换时遵循的规则:
表 13.3 JSON 转换规则
| 其他类型 | CAST(other type AS JSON) | CAST(JSON AS other type) |
|---|---|---|
| JSON | 无变化 | 无变化 |
utf8 字符类型(utf8mb4,utf8mb3,ascii) | 字符串被解析为 JSON 值。 | JSON 值被序列化为utf8mb4字符串。 |
| 其他字符类型 | 其他字符编码会隐式转换为utf8mb4,并按照该字符类型描述的方式处理。 | JSON 值被序列化为utf8mb4字符串,然后转换为其他字符编码。结果可能无意义。 |
NULL | 结果为 JSON 类型的NULL值。 | 不适用。 |
| 几何类型 | 几何值通过调用 ST_AsGeoJSON() 转换为 JSON 文档。 | 非法操作。解决方法:将 CAST(*json_val* AS CHAR) 的结果传递给 ST_GeomFromGeoJSON()。 |
| 所有其他类型 | 结果为由单个标量值组成的 JSON 文档。 | 如果 JSON 文档由目标类型的单个标量值组成且该标量值可以转换为目标类型,则成功。否则,返回NULL并产生警告。 |
对于 JSON 值,ORDER BY 和 GROUP BY 遵循以下原则:
-
标量 JSON 值的排序使用与前述讨论相同的规则。
-
对于升序排序,SQL
NULL排在所有 JSON 值之前,包括 JSON 的 null 字面量;对于降序排序,SQLNULL排在所有 JSON 值之后,包括 JSON 的 null 字面量。 -
JSON 值的排序键受
max_sort_length系统变量的值限制,因此仅在首个max_sort_length字节之后有差异的键将被视为相等。 -
非标量值的排序目前不受支持,会出现警告。
对于排序,将 JSON 标量转换为其他本机 MySQL 类型可能是有益的。例如,如果名为jdoc的列包含具有由id键和非负值组成的成员的 JSON 对象,则使用此表达式按id值排序:
ORDER BY CAST(JSON_EXTRACT(jdoc, '$.id') AS UNSIGNED)
如果存在一个生成的列被定义为使用与ORDER BY相同的表达式,MySQL 优化器会识别并考虑在查询执行计划中使用该索引。参见 Section 10.3.11, “生成列索引的优化器使用”。
JSON 值的聚合
对于 JSON 值的聚合,SQL NULL 值会被忽略,就像其他数据类型一样。非NULL 值会被转换为数值类型并进行聚合,除了 MIN(), MAX(), 和 GROUP_CONCAT()。对于 JSON 值转换为数字应该会产生有意义的结果,尽管(取决于值)可能会发生截断和精度丢失。其他 JSON 值的转换为数字可能不会产生有意义的结果。
13.6 数据类型默认值
数据类型规范可以具有显式或隐式默认值。
数据类型规范中的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())
);
例外情况是,对于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 节,“表达式评估中的类型转换”。
显式默认处理在 MySQL 8.0.13 之前
除了一个例外,DEFAULT子句中指定的默认值必须是字面常量;它不能是函数或表达式。这意味着,例如,你不能将日期列的默认值设置为函数值,如NOW()或CURRENT_DATE。例外是,对于TIMESTAMP和DATETIME列,你可以指定CURRENT_TIMESTAMP作为默认值。参见 第 13.2.5 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新”。
BLOB、TEXT、GEOMETRY 和 JSON 数据类型不能被分配默认值。
如果默认值计算结果的数据类型与声明的列类型不同,根据通常的 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));
参见第 7.1.11 节,“服务器 SQL 模式”。
对于给定表,SHOW CREATE TABLE语句显示哪些列具有显式的DEFAULT子句。
隐式默认值定义如下:
-
对于数值类型,默认值为
0,但对于声明了AUTO_INCREMENT属性的整数或浮点数类型,其默认值为序列中的下一个值。 -
对于除
TIMESTAMP之外的日期和时间类型,其默认值为该类型的适当“零”值。如果启用了explicit_defaults_for_timestamp系统变量(参见第 7.1.8 节,“服务器系统变量”),则对于TIMESTAMP也是如此。否则,对于表中的第一个TIMESTAMP列,其默认值为当前日期和时间。参见第 13.2 节,“日期和时间数据类型”。 -
对于除
ENUM之外的字符串类型,默认值为空字符串。对于ENUM,默认值为第一个枚举值。
13.7 数据类型存储要求
原文:
dev.mysql.com/doc/refman/8.0/en/storage-requirements.html
-
InnoDB 表存储要求
-
NDB 表存储要求
-
数值类型存储要求
-
日期和时间类型存储要求
-
字符串类型存储要求
-
空间类型存储要求
-
JSON 存储要求
磁盘上表数据的存储要求取决于几个因素。不同的存储引擎表示数据类型并以不同方式存储原始数据。表数据可能会被压缩,无论是针对列还是整个行,这会使得计算表或列的存储要求变得复杂。
尽管在磁盘上存储布局存在差异,但内部 MySQL API 用于通信和交换关于表行的信息的数据结构是一致的,适用于所有存储引擎。
本节包括 MySQL 支持的每种数据类型的存储要求的指南和信息,包括对使用固定大小表示数据类型的存储引擎的内部格式和大小的描述。信息按类别或存储引擎列出。
表的内部表示最大行大小为 65,535 字节,即使存储引擎能够支持更大的行也是如此。这个数字不包括BLOB或TEXT列,这些列只对这个大小贡献了 9 到 12 个字节。对于BLOB和TEXT数据,信息存储在内存的不同区域中,而不是行缓冲区。不同的存储引擎根据它们用于处理相应类型的方法以不同的方式处理这些数据的分配和存储。有关更多信息,请参见第十八章,替代存储引擎和第 10.4.7 节,“表列计数和行大小限制”。
InnoDB 表存储要求
有关InnoDB表的存储要求,请参见第 17.10 节“InnoDB 行格式”。
NDB 表存储要求
重要提示
NDB表使用 4 字节对齐;所有NDB数据存储都是 4 字节的倍数。因此,在NDB表中,通常需要 15 字节的列值需要 16 字节。例如,在NDB表中,TINYINT、SMALLINT、MEDIUMINT和INTEGER(INT)列类型每个记录需要 4 字节的存储空间,这是由于对齐因素。
每个BIT(*M*)列占用M位的存储空间。虽然单个BIT列不是 4 字节对齐,但是NDB每行为BIT列的前 1-32 位保留 4 字节(32 位),然后为第 33-64 位保留另外 4 字节,依此类推。
虽然NULL本身不需要任何存储空间,但是如果表定义包含允许NULL的列,NDB每行将保留 4 个字节,最多 32 个NULL列。(如果 NDB Cluster 表定义中包含超过 32 个NULL列,最多 64 个NULL列,则每行将保留 8 个字节。)
每个使用NDB存储引擎的表都需要一个主键;如果您没有定义主键,NDB将创建一个“隐藏”主键。这个隐藏主键每个表记录消耗 31-35 字节。
您可以使用 ndb_size.pl Perl 脚本来估算NDB的存储需求。它连接到当前的 MySQL(而不是 NDB Cluster)数据库,并创建一个关于如果该数据库使用NDB存储引擎将需要多少空间的报告。有关更多信息,请参见 第 25.5.28 节“ndb_size.pl — NDBCLUSTER Size Requirement Estimator”。
数值类型存储需求
| 数据类型 | 所需存储空间 |
|---|---|
TINYINT | 1 字节 |
SMALLINT | 2 字节 |
MEDIUMINT | 3 字节 |
INT, INTEGER | 4 字节 |
BIGINT | 8 字节 |
FLOAT(*p*) | 如果 0 <= p <= 24,则为 4 字节,如果 25 <= p <= 53,则为 8 字节 |
FLOAT | 4 字节 |
DOUBLE [PRECISION], REAL | 8 字节 |
DECIMAL(*M*,*D*), NUMERIC(*M*,*D*) | 变化;参见下面的讨论 |
BIT(*M*) | 大约(M+7)/8 字节 |
| 数据类型 | 所需存储空间 |
DECIMAL(以及NUMERIC列使用一种二进制格式表示,将九个十进制(十进制)数字打包成四个字节。每个值的整数部分和小数部分的存储是分开确定的。每个九位数字的倍数需要四个字节,“剩余”数字需要四个字节的一部分。多余数字所需的存储空间由下表给出。
| 剩余数字 | 字节数 |
|---|---|
| 0 | 0 |
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 2 |
| 5 | 3 |
| 6 | 3 |
| 7 | 4 |
| 8 | 4 |
日期和时间类型存储需求
对于 TIME、DATETIME 和 TIMESTAMP 列,MySQL 5.6.4 之前创建的表所需的存储空间与从 5.6.4 开始创建的表不同。这是因为 5.6.4 版本的更改允许这些类型具有分数部分,这需要从 0 到 3 个字节。
| 数据类型 | MySQL 5.6.4 之前所需存储空间 | MySQL 5.6.4 及以后所需存储空间 |
|---|---|---|
YEAR | 1 字节 | 1 字节 |
DATE | 3 字节 | 3 字节 |
TIME | 3 字节 | 3 字节 + 分数秒存储 |
DATETIME | 8 字节 | 5 字节 + 分数秒存储 |
TIMESTAMP | 4 字节 | 4 字节 + 分数秒存储 |
截至 MySQL 5.6.4 版本,YEAR 和 DATE 的存储方式保持不变。然而,TIME、DATETIME 和 TIMESTAMP 的表示方式有所不同。DATETIME 被更有效地打包,非分数部分只需 5 个字节,而不是 8 个字节,而且所有三部分都有一个分数部分,根据存储值的分数秒精度,需要从 0 到 3 个字节。
| 分数秒精度 | 所需存储空间 |
|---|---|
| 0 | 0 字节 |
| 1, 2 | 1 字节 |
| 3, 4 | 2 字节 |
| 5, 6 | 3 字节 |
例如,TIME(0)、TIME(2)、TIME(4) 和 TIME(6) 分别使用 3、4、5 和 6 个字节。TIME 和 TIME(0) 是等效的,需要相同的存储空间。
有关时间值的内部表示的详细信息,请参阅 MySQL Internals: Important Algorithms and Structures。
字符串类型存储要求
在下表中,*M代表非二进制字符串类型的声明列长度(以字符计)和二进制字符串类型的字节数。L*代表给定字符串值的实际字节长度。
| 数据类型 | 所需存储空间 |
|---|---|
CHAR(*M*) | InnoDB 行格式的紧凑系列优化了变长字符集的存储。请参阅 COMPACT 行格式存储特性。否则,M × *w字节,<= *M* <= 255,其中w*是字符集中最大长度字符所需的字节数。 |
BINARY(*M*) | *M*字节,0 <= *M* <= 255 |
VARCHAR(*M*), VARBINARY(*M*) | 如果列值需要 0 − 255 字节,则为*L* + 1 字节,如果值可能需要超过 255 字节,则为*L* + 2 字节 |
TINYBLOB, TINYTEXT | L + 1 字节,其中*L* < 2⁸ |
BLOB, TEXT | L + 2 字节,其中*L* < 2¹⁶ |
MEDIUMBLOB, MEDIUMTEXT | L + 3 字节,其中*L* < 2²⁴ |
LONGBLOB, LONGTEXT | L + 4 字节,其中*L* < 2³² |
ENUM('*value1*','*value2*',...) | 1 或 2 字节,取决于枚举值的数量(最多 65,535 个值) |
SET('*value1*','*value2*',...) | 1、2、3、4 或 8 字节,取决于集合成员的数量(最多 64 个成员) |
变长字符串类型使用长度前缀加数据进行存储。长度前缀根据数据类型需要占用一到四个字节不等,前缀的值为*L(字符串的字节长度)。例如,存储MEDIUMTEXT值需要L*字节来存储值,再加上三个字节来存储值的长度。
要计算存储特定CHAR、VARCHAR或TEXT列值所需的字节数,必须考虑用于该列的字符集以及值是否包含多字节字符。特别是在使用 UTF-8 Unicode 字符集时,必须记住并非所有字符使用相同数量的字节。utf8mb3和utf8mb4字符集分别可以每个字符需要最多三个和四个字节。有关不同类别utf8mb3或utf8mb4字符所使用的存储的详细信息,请参见第 12.9 节“Unicode 支持”。
VARCHAR、VARBINARY、BLOB 和 TEXT 类型是可变长度类型。对于每种类型,存储需求取决于以下因素:
-
列值的实际长度
-
列的最大可能长度
-
列使用的字符集,因为某些字符集包含多字节字符
例如,VARCHAR(255) 列可以容纳最大长度为 255 个字符的字符串。假设该列使用 latin1 字符集(每个字符一个字节),实际所需存储空间是字符串的长度(L),再加上一个字节来记录字符串的长度。对于字符串 'abcd',L 为 4,存储需求为五个字节。如果相同列改为使用 ucs2 双字节字符集,则存储需求为 10 个字节:'abcd' 的长度为八个字节,列需要两个字节来存储长度,因为最大长度大于 255(最多 510 个字节)。
可存储在 VARCHAR 或 VARBINARY 列中的有效最大 字节数 受限于 65,535 字节的最大行大小,该大小在所有列之间共享。对于存储多字节字符的 VARCHAR 列,有效最大 字符数 较少。例如,utf8mb4 字符可能每个字符需要最多四个字节,因此使用 utf8mb4 字符集的 VARCHAR 列最多可以声明为 16,383 个字符。参见 第 10.4.7 节,“表列数和行大小的限制”。
InnoDB 将长度大于或等于 768 个字节的固定长度字段编码为可变长度字段,可以存储在页外。例如,如果 CHAR(255) 列的字符集的最大字节长度大于 3,比如 utf8mb4,则可以超过 768 个字节。
NDB 存储引擎支持可变宽度列。这意味着在 NDB Cluster 表中,VARCHAR 列需要与任何其他存储引擎相同的存储空间,唯一的例外是这些值是 4 字节对齐的。因此,在使用 latin1 字符集的 VARCHAR(50) 列中存储的字符串 'abcd' 需要 8 字节(而不是在 MyISAM 表中相同列值的 5 字节)。
TEXT, BLOB 和 JSON 列在 NDB 存储引擎中实现方式不同,其中列中的每一行由两个独立部分组成。其中一个是固定大小的(TEXT 和 BLOB 为 256 字节,JSON 为 4000 字节),实际上存储在原始表中。另一个部分包含超过 256 字节的任何数据,存储在隐藏的 blob 部分表中。第二个表中行的大小由列的确切类型确定,如下表所示:
| 类型 | Blob 部分大小 |
|---|---|
BLOB, TEXT | 2000 |
MEDIUMBLOB, MEDIUMTEXT | 4000 |
LONGBLOB, LONGTEXT | 13948 |
JSON | 8100 |
这意味着如果 size <= 256(其中 size 表示行的大小),则 TEXT 列的大小为 256;否则,大小为 256 + size + (2000 × (size − 256) % 2000)。
NDB 不会为 TINYBLOB 或 TINYTEXT 列值单独存储 blob 部分。
可以使用 NDB_COLUMN 在创建或更改父表时在列注释中将 NDB blob 列的 blob 部分大小增加到最大值 13948。在 NDB 8.0.30 及更高版本中,还可以使用 NDB_TABLE 在列注释中设置 TEXT、BLOB 或 JSON 列的内联大小。有关更多信息,请参见 NDB_COLUMN 选项。
ENUM 对象的大小由不同枚举值的数量确定。对于最多有 255 个可能值的枚举,使用一个字节。对于具有 256 到 65,535 个可能值的枚举,使用两个字节。请参见 第 13.3.5 节,“ENUM 类型”。
SET 对象的大小由不同集合成员的数量确定。如果集合大小为 N,则对象占用 (*N*+7)/8 字节,向上取整为 1、2、3、4 或 8 字节。SET 最多可以有 64 个成员。请参见 第 13.3.6 节,“SET 类型”。
空间类型存储要求
MySQL 使用 4 个字节来存储几何值的 SRID,后跟值的 WKB 表示。LENGTH() 函数返回存储值所需的字节空间。
有关空间值的 WKB 和内部存储格式的描述,请参阅第 13.4.3 节,“支持的空间数据格式”。
JSON 存储需求
一般来说,JSON 列的存储需求大致与 LONGBLOB 或 LONGTEXT 列相同;也就是说,JSON 文档所占用的空间大致与存储在这些类型列中的文档的字符串表示相同。然而,由于存储在 JSON 文档中的各个值的二进制编码,包括用于查找的元数据和字典,会带来一些额外开销。例如,存储在 JSON 文档中的字符串需要额外的 4 到 10 字节的存储空间,取决于字符串的长度以及存储它的对象或数组的大小。
此外,MySQL 对存储在 JSON 列中的任何 JSON 文档的大小施加了限制,使其不能大于 max_allowed_packet 的值。
13.8 选择适合列的正确类型
为了最佳存储,您应该尽量在所有情况下使用最精确的类型。例如,如果整数列用于范围在1到99999之间的值,MEDIUMINT UNSIGNED是最佳类型。在表示所有所需值的类型中,此类型使用的存储空间最少。
所有基本计算(+, -, *, 和 /)与DECIMAL列都以 65 位十进制(基数 10)数字的精度进行。参见 Section 13.1.1, “Numeric Data Type Syntax”。
如果精度不是太重要,或者速度是最高优先级,DOUBLE 类型可能已经足够好了。对于高精度,您可以随时转换为存储在BIGINT中的固定点类型。这使您可以使用 64 位整数进行所有计算,然后根据需要将结果转换回浮点值。
13.9 使用其他数据库引擎的数据类型
原文:
dev.mysql.com/doc/refman/8.0/en/other-vendor-data-types.html
为了方便使用来自其他供应商的 SQL 实现编写的代码,MySQL 将数据类型映射如下表所示。这些映射使得更容易将其他数据库系统的表定义导入到 MySQL 中。
| 其他供应商类型 | MySQL 类型 |
|---|---|
BOOL | TINYINT |
BOOLEAN | TINYINT |
CHARACTER VARYING(*M*) | VARCHAR(*M*) |
FIXED | DECIMAL |
FLOAT4 | FLOAT |
FLOAT8 | DOUBLE |
INT1 | TINYINT |
INT2 | SMALLINT |
INT3 | MEDIUMINT |
INT4 | INT |
INT8 | BIGINT |
LONG VARBINARY | MEDIUMBLOB |
LONG VARCHAR | MEDIUMTEXT |
LONG | MEDIUMTEXT |
MIDDLEINT | MEDIUMINT |
NUMERIC | DECIMAL |
| 其他供应商类型 | MySQL 类型 |
数据类型映射发生在表创建时,之后原始类型规范被丢弃。如果你创建了一个使用其他供应商类型的表,然后发出一个DESCRIBE *tbl_name*语句,MySQL 会使用等效的 MySQL 类型报告表结构。例如:
mysql> CREATE TABLE t (a BOOL, b FLOAT8, c LONG VARCHAR, d NUMERIC);
Query OK, 0 rows affected (0.00 sec)
mysql> DESCRIBE t;
+-------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| a | tinyint(1) | YES | | NULL | |
| b | double | YES | | NULL | |
| c | mediumtext | YES | | NULL | |
| d | decimal(10,0) | YES | | NULL | |
+-------+---------------+------+-----+---------+-------+
4 rows in set (0.01 sec)
第十四章 函数和运算符
目录
14.1 内置函数和运算符参考
14.2 可加载函数参考
14.3 表达式求值中的类型转换
14.4 运算符
14.4.1 运算符优先级
14.4.2 比较函数和运算符
14.4.3 逻辑运算符
14.4.4 赋值运算符
14.5 流程控制函数
14.6 数值函数和运算符
14.6.1 算术运算符
14.6.2 数学函数
14.7 日期和时间函数
14.8 字符串函数和运算符
14.8.1 字符串比较函数和运算符
14.8.2 正则表达式
14.8.3 函数结果的字符集和排序规则
14.9 全文搜索函数
14.9.1 自然语言全文搜索
14.9.2 布尔全文搜索
14.9.3 具有查询扩展的全文搜索
14.9.4 全文搜索停用词
14.9.5 全文搜索限制
14.9.6 调整 MySQL 全文搜索
14.9.7 为全文索引添加用户定义排序规则
14.9.8 ngram 全文解析器
14.9.9 MeCab 全文解析器插件
14.10 强制转换函数和运算符
14.11 XML 函数
14.12 位运算函数和运算符
14.13 加密和压缩函数
14.14 锁定函数
14.15 信息函数
14.16 空间分析函数
14.16.1 空间函数参考
14.16.2 空间函数的参数处理
14.16.3 从 WKT 值创建几何值的函数
14.16.4 从 WKB 值创建几何值的函数
14.16.5 MySQL 特定的从几何值创建函数
14.16.6 几何格式转换函数
14.16.7 几何属性函数
14.16.8 空间运算符函数
14.16.9 几何对象之间空间关系测试函数
14.16.10 空间 Geohash 函数
14.16.11 空间 GeoJSON 函数
14.16.12 空间聚合函数
14.16.13 空间便利函数
14.17 JSON 函数
14.17.1 JSON 函数参考
14.17.2 创建 JSON 值的函数
14.17.3 搜索 JSON 值的函数
14.17.4 修改 JSON 值的函数
14.17.5 返回 JSON 值属性的函数
14.17.6 JSON 表函数
14.17.7 JSON 模式验证函数
14.17.8 JSON 实用函数
14.18 复制函数
14.18.1 组复制函数
14.18.2 与全局事务标识符(GTID)一起使用的函数
14.18.3 异步复制通道故障转移函数
14.18.4 基于位置的同步函数
14.19 聚合函数
14.19.1 聚合函数描述
14.19.2 GROUP BY 修饰符
14.19.3 MySQL 处理 GROUP BY
14.19.4 功能依赖检测
14.20 窗口函数
14.20.1 窗口函数描述
14.20.2 窗口函数概念和语法
14.20.3 窗口函数框架规范
14.20.4 命名窗口
14.20.5 窗口函数限制
14.21 性能模式函数
14.22 内部函数
14.23 杂项函数
14.24 精确数学
14.24.1 数值类型
14.24.2 DECIMAL 数据类型特性
14.24.3 表达式处理
14.24.4 四舍五入行为
14.24.5 精确数学示例
表达式可以在 SQL 语句的多个位置中使用,例如在SELECT语句的ORDER BY或HAVING子句中,在SELECT、DELETE或UPDATE语句的WHERE子句中,或在SET语句中。表达式可以使用来自多个来源的值编写,例如文字值、列值、NULL、变量、内置函数和运算符、可加载函数以及存储函数(一种存储对象类型)。
本章描述了在 MySQL 中允许用于编写表达式的内置函数和运算符。有关可加载函数和存储函数的信息,请参见第 7.7 节,“MySQL 服务器可加载函数”和第 27.2 节,“使用存储例程”。有关服务器解释对不同类型函数引用的规则,请参见第 11.2.5 节,“函数名称解析和解析”。
包含NULL的表达式始终产生NULL值,除非特定函数或运算符的文档另有说明。
注意
默认情况下,函数名称和其后的括号之间不能有空格。这有助于 MySQL 解析器区分函数调用和恰好与函数同名的表或列的引用。但是,函数参数周围的空格是允许的。
通过使用--sql-mode=IGNORE_SPACE选项告诉 MySQL 服务器接受函数名称后的空格。 (请参见第 7.1.11 节,“服务器 SQL 模式”。)个别客户端程序可以通过在mysql_real_connect()中使用CLIENT_IGNORE_SPACE选项来请求此行为。在任一情况下,所有函数名称都变为保留字。
为简洁起见,本章中的一些示例以缩写形式显示了来自mysql程序的输出。而不是以这种格式显示示例:
mysql> SELECT MOD(29,9);
+-----------+
| mod(29,9) |
+-----------+
| 2 |
+-----------+
1 rows in set (0.00 sec)
取而代之的是使用此格式:
mysql> SELECT MOD(29,9);
-> 2
14.1 内置函数和运算符参考
原文:
dev.mysql.com/doc/refman/8.0/en/built-in-function-reference.html
以下表格列出了每个内置(原生)函数和运算符,并提供了每个的简短描述。有关在运行时可加载的函数列表,请参见第 14.2 节,“可加载函数参考”。
表格 14.1 内置函数和运算符
| 名称 | 描述 | 引入 | 废弃 |
|---|---|---|---|
& | 按位与 | ||
> | 大于运算符 | ||
>> | 右移 | ||
>= | 大于或等于运算符 | ||
< | 小于运算符 | ||
<>, != | 不等于运算符 | ||
<< | 左移 | ||
<= | 小于或等于运算符 | ||
<=> | NULL 安全等于运算符 | ||
%, MOD | 取模运算符 | ||
* | 乘法运算符 | ||
+ | 加法运算符 | ||
- | 减法运算符 | ||
- | 改变参数的符号 | ||
-> | 在评估路径后从 JSON 列返回值;相当于 JSON_EXTRACT()。 | ||
->> | 在评估路径并取消引用结果后从 JSON 列返回值;相当于 JSON_UNQUOTE(JSON_EXTRACT())。 | ||
/ | 除法运算符 | ||
:= | 赋值 | ||
= | 赋值(作为 SET 语句的一部分,或作为 UPDATE 语句中 SET 子句的一部分) | ||
= | 等于运算符 | ||
^ | 按位异或 | ||
ABS() | 返回绝对值 | ||
ACOS() | 返回反余弦 | ||
ADDDATE() | 将时间值(间隔)添加到日期值中 | ||
ADDTIME() | 添加时间 | ||
AES_DECRYPT() | 使用 AES 解密 | ||
AES_ENCRYPT() | 使用 AES 加密 | ||
AND, && | 逻辑与 | ||
ANY_VALUE() | 抑制 ONLY_FULL_GROUP_BY 值拒绝 | ||
ASCII() | 返回最左字符的数字值 | ||
ASIN() | 返回反正弦 | ||
asynchronous_connection_failover_add_managed() | 将组成员源服务器配置信息添加到复制通道源列表 | 8.0.23 | |
asynchronous_connection_failover_add_source() | 将源服务器配置信息添加到复制通道源列表 | 8.0.22 | |
asynchronous_connection_failover_delete_managed() | 从复制通道源列表中删除受管组 | 8.0.23 | |
asynchronous_connection_failover_delete_source() | 从复制通道源列表中删除源服务器 | 8.0.22 | |
asynchronous_connection_failover_reset() | 删除与组复制异步故障转移相关的所有设置 | 8.0.27 | |
ATAN() | 返回反正切 | ||
ATAN2(), ATAN() | 返回两个参数的反正切 | ||
AVG() | 返回参数的平均值 | ||
BENCHMARK() | 反复执行表达式 | ||
BETWEEN ... AND ... | 值是否在一系列值范围内 | ||
BIN() | 返回包含数字的二进制表示的字符串 | ||
BIN_TO_UUID() | 将二进制 UUID 转换为字符串 | ||
BINARY | 将字符串转换为二进制字符串 | 8.0.27 | |
BIT_AND() | 返回按位与 | ||
BIT_COUNT() | 返回设置的位数 | ||
BIT_LENGTH() | 返回参数的位长度 | ||
BIT_OR() | 返回按位或 | ||
BIT_XOR() | 返回按位异或 | ||
CAN_ACCESS_COLUMN() | 仅供内部使用 | ||
CAN_ACCESS_DATABASE() | 仅供内部使用 | ||
CAN_ACCESS_TABLE() | 仅供内部使用 | ||
CAN_ACCESS_USER() | 仅供内部使用 | 8.0.22 | |
CAN_ACCESS_VIEW() | 仅供内部使用 | ||
CASE | Case 运算符 | ||
CAST() | 将值转换为特定类型 | ||
CEIL() | 返回不小于参数的最小整数值 | ||
CEILING() | 返回不小于参数的最小整数值 | ||
CHAR() | 返回每个传递的整数的字符 | ||
CHAR_LENGTH() | 返回参数中的字符数 | ||
CHARACTER_LENGTH() | CHAR_LENGTH()的同义词 | ||
CHARSET() | 返回参数的字符集 | ||
COALESCE() | 返回第一个非 NULL 参数 | ||
COERCIBILITY() | 返回字符串参数的排序强制性值 | ||
COLLATION() | 返回字符串参数的排序规则 | ||
COMPRESS() | 返回结果作为二进制字符串 | ||
CONCAT() | 返回连接的字符串 | ||
CONCAT_WS() | 返回带有分隔符的连接 | ||
CONNECTION_ID() | 返回连接的连接 ID(线程 ID) | ||
CONV() | 在不同进制之间转换数字 | ||
CONVERT() | 将值转换为特定类型 | ||
CONVERT_TZ() | 从一个时区转换到另一个时区 | ||
COS() | 返回余弦值 | ||
COT() | 返回余切 | ||
COUNT() | 返回返回的行数计数 | ||
COUNT(DISTINCT) | 返回不同值的计数 | ||
CRC32() | 计算循环冗余校验值 | ||
CUME_DIST() | 累积分布值 | ||
CURDATE() | 返回当前日期 | ||
CURRENT_DATE(), CURRENT_DATE | CURDATE()的同义词 | ||
CURRENT_ROLE() | 返回当前活动角色 | ||
CURRENT_TIME(), CURRENT_TIME | CURTIME()的同义词 | ||
CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP | NOW()的同义词 | ||
CURRENT_USER(), CURRENT_USER | 认证用户名称和主机名 | ||
CURTIME() | 返回当前时间 | ||
DATABASE() | 返回默认(当前)数据库名称 | ||
DATE() | 提取日期或日期时间表达式的日期部分 | ||
DATE_ADD() | 将时间值(间隔)添加到日期值 | ||
DATE_FORMAT() | 格式化指定的日期 | ||
DATE_SUB() | 从日期中减去时间值(间隔) | ||
DATEDIFF() | 减去两个日期 | ||
DAY() | DAYOFMONTH()的同义词 | ||
DAYNAME() | 返回星期几的名称 | ||
DAYOFMONTH() | 返回月份的日期(0-31) | ||
DAYOFWEEK() | 返回参数的星期索引 | ||
DAYOFYEAR() | 返回年份的日期(1-366) | ||
DEFAULT() | 返回表列的默认值 | ||
DEGREES() | 将弧度转换为度数 | ||
DENSE_RANK() | 在其分区内当前行的排名,无间隔 | ||
DIV | 整数除法 | ||
ELT() | 返回索引号处的字符串 | ||
EXP() | 求幂 | ||
EXPORT_SET() | 返回一个字符串,对于值位中的每个位设置,您会得到一个打开字符串,对于每个未设置的位,您会得到一个关闭字符串 | ||
EXTRACT() | 提取日期的部分 | ||
ExtractValue() | 使用 XPath 表示法从 XML 字符串中提取值 | ||
FIELD() | 第一个参数在后续参数中的索引(位置) | ||
FIND_IN_SET() | 第一个参数在第二个参数中的索引(位置) | ||
FIRST_VALUE() | 窗口帧的第一行中的参数值 | ||
FLOOR() | 返回不大于参数的最大整数值 | ||
FORMAT() | 返回格式化为指定小数位数的数字 | ||
FORMAT_BYTES() | 将字节计数转换为带单位的值 | 8.0.16 | |
FORMAT_PICO_TIME() | 将皮秒时间转换为带单位的值 | 8.0.16 | |
FOUND_ROWS() | 对于带有 LIMIT 子句的 SELECT 语句,如果没有 LIMIT 子句,将返回的行数 | ||
FROM_BASE64() | 解码 base64 编码的字符串并返回结果 | ||
FROM_DAYS() | 将天数转换为日期 | ||
FROM_UNIXTIME() | 将 Unix 时间戳格式化为日期 | ||
GeomCollection() | 从几何体构造几何集合 | ||
GeometryCollection() | 从几何体构造几何集合 | ||
GET_DD_COLUMN_PRIVILEGES() | 仅供内部使用 | ||
GET_DD_CREATE_OPTIONS() | 仅供内部使用 | ||
GET_DD_INDEX_SUB_PART_LENGTH() | 仅供内部使用 | ||
GET_FORMAT() | 返回日期格式字符串 | ||
GET_LOCK() | 获取命名锁 | ||
GREATEST() | 返回最大的参数 | ||
GROUP_CONCAT() | 返回连接的字符串 | ||
group_replication_disable_member_action() | 为指定事件禁用成员操作 | 8.0.26 | |
group_replication_enable_member_action() | 为指定事件启用成员操作 | 8.0.26 | |
group_replication_get_communication_protocol() | 获取当前正在使用的组复制通信协议的版本 | 8.0.16 | |
group_replication_get_write_concurrency() | 获取当前为组设置的最大一致性实例数 | 8.0.13 | |
group_replication_reset_member_actions() | 将所有成员操作重置为默认值,并将配置版本号重置为 1 | 8.0.26 | |
group_replication_set_as_primary() | 将特定组成员设为主节点 | 8.0.29 | |
group_replication_set_communication_protocol() | 设置组复制通信协议要使用的版本 | 8.0.16 | |
group_replication_set_write_concurrency() | 设置可以并行执行的最大一致性实例数 | 8.0.13 | |
group_replication_switch_to_multi_primary_mode() | 将运行在单主模式下的组的模式更改为多主模式 | 8.0.13 | |
group_replication_switch_to_single_primary_mode() | 将运行在多主模式下的组的模式更改为单主模式 | 8.0.13 | |
GROUPING() | 区分超级聚合 ROLLUP 行和常规行 | ||
GTID_SUBSET() | 如果子集中的所有 GTID 也在集合中,则返回 true;否则返回 false。 | ||
GTID_SUBTRACT() | 返回集合中不在子集中的所有 GTID。 | ||
HEX() | 十六进制表示的十进制或字符串值 | ||
HOUR() | 提取小时 | ||
ICU_VERSION() | ICU 库版本 | ||
IF() | 如果/否则结构 | ||
IFNULL() | 如果/否则结构中的空值 | ||
IN() | 值是否在一组值内 | ||
INET_ATON() | 返回 IP 地址的数值 | ||
INET_NTOA() | 从数值返回 IP 地址 | ||
INET6_ATON() | 返回 IPv6 地址的数值 | ||
INET6_NTOA() | 从数值返回 IPv6 地址 | ||
INSERT() | 在指定位置插入子字符串,最多指定字符数 | ||
INSTR() | 返回子字符串第一次出现的索引 | ||
INTERNAL_AUTO_INCREMENT() | 仅供内部使用 | ||
INTERNAL_AVG_ROW_LENGTH() | 仅供内部使用 | ||
INTERNAL_CHECK_TIME() | 仅供内部使用 | ||
INTERNAL_CHECKSUM() | 仅供内部使用 | ||
INTERNAL_DATA_FREE() | 仅供内部使用 | ||
INTERNAL_DATA_LENGTH() | 仅供内部使用 | ||
INTERNAL_DD_CHAR_LENGTH() | 仅供内部使用 | ||
INTERNAL_GET_COMMENT_OR_ERROR() | 仅供内部使用 | ||
INTERNAL_GET_ENABLED_ROLE_JSON() | 仅供内部使用 | 8.0.19 | |
INTERNAL_GET_HOSTNAME() | 仅供内部使用 | 8.0.19 | |
INTERNAL_GET_USERNAME() | 仅供内部使用 | 8.0.19 | |
INTERNAL_GET_VIEW_WARNING_OR_ERROR() | 仅供内部使用 | ||
INTERNAL_INDEX_COLUMN_CARDINALITY() | 仅供内部使用 | ||
INTERNAL_INDEX_LENGTH() | 仅供内部使用 | ||
INTERNAL_IS_ENABLED_ROLE() | 仅供内部使用 | 8.0.19 | |
INTERNAL_IS_MANDATORY_ROLE() | 仅供内部使用 | 8.0.19 | |
INTERNAL_KEYS_DISABLED() | 仅供内部使用 | ||
INTERNAL_MAX_DATA_LENGTH() | 仅供内部使用 | ||
INTERNAL_TABLE_ROWS() | 仅供内部使用 | ||
INTERNAL_UPDATE_TIME() | 仅供内部使用 | ||
INTERVAL() | 返回小于第一个参数的参数的索引 | ||
IS | 测试一个值是否为布尔值 | ||
IS_FREE_LOCK() | 检查指定的锁是否空闲 | ||
IS_IPV4() | 参数是否为 IPv4 地址 | ||
IS_IPV4_COMPAT() | 参数是否为 IPv4 兼容地址 | ||
IS_IPV4_MAPPED() | 参数是否为 IPv4 映射地址 | ||
IS_IPV6() | 参数是否为 IPv6 地址 | ||
IS NOT | 测试一个值是否为布尔值 | ||
IS NOT NULL | 非 NULL 值测试 | ||
IS NULL | NULL 值测试 | ||
IS_USED_LOCK() | 检查指定的锁是否正在使用;如果是,则返回连接标识符 | ||
IS_UUID() | 参数是否为有效的 UUID | ||
ISNULL() | 测试参数是否为 NULL | ||
JSON_ARRAY() | 创建 JSON 数组 | ||
JSON_ARRAY_APPEND() | 向 JSON 文档追加数据 | ||
JSON_ARRAY_INSERT() | 插入到 JSON 数组中 | ||
JSON_ARRAYAGG() | 将结果集作为单个 JSON 数组返回 | ||
JSON_CONTAINS() | JSON 文档是否包含特定路径处的对象 | ||
JSON_CONTAINS_PATH() | JSON 文档是否在路径处包含任何数据 | ||
JSON_DEPTH() | JSON 文档的最大深度 | ||
JSON_EXTRACT() | 从 JSON 文档中返回数据 | ||
JSON_INSERT() | 将数据插入 JSON 文档 | ||
JSON_KEYS() | JSON 文档中的键数组 | ||
JSON_LENGTH() | JSON 文档中的元素数量 | ||
JSON_MERGE() | 合并 JSON 文档,保留重复的键。已弃用的 JSON_MERGE_PRESERVE()的同义词 | 是 | |
JSON_MERGE_PATCH() | 合并 JSON 文档,替换重复键的值 | ||
JSON_MERGE_PRESERVE() | 合并 JSON 文档,保留重复的键 | ||
JSON_OBJECT() | 创建 JSON 对象 | ||
JSON_OBJECTAGG() | 将结果集作为单个 JSON 对象返回 | ||
JSON_OVERLAPS() | 比较两个 JSON 文档,如果它们有任何公共键值对或数组元素,则返回 TRUE(1),否则返回 FALSE(0) | 8.0.17 | |
JSON_PRETTY() | 以人类可读的格式打印 JSON 文档 | ||
JSON_QUOTE() | 引用 JSON 文档 | ||
JSON_REMOVE() | 从 JSON 文档中删除数据 | ||
JSON_REPLACE() | 替换 JSON 文档中的值 | ||
JSON_SCHEMA_VALID() | 针对 JSON 模式验证 JSON 文档;如果文档符合模式,则返回 TRUE/1,否则返回 FALSE/0 | 8.0.17 | |
JSON_SCHEMA_VALIDATION_REPORT() | 针对 JSON 模式验证 JSON 文档;返回 JSON 格式的验证结果报告,包括成功或失败以及失败原因 | 8.0.17 | |
JSON_SEARCH() | JSON 文档中值的路径 | ||
JSON_SET() | 将数据插入 JSON 文档 | ||
JSON_STORAGE_FREE() | 部分更新后 JSON 列值的二进制表示中释放的空间 | ||
JSON_STORAGE_SIZE() | 用于存储 JSON 文档的二进制表示的空间 | ||
JSON_TABLE() | 将 JSON 表达式的数据作为关系表返回 | ||
JSON_TYPE() | JSON 值的类型 | ||
JSON_UNQUOTE() | 取消 JSON 值的引号 | ||
JSON_VALID() | JSON 值是否有效 | ||
JSON_VALUE() | 从 JSON 文档中提取路径指向的值;将该值作为 VARCHAR(512) 或指定类型返回 | 8.0.21 | |
LAG() | 分区内当前行后退行的参数值 | ||
LAST_DAY | 返回参数所在月份的最后一天 | ||
LAST_INSERT_ID() | 最后一次 INSERT 的 AUTOINCREMENT 列的值 | ||
LAST_VALUE() | 窗口帧中最后一行的参数值 | ||
LCASE() | LOWER() 的同义词 | ||
LEAD() | 分区内当前行前导行的参数值 | ||
LEAST() | 返回最小的参数 | ||
LEFT() | 返回指定数量的最左侧字符 | ||
LENGTH() | 返回字符串的字节长度 | ||
LIKE | 简单的模式匹配 | ||
LineString() | 从 Point 值构造 LineString | ||
LN() | 返回参数的自然对数 | ||
LOAD_FILE() | 加载指定文件 | ||
LOCALTIME(), LOCALTIME | NOW() 的同义词 | ||
LOCALTIMESTAMP, LOCALTIMESTAMP() | NOW() 的同义词 | ||
LOCATE() | 返回子字符串第一次出现的位置 | ||
LOG() | 返回第一个参数的自然对数 | ||
LOG10() | 返回参数的以 10 为底的对数 | ||
LOG2() | 返回参数的以 2 为底的对数 | ||
LOWER() | 返回小写参数 | ||
LPAD() | 返回左侧填充了指定字符串的字符串参数 | ||
LTRIM() | 移除前导空格 | ||
MAKE_SET() | 返回一组逗号分隔的字符串,其中对应位在位中设置 | ||
MAKEDATE() | 从年份和一年中的天数创建日期 | ||
MAKETIME() | 从小时、分钟、秒创建时间 | ||
MASTER_POS_WAIT() | 阻塞,直到副本读取并应用到指定位置的所有更新 | 8.0.26 | |
MATCH() | 执行全文搜索 | ||
MAX() | 返回最大值 | ||
MBRContains() | 一个几何图形的 MBR 是否包含另一个几何图形的 MBR | ||
MBRCoveredBy() | 一个 MBR 是否被另一个覆盖 | ||
MBRCovers() | 一个 MBR 是否覆盖另一个 | ||
MBRDisjoint() | 两个几何图形的 MBR 是否不相交 | ||
MBREquals() | 两个几何图形的 MBR 是否相等 | ||
MBRIntersects() | 两个几何图形的 MBR 是否相交 | ||
MBROverlaps() | 两个几何图形的 MBR 是否重叠 | ||
MBRTouches() | 两个几何图形的 MBR 是否相接触 | ||
MBRWithin() | 一个几何图形的 MBR 是否在另一个几何图形的 MBR 内部 | ||
MD5() | 计算 MD5 校验和 | ||
MEMBER OF() | 如果第一个操作数与作为第二个操作数传递的 JSON 数组中的任何元素匹配,则返回 true(1),否则返回 false(0) | 8.0.17 | |
MICROSECOND() | 从参数返回微秒 | ||
MID() | 从指定位置开始返回子字符串 | ||
MIN() | 返回最小值 | ||
MINUTE() | 从参数返回分钟 | ||
MOD() | 返回余数 | ||
MONTH() | 返回传递日期的月份 | ||
MONTHNAME() | 返回月份的名称 | ||
MultiLineString() | 从 LineString 值构造多线 | ||
MultiPoint() | 从点值构造多点 | ||
MultiPolygon() | 从多边形值构造多边形 | ||
NAME_CONST() | 使列具有给定名称 | ||
NOT, ! | 反转值 | ||
NOT BETWEEN ... AND ... | 值是否不在一组值的范围内 | ||
NOT IN() | 值是否不在一组值内 | ||
NOT LIKE | 简单模式匹配的否定 | ||
NOT REGEXP | REGEXP 的否定 | ||
NOW() | 返回当前日期和时间 | ||
NTH_VALUE() | 窗口帧的第 N 行参数值 | ||
NTILE() | 当前行在其分区内的桶号 | ||
NULLIF() | 如果 expr1 = expr2 则返回 NULL | ||
OCT() | 返回包含数字的八进制表示的字符串 | ||
OCTET_LENGTH() | LENGTH() 的同义词 | ||
OR, || | 逻辑或 | ||
ORD() | 返回参数的最左字符的字符代码 | ||
PERCENT_RANK() | 百分比排名值 | ||
PERIOD_ADD() | 将一个周期添加到年-月 | ||
PERIOD_DIFF() | 返回两个周期之间的月数 | ||
PI() | 返回圆周率的值 | ||
Point() | 从坐标构造点 | ||
Polygon() | 从 LineString 参数构造多边形 | ||
POSITION() | LOCATE() 的同义词 | ||
POW() | 返回参数的指定幂次方 | ||
POWER() | 返回参数的指定幂次方 | ||
PS_CURRENT_THREAD_ID() | 当前线程的性能模式线程 ID | 8.0.16 | |
PS_THREAD_ID() | 给定线程的性能模式线程 ID | 8.0.16 | |
QUARTER() | 返回日期参数的季度 | ||
QUOTE() | 为在 SQL 语句中使用而转义参数 | ||
RADIANS() | 将参数转换为弧度 | ||
RAND() | 返回一个随机浮点值 | ||
RANDOM_BYTES() | 返回一个随机字节向量 | ||
RANK() | 当前行在其分区内的排名,带有间隔 | ||
REGEXP | 字符串是否匹配正则表达式 | ||
REGEXP_INSTR() | 匹配正则表达式的子字符串的起始索引 | ||
REGEXP_LIKE() | 字符串是否匹配正则表达式 | ||
REGEXP_REPLACE() | 替换匹配正则表达式的子字符串 | ||
REGEXP_SUBSTR() | 返回匹配正则表达式的子字符串 | ||
RELEASE_ALL_LOCKS() | 释放所有当前命名的锁 | ||
RELEASE_LOCK() | 释放命名的锁 | ||
REPEAT() | 将字符串重复指定次数 | ||
REPLACE() | 替换指定字符串的出现次数 | ||
REVERSE() | 反转字符串中的字符 | ||
RIGHT() | 返回指定右侧字符数 | ||
RLIKE | 字符串是否匹配正则表达式 | ||
ROLES_GRAPHML() | 返回表示内存角色子图的 GraphML 文档 | ||
ROUND() | 四舍五入参数 | ||
ROW_COUNT() | 更新的行数 | ||
ROW_NUMBER() | 当前行在其分区内的编号 | ||
RPAD() | 将字符串重复指定次数 | ||
RTRIM() | 移除字符串末尾的空格 | ||
SCHEMA() | DATABASE()的同义词 | ||
SEC_TO_TIME() | 将秒数转换为'hh:mm:ss'格式 | ||
SECOND() | 返回秒数 (0-59) | ||
SESSION_USER() | USER()的同义词 | ||
SHA1(), SHA() | 计算 SHA-1 160 位校验和 | ||
SHA2() | 计算 SHA-2 校验和 | ||
SIGN() | 返回参数的符号 | ||
SIN() | 返回参数的正弦值 | ||
SLEEP() | 休眠指定秒数 | ||
SOUNDEX() | 返回一个 soundex 字符串 | ||
SOUNDS LIKE | 比较音频 | ||
SOURCE_POS_WAIT() | 阻塞直到复制品读取并应用到指定位置的所有更新 | 8.0.26 | |
SPACE() | 返回指定数量的空格字符串 | ||
SQRT() | 返回参数的平方根 | ||
ST_Area() | 返回多边形或多重多边形的面积 | ||
ST_AsBinary(), ST_AsWKB() | 从内部几何格式转换为 WKB | ||
ST_AsGeoJSON() | 从几何体生成 GeoJSON 对象 | ||
ST_AsText(), ST_AsWKT() | 从内部几何格式转换为 WKT | ||
ST_Buffer() | 返回距离给定几何体一定距离内的点的几何体 | ||
ST_Buffer_Strategy() | 为 ST_Buffer()生成策略选项 | ||
ST_Centroid() | 返回几何体的质心点 | ||
ST_Collect() | 将空间值聚合为集合 | 8.0.24 | |
ST_Contains() | 判断一个几何体是否包含另一个 | ||
ST_ConvexHull() | 返回几何体的凸包 | ||
ST_Crosses() | 一个几何体是否穿过另一个 | ||
ST_Difference() | 两个几何体的点集差 | ||
ST_Dimension() | 几何体的维度 | ||
ST_Disjoint() | 一个几何体是否与另一个不相交 | ||
ST_Distance() | 一个几何体到另一个几何体的距离 | ||
ST_Distance_Sphere() | 两个几何体在地球上的最小距离 | ||
ST_EndPoint() | 线串的终点 | ||
ST_Envelope() | 返回几何体的最小边界矩形 | ||
ST_Equals() | 一个几何体是否等于另一个 | ||
ST_ExteriorRing() | 返回多边形的外环 | ||
ST_FrechetDistance() | 一个几何体到另一个几何体的离散 Fréchet 距离 | 8.0.23 | |
ST_GeoHash() | 生成地理哈希值 | ||
ST_GeomCollFromText(), ST_GeometryCollectionFromText(), ST_GeomCollFromTxt() | 从 WKT 返回几何集合 | ||
ST_GeomCollFromWKB(), ST_GeometryCollectionFromWKB() | 从 WKB 返回几何集合 | ||
ST_GeometryN() | 从几何集合中返回第 N 个几何体 | ||
ST_GeometryType() | 返回几何类型的名称 | ||
ST_GeomFromGeoJSON() | 从 GeoJSON 对象生成几何体 | ||
ST_GeomFromText(), ST_GeometryFromText() | 从 WKT 返回几何体 | ||
ST_GeomFromWKB(), ST_GeometryFromWKB() | 从 WKB 返回几何体 | ||
ST_HausdorffDistance() | 一个几何体到另一个几何体的离散豪斯多夫距离 | 8.0.23 | |
ST_InteriorRingN() | 返回多边形的第 N 个内环 | ||
ST_Intersection() | 返回两个几何体的点集交集 | ||
ST_Intersects() | 判断一个几何体是否与另一个相交 | ||
ST_IsClosed() | 判断几何体是否封闭且简单 | ||
ST_IsEmpty() | 判断几何体是否为空 | ||
ST_IsSimple() | 判断几何体是否简单 | ||
ST_IsValid() | 判断几何体是否有效 | ||
ST_LatFromGeoHash() | 从 geohash 值返回纬度 | ||
ST_Latitude() | 返回 Point 的纬度 | 8.0.12 | |
ST_Length() | 返回 LineString 的长度 | ||
ST_LineFromText(), ST_LineStringFromText() | 从 WKT 构建 LineString | ||
ST_LineFromWKB(), ST_LineStringFromWKB() | 从 WKB 构建 LineString | ||
ST_LineInterpolatePoint() | 沿着 LineString 给定百分比的点 | 8.0.24 | |
ST_LineInterpolatePoints() | 沿着 LineString 给定百分比的点 | 8.0.24 | |
ST_LongFromGeoHash() | 从 geohash 值返回经度 | ||
ST_Longitude() | 返回 Point 的经度 | 8.0.12 | |
ST_MakeEnvelope() | 两点围成的矩形 | ||
ST_MLineFromText(), ST_MultiLineStringFromText() | 从 WKT 构建 MultiLineString | ||
ST_MLineFromWKB(), ST_MultiLineStringFromWKB() | 从 WKB 构建 MultiLineString | ||
ST_MPointFromText(), ST_MultiPointFromText() | 从 WKT 构建 MultiPoint | ||
ST_MPointFromWKB(), ST_MultiPointFromWKB() | 从 WKB 构建 MultiPoint | ||
ST_MPolyFromText(), ST_MultiPolygonFromText() | 从 WKT 构建 MultiPolygon | ||
ST_MPolyFromWKB(), ST_MultiPolygonFromWKB() | 从 WKB 构建 MultiPolygon | ||
ST_NumGeometries() | 返回几何集合中的几何图形数量 | ||
ST_NumInteriorRing(), ST_NumInteriorRings() | 返回多边形中的内部环数量 | ||
ST_NumPoints() | 返回线串中的点数 | ||
ST_Overlaps() | 一个几何图形是否与另一个重叠 | ||
ST_PointAtDistance() | 沿着线串给定距离的点 | 8.0.24 | |
ST_PointFromGeoHash() | 将 geohash 值转换为 POINT 值 | ||
ST_PointFromText() | 从 WKT 构造点 | ||
ST_PointFromWKB() | 从 WKB 构造点 | ||
ST_PointN() | 返回线串中第 N 个点 | ||
ST_PolyFromText(), ST_PolygonFromText() | 从 WKT 构造多边形 | ||
ST_PolyFromWKB(), ST_PolygonFromWKB() | 从 WKB 构造多边形 | ||
ST_Simplify() | 返回简化后的几何图形 | ||
ST_SRID() | 返回几何图形的空间参考系统 ID | ||
ST_StartPoint() | 线串的起始点 | ||
ST_SwapXY() | 返回 X/Y 坐标交换的参数 | ||
ST_SymDifference() | 返回两个几何图形的点集对称差 | ||
ST_Touches() | 一个几何图形是否与另一个相接触 | ||
ST_Transform() | 转换几何图形的坐标 | 8.0.13 | |
ST_Union() | 返回两个几何图形的点集并集 | ||
ST_Validate() | 返回经过验证的几何图形 | ||
ST_Within() | 一个几何图形是否在另一个内部 | ||
ST_X() | 返回点的 X 坐标 | ||
ST_Y() | 返回点的 Y 坐标 | ||
STATEMENT_DIGEST() | 计算语句摘要哈希值 | ||
STATEMENT_DIGEST_TEXT() | 计算规范化语句摘要 | ||
STD() | 返回总体标准偏差 | ||
STDDEV() | 返回总体标准偏差 | ||
STDDEV_POP() | 返回总体标准偏差 | ||
STDDEV_SAMP() | 返回样本标准偏差 | ||
STR_TO_DATE() | 将字符串转换为日期 | ||
STRCMP() | 比较两个字符串 | ||
SUBDATE() | 在使用三个参数调用时,DATE_SUB()的同义词 | ||
SUBSTR() | 返回指定的子字符串 | ||
SUBSTRING() | 返回指定的子字符串 | ||
SUBSTRING_INDEX() | 返回指定分隔符出现次数之前的字符串子串 | ||
SUBTIME() | 减去时间 | ||
SUM() | 返回总和 | ||
SYSDATE() | 返回函数执行时的时间 | ||
SYSTEM_USER() | USER()的同义词 | ||
TAN() | 返回参数的正切 | ||
TIME() | 提取传递表达式的时间部分 | ||
TIME_FORMAT() | 格式化为时间 | ||
TIME_TO_SEC() | 返回转换为秒的参数 | ||
TIMEDIFF() | 减去时间 | ||
TIMESTAMP() | 使用单个参数,此函数返回日期或日期时间表达式;使用两个参数,返回参数的总和 | ||
TIMESTAMPADD() | 将间隔添加到日期时间表达式 | ||
TIMESTAMPDIFF() | 返回两个日期时间表达式的差异,使用指定的单位 | ||
TO_BASE64() | 返回转换为 base-64 字符串的参数 | ||
TO_DAYS() | 返回转换为天数的日期参数 | ||
TO_SECONDS() | 返回自公元 0 年以来的秒数转换为日期或日期时间参数 | ||
TRIM() | 移除前导和尾随空格 | ||
TRUNCATE() | 截断到指定的小数位数 | ||
UCASE() | UPPER()的同义词 | ||
UNCOMPRESS() | 解压缩压缩的字符串 | ||
UNCOMPRESSED_LENGTH() | 返回压缩前字符串的长度 | ||
UNHEX() | 返回包含数字的十六进制表示的字符串 | ||
UNIX_TIMESTAMP() | 返回 Unix 时间戳 | ||
UpdateXML() | 返回替换的 XML 片段 | ||
UPPER() | 转换为大写 | ||
USER() | 客户端提供的用户名和主机名 | ||
UTC_DATE() | 返回当前的 UTC 日期 | ||
UTC_TIME() | 返回当前的 UTC 时间 | ||
UTC_TIMESTAMP() | 返回当前的 UTC 日期和时间 | ||
UUID() | 返回通用唯一标识符(UUID) | ||
UUID_SHORT() | 返回整数值通用标识符 | ||
UUID_TO_BIN() | 将字符串 UUID 转换为二进制 | ||
VALIDATE_PASSWORD_STRENGTH() | 确定密码强度 | ||
VALUES() | 定义在 INSERT 期间要使用的值 | ||
VAR_POP() | 返回总体标准方差 | ||
VAR_SAMP() | 返回样本方差 | ||
VARIANCE() | 返回总体标准方差 | ||
VERSION() | 返回指示 MySQL 服务器版本的字符串 | ||
WAIT_FOR_EXECUTED_GTID_SET() | 等待副本上执行给定的 GTIDs。 | ||
WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS() | 使用 WAIT_FOR_EXECUTED_GTID_SET()。 | 8.0.18 | |
WEEK() | 返回周数 | ||
WEEKDAY() | 返回星期索引 | ||
WEEKOFYEAR() | 返回日期的日历周数(1-53) | ||
WEIGHT_STRING() | 返回字符串的权重字符串 | ||
XOR | 逻辑异或 | ||
YEAR() | 返回年份 | ||
YEARWEEK() | 返回年份和周数 | ||
| | 按位或 | ||
~ | 按位取反 | ||
| 名称 | 描述 | 引入版本 | 废弃版本 |