MySQL8-中文参考-二十一-
MySQL8 中文参考(二十一)
14.2 可加载函数参考
原文:
dev.mysql.com/doc/refman/8.0/en/loadable-function-reference.html
下表列出了每个可在运行时加载的函数,并提供了每个函数的简短描述。有关列出内置函数和运算符的表格,请参见第 14.1 节,“内置函数和运算符参考”
有关可加载函数的一般信息,请参见第 7.7 节,“MySQL 服务器可加载函数”。
表 14.2 可加载函数
名称 | 描述 | 引入版本 | 废弃版本 |
---|---|---|---|
asymmetric_decrypt() |
使用私钥或公钥解密密文 | ||
asymmetric_derive() |
从非对称密钥派生对称密钥 | ||
asymmetric_encrypt() |
使用私钥或公钥加密明文 | ||
asymmetric_sign() |
从摘要生成签名 | ||
asymmetric_verify() |
验证签名是否匹配摘要 | ||
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 | |
audit_api_message_emit_udf() |
向审计日志添加消息事件 | ||
audit_log_encryption_password_get() |
获取审计日志加密密码 | ||
audit_log_encryption_password_set() |
设置审计日志加密密码 | ||
audit_log_filter_flush() |
刷新审计日志过滤表 | ||
audit_log_filter_remove_filter() |
移除审计日志过滤器 | ||
audit_log_filter_remove_user() |
从用户中取消分配审计日志过滤器 | ||
audit_log_filter_set_filter() |
定义审计日志过滤器 | ||
audit_log_filter_set_user() |
为用户分配审计日志过滤器 | ||
audit_log_read() |
返回审计日志记录 | ||
audit_log_read_bookmark() |
最近审计日志事件的书签 | ||
audit_log_rotate() |
旋转审计日志文件 | ||
create_asymmetric_priv_key() |
创建私钥 | ||
create_asymmetric_pub_key() |
创建公钥 | ||
create_dh_parameters() |
生成共享 DH 密钥 | ||
create_digest() |
从字符串生成摘要 | ||
firewall_group_delist() |
从防火墙组配置文件中移除帐户 | 8.0.23 | |
firewall_group_enlist() |
将帐户添加到防火墙组配置文件 | 8.0.23 | |
flush_rewrite_rules() |
将 rewrite_rules 表加载到 Rewriter 缓存中 | ||
gen_blacklist() |
执行字典术语替换 | 8.0.23 | |
gen_blocklist() |
执行字典术语替换 | 8.0.33 | |
gen_blocklist() |
执行字典术语替换 | 8.0.23 | |
gen_dictionary() |
从字典中返回随机术语 | 8.0.33 | |
gen_dictionary_drop() |
从注册表中移除字典 | ||
gen_dictionary_load() |
将字典加载到注册表中 | ||
gen_dictionary() |
从字典中返回随机术语 | ||
gen_range() |
在范围内生成随机数 | 8.0.33 | |
gen_range() |
在范围内生成随机数 | ||
gen_rnd_canada_sin() |
生成随机加拿大社会保险号码 | 8.0.33 | |
gen_rnd_email() |
生成随机电子邮件地址 | 8.0.33 | |
gen_rnd_email() |
生成随机电子邮件地址 | ||
gen_rnd_iban() |
生成随机国际银行帐号 | 8.0.33 | |
gen_rnd_pan() |
生成随机支付卡主帐号 | 8.0.33 | |
gen_rnd_pan() |
生成随机支付卡主帐号 | ||
gen_rnd_ssn() |
生成随机美国社会安全号码 | 8.0.33 | |
gen_rnd_ssn() |
生成随机美国社会安全号码 | ||
gen_rnd_uk_nin() |
生成随机英国国民保险号码 | 8.0.33 | |
gen_rnd_us_phone() |
生成随机美国电话号码 | 8.0.33 | |
gen_rnd_us_phone() |
生成随机美国电话号码 | ||
gen_rnd_uuid() |
生成随机通用唯一标识符 | 8.0.33 | |
group_replication_disable_member_action() |
启用成员操作,使成员在指定情况下不执行 | ||
group_replication_enable_member_action() |
在指定情况下启用成员操作 | ||
group_replication_get_communication_protocol() |
返回 Group Replication 协议版本 | ||
group_replication_get_write_concurrency() |
返回可并行执行的最大共识实例数 | ||
group_replication_reset_member_actions() |
将成员操作配置重置为默认设置 | ||
group_replication_set_as_primary() |
将组成员指定为新主 | ||
group_replication_set_communication_protocol() |
设置组复制协议版本 | ||
group_replication_set_write_concurrency() |
设置可以并行执行的最大一致性实例数 | ||
group_replication_switch_to_multi_primary_mode() |
将组从单主模式切换到多主模式 | ||
group_replication_switch_to_single_primary_mode() |
将组从多主模式切换到单主模式 | ||
keyring_aws_rotate_cmk() |
旋转 AWS 客户主密钥 | ||
keyring_aws_rotate_keys() |
旋转 keyring_aws 存储文件中的钥匙 | ||
keyring_hashicorp_update_config() |
导致运行时 keyring_hashicorp 重新配置 | ||
keyring_key_fetch() |
获取钥匙环钥匙值 | ||
keyring_key_generate() |
生成随机钥匙环钥匙 | ||
keyring_key_length_fetch() |
返回钥匙环钥匙长度 | ||
keyring_key_remove() |
移除钥匙环钥匙 | ||
keyring_key_store() |
在钥匙环中存储钥匙 | ||
keyring_key_type_fetch() |
返回钥匙环钥匙类型 | ||
load_rewrite_rules() |
重写插件辅助例程 | ||
mask_canada_sin() |
遮蔽加拿大社会保险号码 | 8.0.33 | |
mask_iban() |
遮蔽国际银行账号 | 8.0.33 | |
mask_inner() |
遮蔽字符串的内部部分 | 8.0.33 | |
mask_inner() |
遮蔽字符串的内部部分 | ||
mask_outer() |
遮蔽字符串的左右部分 | 8.0.33 | |
mask_outer() |
遮蔽字符串的左右部分 | ||
mask_pan() |
遮蔽支付卡主帐号部分字符串 | 8.0.33 | |
mask_pan() |
遮蔽支付卡主帐号部分字符串 | ||
mask_pan_relaxed() |
遮蔽支付卡主帐号部分字符串 | 8.0.33 | |
mask_pan_relaxed() |
遮蔽支付卡主帐号部分字符串 | ||
mask_ssn() |
遮蔽美国社会安全号码 | 8.0.33 | |
mask_ssn() |
遮蔽美国社会安全号码 | ||
mask_uk_nin() |
遮蔽英国国民保险号码 | 8.0.33 | |
mask_uuid() |
遮蔽字符串的通用唯一标识符部分 | 8.0.33 | |
masking_dictionary_remove() |
从数据库表中删除字典 | 8.0.33 | |
masking_dictionary_term_add() |
向字典中添加新术语 | 8.0.33 | |
masking_dictionary_term_remove() |
从字典中删除现有术语 | 8.0.33 | |
mysql_firewall_flush_status() |
重置防火墙状态变量 | ||
mysql_query_attribute_string() |
获取查询属性值 | 8.0.23 | |
normalize_statement() |
将 SQL 语句规范化为摘要形式 | ||
read_firewall_group_allowlist() |
更新防火墙组配置文件记录语句缓存 | 8.0.23 | |
read_firewall_groups() |
更新防火墙组配置文件缓存 | 8.0.23 | |
read_firewall_users() |
更新防火墙账户配置文件缓存 | 8.0.26 | |
read_firewall_whitelist() |
更新防火墙账户配置文件记录语句缓存 | 8.0.26 | |
service_get_read_locks() |
获取锁定服务共享锁 | ||
service_get_write_locks() |
获取锁定服务独占锁 | ||
service_release_locks() |
释放锁定服务锁 | ||
set_firewall_group_mode() |
建立防火墙组配置操作模式 | 8.0.23 | |
set_firewall_mode() |
建立防火墙账户配置操作模式 | 8.0.26 | |
version_tokens_delete() |
从版本令牌列表中删除令牌 | ||
version_tokens_edit() |
修改版本令牌列表 | ||
version_tokens_lock_exclusive() |
获取版本令牌的独占锁 | ||
version_tokens_lock_shared() |
获取版本令牌的共享锁 | ||
version_tokens_set() |
设置版本令牌列表 | ||
version_tokens_show() |
返回版本令牌列表 | ||
version_tokens_unlock() |
释放版本令牌锁 | ||
名称 | 描述 | 引入版本 | 废弃版本 |
14.3 表达式求值中的类型转换
当使用具有不同类型操作数的运算符时,会发生类型转换以使操作数兼容。一些转换会隐式发生。例如,MySQL 会根据需要自动将字符串转换为数字,反之亦然。
mysql> SELECT 1+'1';
-> 2
mysql> SELECT CONCAT(2,' test');
-> '2 test'
也可以使用CAST()
函数将数字显式转换为字符串。使用CONCAT()
函数时会隐式进行转换,因为它期望字符串参数。
mysql> SELECT 38.8, CAST(38.8 AS CHAR);
-> 38.8, '38.8'
mysql> SELECT 38.8, CONCAT(38.8);
-> 38.8, '38.8'
请参阅本节后面有关隐式数字到字符串转换的字符集信息,以及适用于CREATE TABLE ... SELECT
语句的修改规则。
以下规则描述了比较操作的转换方式:
-
如果一个或两个参数为
NULL
,则比较的结果为NULL
,除了NULL
安全的<=>
等于比较运算符。对于NULL <=> NULL
,结果为真。不需要转换。 -
如果比较操作中的两个参数都是字符串,则将它们作为字符串进行比较。
-
如果两个参数都是整数,则将它们作为整数进行比较。
-
如果十六进制值与数字进行比较,则将其视为二进制字符串。
-
如果其中一个参数是
TIMESTAMP
或DATETIME
列,另一个参数是常量,则在执行比较之前将常量转换为时间戳。这样做是为了更符合 ODBC 标准。但对于IN()
的参数不会执行此操作。为了安全起见,在进行比较时,始终使用完整的日期、日期或时间字符串。例如,当使用BETWEEN
与日期或时间值时,使用CAST()
将值显式转换为所需的数据类型以获得最佳结果。来自表或表的单行子查询不被视为常量。例如,如果子查询返回一个整数用于与
DATETIME
值进行比较,则比较将作为两个整数进行。整数不会转换为时间值。要将操作数作为DATETIME
值进行比较,请使用CAST()
将子查询值显式转换为DATETIME
。 -
如果其中一个参数是十进制值,则比较取决于另一个参数。如果另一个参数是十进制或整数值,则将参数作为十进制值进行比较,如果另一个参数是浮点值,则将参数作为浮点值进行比较。
-
在所有其他情况下,参数将作为浮点(双精度)数进行比较。例如,字符串和数字操作数的比较将作为浮点数的比较进行。
有关从一种时间类型转换为另一种时间类型的值的转换信息,请参见第 13.2.8 节,“日期和时间类型之间的转换”。
JSON 值的比较分为两个级别。第一级别的比较基于比较值的 JSON 类型。如果类型不同,则比较结果仅由具有更高优先级的类型确定。如果两个值具有相同的 JSON 类型,则使用特定于类型的规则进行第二级别的比较。对于 JSON 和非 JSON 值的比较,将非 JSON 值转换为 JSON,然后将值作为 JSON 值进行比较。有关详细信息,请参见 JSON 值的比较和排序。
以下示例说明了将字符串转换为数字进行比较操作:
mysql> SELECT 1 > '6x';
-> 0
mysql> SELECT 7 > '6x';
-> 1
mysql> SELECT 0 > 'x6';
-> 0
mysql> SELECT 0 = 'x6';
-> 1
对于字符串列与数字的比较,MySQL 无法使用列上的索引快速查找值。如果str_col
是一个带索引的字符串列,在执行以下语句中进行查找时,索引将无法使用:
SELECT * FROM *tbl_name* WHERE *str_col*=1;
这是因为有许多不同的字符串可能转换为值1
,比如'1'
,' 1'
或'1a'
。
浮点数和大整数类型的比较是近似的,因为在比较之前整数被转换为双精度浮点数,而双精度浮点数无法精确表示所有 64 位整数。例如,整数值 2⁵³ + 1 无法表示为浮点数,在浮点比较之前会被四舍五入为 2⁵³或 2⁵³ + 2,具体取决于平台。
仅以以下比较中的第一个比较相等的值,但两个比较都返回 true(1):
mysql> SELECT '9223372036854775807' = 9223372036854775807;
-> 1
mysql> SELECT '9223372036854775807' = 9223372036854775806;
-> 1
当从字符串到浮点数和从整数到浮点数的转换发生时,它们不一定以相同的方式发生。整数可能由 CPU 转换为浮点数,而字符串则通过涉及浮点数乘法的操作逐位转换。此外,结果可能受到诸如计算机架构、编译器版本或优化级别等因素的影响。避免此类问题的一种方法是使用CAST()
以便值不会隐式转换为浮点数:
mysql> SELECT CAST('9223372036854775807' AS UNSIGNED) = 9223372036854775806;
-> 0
有关浮点比较的更多信息,请参见第 B.3.4.8 节,“浮点值的问题”。
服务器包含dtoa
,一个转换库,提供了在字符串或DECIMAL
- DECIMAL, NUMERIC")值和近似值(FLOAT
- FLOAT, DOUBLE")/DOUBLE
- FLOAT, DOUBLE"))之间改进转换的基础:
-
跨平台的一致转换结果,消除了 Unix 与 Windows 转换差异,例如。
-
在以前结果未提供足够精度的情况下准确表示值,例如接近 IEEE 极限的值。
-
将数字转换为具有最佳可能精度的字符串格式。
dtoa
的精度始终与标准 C 库函数相同或更好。
由于此库产生的转换在某些情况下与非dtoa
结果不同,因此存在应用程序不兼容的潜在可能性,这些应用程序依赖于以前的结果。例如,依赖于以前转换的特定精确结果的应用程序可能需要调整以适应额外的精度。
dtoa
库提供了以下属性的转换。D
表示具有DECIMAL
- DECIMAL, NUMERIC")或字符串表示的值,F
表示本机二进制(IEEE)格式的浮点数。
-
F
->D
转换是以最佳可能精度进行的,返回D
作为最短字符串,当读回并按 IEEE 指定的本机二进制格式四舍五入到最接近的值时,会产生F
。 -
D
->F
转换是这样进行的,使得F
是输入十进制字符串D
最接近的本机二进制数。
这些属性意味着 F
-> D
-> F
转换是无损失的,除非 F
是 -inf
,+inf
或 NaN
。后三个值不受支持,因为 SQL 标准将它们定义为FLOAT
- FLOAT, DOUBLE")或DOUBLE
- FLOAT, DOUBLE")的无效值。
对于 D
-> F
-> D
转换,无损失的一个充分条件是 D
使用 15 位或更少的精度,不是非规格化值,也不是 -inf
,+inf
或 NaN
。在某些情况下,即使 D
的精度超过 15 位,转换也是无损失的,但并非总是如此。
将数值或时间值隐式转换为字符串会产生一个具有由character_set_connection
和collation_connection
系统变量确定的字符集和排序规则的值。(这些变量通常使用SET NAMES
设置。有关连接字符集的信息,请参见第 12.4 节,“连接字符集和排序规则”。)
这意味着这样的转换会产生一个字符(非二进制)字符串(一个CHAR
、VARCHAR
或LONGTEXT
值),除非连接字符集设置为binary
。在这种情况下,转换结果是一个二进制字符串(一个BINARY
、VARBINARY
或LONGBLOB
值)。
对于整数表达式,关于表达式评估的前述备注在表达式赋值方面有所不同;例如,在这样的语句中:
CREATE TABLE t SELECT *integer_expr*;
在这种情况下,由表达式生成的列中的表具有INT
- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT")或BIGINT
- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT")类型,具体取决于整数表达式的长度。如果表达式的最大长度不适合INT
- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"),则改用BIGINT
- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT")。长度取自SELECT
结果集元数据的max_length
值(参见 C API 基本数据结构)。这意味着您可以通过使用足够长的表达式来强制使用BIGINT
- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT")而不是INT
- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"):
CREATE TABLE t SELECT 000000000000000000000;
14.4 操作符
14.4.1 操作符优先级
14.4.2 比较函数和操作符
14.4.3 逻辑操作符
14.4.4 赋值操作符
表格 14.3 操作符
名称 | 描述 | 引入版本 | 废弃版本 |
---|---|---|---|
& |
按位与 | ||
> |
大于操作符 | ||
>> |
右移操作符 | ||
>= |
大于等于操作符 | ||
< |
小于操作符 | ||
<> , != |
不等于操作符 | ||
<< |
左移操作符 | ||
<= |
小于等于操作符 | ||
<=> |
NULL 安全等于操作符 | ||
% , MOD |
取模操作符 | ||
* |
乘法操作符 | ||
+ |
加法操作符 | ||
- |
减法操作符 | ||
- |
改变参数的符号 | ||
-> |
在评估路径后从 JSON 列返回值;相当于 JSON_EXTRACT()。 | ||
->> |
在评估路径并取消引用结果后从 JSON 列返回值;相当于 JSON_UNQUOTE(JSON_EXTRACT())。 | ||
/ |
除法操作符 | ||
:= |
赋值操作符 | ||
= |
赋值操作符(作为 SET 语句的一部分,或作为 UPDATE 语句中的 SET 子句的一部分) |
||
= |
等于操作符 | ||
^ |
按位异或 | ||
AND , && |
逻辑与 | ||
BETWEEN ... AND ... |
判断一个值是否在一系列值范围内 | ||
BINARY |
将字符串转换为二进制字符串 | 8.0.27 | |
CASE |
Case 操作符 | ||
DIV |
整数除法 | ||
IN() |
值是否在一组值内 | ||
IS |
测试值是否为布尔值 | ||
IS NOT |
测试值是否为布尔值 | ||
IS NOT NULL |
非空值测试 | ||
IS NULL |
空值测试 | ||
LIKE |
简单模式匹配 | ||
MEMBER OF() |
如果第一个操作数匹配作为第二个操作数传递的 JSON 数组的任何元素,则返回 true (1),否则返回 false (0) | 8.0.17 | |
NOT , ! |
取反值 | ||
NOT BETWEEN ... AND ... |
值是否不在一系列值范围内 | ||
NOT IN() |
值是否不在一组值内 | ||
NOT LIKE |
简单模式匹配的否定 | ||
NOT REGEXP |
REGEXP 的否定 | ||
OR , || |
逻辑或 | ||
REGEXP |
字符串是否匹配正则表达式 | ||
RLIKE |
字符串是否匹配正则表达式 | ||
SOUNDS LIKE |
比较声音 | ||
XOR |
逻辑异或 | ||
| |
按位或 | ||
~ |
按位取反 | ||
Name | 描述 | 引入 | 废弃 |
14.4.1 运算符优先级
运算符优先级按照以下列表从最高优先级到最低优先级显示。在同一行上显示在一起的运算符具有相同的优先级。
INTERVAL
BINARY, COLLATE
!
- (unary minus), ~ (unary bit inversion)
^
*, /, DIV, %, MOD
-, +
<<, >>
&
|
= (comparison), <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN, MEMBER OF
BETWEEN, CASE, WHEN, THEN, ELSE
NOT
AND, &&
XOR
OR, ||
= (assignment), :=
=
的优先级取决于它是作为比较运算符(=
)还是作为赋值运算符(=
)使用。当作为比较运算符使用时,它与<=>
、>=
、>
、<=
、<
、<>
、!=
、IS
、LIKE
、REGEXP
和IN()
具有相同的优先级。当作为赋值运算符使用时,它与:=
具有相同的优先级。“变量赋值的 SET 语法”和“用户定义变量”部分解释了 MySQL 如何确定应该应用哪种=
的解释。
对于在表达式中具有相同优先级的运算符,计算从左到右进行,但赋值运算符的计算是从右到左进行。
一些运算符的优先级和含义取决于 SQL 模式:
-
默认情况下,
||
是逻辑OR
运算符。启用PIPES_AS_CONCAT
后,||
是字符串连接运算符,优先级介于^
和一元运算符之间。 -
默认情况下,
!
的优先级高于NOT
。启用HIGH_NOT_PRECEDENCE
后,!
和NOT
具有相同的优先级。
参见“服务器 SQL 模式”第 7.1.11 节。
运算符的优先级确定了表达式中项的计算顺序。要覆盖这个顺序并显式地分组项,请使用括号。例如:
mysql> SELECT 1+2*3;
-> 7
mysql> SELECT (1+2)*3;
-> 9
14.4.2 比较函数和运算符
原文:
dev.mysql.com/doc/refman/8.0/en/comparison-operators.html
表 14.4 比较运算符
名称 | 描述 |
---|---|
> |
大于运算符 |
>= |
大于或等于运算符 |
< |
小于运算符 |
<> , != |
不等运算符 |
<= |
小于或等于运算符 |
<=> |
NULL 安全等于运算符 |
= |
等于运算符 |
BETWEEN ... AND ... |
值是否在一系列值范围内 |
COALESCE() |
返回第一个非 NULL 参数 |
GREATEST() |
返回最大的参数 |
IN() |
值是否在一组值内 |
INTERVAL() |
返回小于第一个参数的参数的索引 |
IS |
测试值是否为布尔值 |
IS NOT |
测试值是否为布尔值 |
IS NOT NULL |
非 NULL 值测试 |
IS NULL |
NULL 值测试 |
ISNULL() |
测试参数是否为 NULL |
LEAST() |
返回最小的参数 |
LIKE |
简单的模式匹配 |
NOT BETWEEN ... AND ... |
值是否不在一系列值范围内 |
NOT IN() |
值是否不在一组值内 |
NOT LIKE |
简单模式匹配的否定 |
STRCMP() |
比较两个字符串 |
名称 | 描述 |
比较操作的结果为1
(TRUE
)、0
(FALSE
)或NULL
。这些操作适用于数字和字符串。字符串会根据需要自动转换为数字,数字也会转换为字符串。
下列关系比较运算符可用于比较标量操作数以及行操作数:
= > < >= <= <> !=
本节后面对这些运算符的描述详细说明了它们如何与行操作数一起工作。有关在行子查询上下文中的行比较的其他示例,请参见第 15.2.15.5 节,“行子查询”。
本节中的一些函数返回除1
(TRUE
)、0
(FALSE
)或NULL
之外的值。LEAST()
和GREATEST()
就是这样的函数的例子;第 14.3 节,“表达式评估中的类型转换”描述了这些函数执行比较操作以确定它们的返回值的规则。
注意
在 MySQL 的早期版本中,当评估包含LEAST()
或GREATEST()
的表达式时,服务器尝试猜测函数的使用上下文,并将函数的参数强制转换为整个表达式的数据类型。例如,对于LEAST("11", "45", "2")
的参数将作为字符串进行评估和排序,因此该表达式返回"11"
。在 MySQL 8.0.3 及更早版本中,当评估表达式LEAST("11", "45", "2") + 0
时,服务器在对其进行排序之前将参数转换为整数(预期将整数 0 添加到结果),从而返回 2。
从 MySQL 8.0.4 开始,服务器不再尝试以这种方式推断上下文。相反,函数将使用提供的参数执行,仅在它们不全为相同类型时对一个或多个参数执行数据类型转换。现在,任何使用返回值的表达式强制执行的类型强制转换都是在函数执行后执行的。这意味着,在 MySQL 8.0.4 及更高版本中,LEAST("11", "45", "2") + 0
计算为"11" + 0
,因此为整数 11。 (Bug #83895, Bug #25123839)
要将值转换为特定类型以进行比较,可以使用CAST()
函数。字符串值可以使用CONVERT()
将其转换为不同的字符集。参见第 14.10 节,“转换函数和运算符”。
默认情况下,字符串比较不区分大小写,并使用当前字符集。默认为utf8mb4
。
-
=
等于:
mysql> SELECT 1 = 0; -> 0 mysql> SELECT '0' = 0; -> 1 mysql> SELECT '0.0' = 0; -> 1 mysql> SELECT '0.01' = 0; -> 0 mysql> SELECT '.01' = 0.01; -> 1
对于行比较,
(a, b) = (x, y)
等同于:(a = x) AND (b = y)
-
<=>
NULL
-安全等于。此运算符执行类似于=
运算符的相等比较,但如果两个操作数都为NULL
,则返回1
而不是NULL
,如果一个操作数为NULL
,则返回0
而不是NULL
。<=>
运算符等同于标准 SQL 的IS NOT DISTINCT FROM
运算符。mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL; -> 1, 1, 0 mysql> SELECT 1 = 1, NULL = NULL, 1 = NULL; -> 1, NULL, NULL
对于行比较,
(a, b) <=> (x, y)
等同于:(a <=> x) AND (b <=> y)
-
<>
,!=
不等于:
mysql> SELECT '.01' <> '0.01'; -> 1 mysql> SELECT .01 <> '0.01'; -> 0 mysql> SELECT 'zapp' <> 'zappp'; -> 1
对于行比较,
(a, b) <> (x, y)
和(a, b) != (x, y)
等同于:(a <> x) OR (b <> y)
-
<=
小于或等于:
mysql> SELECT 0.1 <= 2; -> 1
对于行比较,
(a, b) <= (x, y)
等同于:(a < x) OR ((a = x) AND (b <= y))
-
<
小于:
mysql> SELECT 2 < 2; -> 0
对于行比较,
(a, b) < (x, y)
等同于:(a < x) OR ((a = x) AND (b < y))
-
>=
大于或等于:
mysql> SELECT 2 >= 2; -> 1
对于行比较,
(a, b) >= (x, y)
等同于:(a > x) OR ((a = x) AND (b >= y))
-
>
大于:
mysql> SELECT 2 > 2; -> 0
对于行比较,
(a, b) > (x, y)
等同于:(a > x) OR ((a = x) AND (b > y))
-
*
expr* BETWEEN *
min* AND *
max*
如果
expr
大于或等于min
且expr
小于或等于max
,BETWEEN
返回1
,否则返回0
。如果所有参数类型相同,则这等同于表达式(*
min* <= *
expr* AND *
expr* <= *
max*)
。否则,根据第 14.3 节,“表达式求值中的类型转换”中描述的规则进行类型转换,但应用于所有三个参数。mysql> SELECT 2 BETWEEN 1 AND 3, 2 BETWEEN 3 and 1; -> 1, 0 mysql> SELECT 1 BETWEEN 2 AND 3; -> 0 mysql> SELECT 'b' BETWEEN 'a' AND 'c'; -> 1 mysql> SELECT 2 BETWEEN 2 AND '3'; -> 1 mysql> SELECT 2 BETWEEN 2 AND 'x-3'; -> 0
对于使用
BETWEEN
与日期或时间值时,最佳结果是使用CAST()
显式将值转换为所需的数据类型。例如:如果要比较一个DATETIME
与两个DATE
值,将DATE
值转换为DATETIME
值。如果在与DATE
比较中使用字符串常量如'2001-1-1'
,则将字符串转换为DATE
。 -
*
expr* NOT BETWEEN *
min* AND *
max*
这与
NOT (*
expr* BETWEEN *
min* AND *
max*)
相同。 -
COALESCE(*
value*,...)
返回列表中第一个非
NULL
值,如果没有非NULL
值则返回NULL
。COALESCE()
的返回类型是参数类型的聚合类型。mysql> SELECT COALESCE(NULL,1); -> 1 mysql> SELECT COALESCE(NULL,NULL,NULL); -> NULL
-
GREATEST(*
value1*,*
value2*,...)
有两个或更多参数时,返回最大值的参数。参数使用与
LEAST()
相同的规则进行比较。mysql> SELECT GREATEST(2,0); -> 2 mysql> SELECT GREATEST(34.0,3.0,5.0,767.0); -> 767.0 mysql> SELECT GREATEST('B','A','C'); -> 'C'
GREATEST()
如果任何参数为NULL
,则返回NULL
。 -
*
expr* IN (*
value*,...)
如果
expr
等于IN()
列表中的任何一个值,则返回1
(true),否则返回0
(false)。根据第 14.3 节,“表达式评估中的类型转换”中描述的规则进行类型转换,应用于所有参数。如果
IN()
列表中的值不需要类型转换,它们都是相同类型的非JSON
常量,并且expr
可以与它们中的每一个作为相同类型的值进行比较(可能经过类型转换),则会进行优化。列表中的值被排序,使用二分查找来搜索expr
,使得IN()
操作非常快速。mysql> SELECT 2 IN (0,3,5,7); -> 0 mysql> SELECT 'wefwf' IN ('wee','wefwf','weg'); -> 1
IN()
可以用于比较行构造:mysql> SELECT (3,4) IN ((1,2), (3,4)); -> 1 mysql> SELECT (3,4) IN ((1,2), (3,5)); -> 0
永远不要在
IN()
列表中混合引号和非引号值,因为引号值(如字符串)和非引号值(如数字)的比较规则不同。因此,混合类型可能导致不一致的结果。例如,不要像这样编写IN()
表达式:SELECT val1 FROM tbl1 WHERE val1 IN (1,2,'a');
相反,应该这样写:
SELECT val1 FROM tbl1 WHERE val1 IN ('1','2','a');
隐式类型转换可能会产生令人费解的结果:
mysql> SELECT 'a' IN (0), 0 IN ('b'); -> 1, 1
在这两种情况下,比较值被转换为浮点值,每种情况下均产生 0.0,并且比较结果为 1(true)。
IN()
列表中的值的数量仅受max_allowed_packet
值的限制。为了符合 SQL 标准,
IN()
不仅在左侧表达式为NULL
时返回NULL
,而且在列表中找不到匹配项且列表中的一个表达式为NULL
时也返回NULL
。IN()
语法也可以用于编写某些类型的子查询。请参见第 15.2.15.3 节,“带有 ANY、IN 或 SOME 的子查询”。 -
*
expr* NOT IN (*
value*,...)
这与
NOT (*
expr* IN (*
value*,...))
相同。 -
INTERVAL(*
N*,*
N1*,*
N2*,*
N3*,...)
如果
N
≤N1
,则返回0
,如果N
≤N2
等等,或者如果N
为NULL
,则返回-1
。所有参数都被视为整数。对于这个函数能够正确工作,需要满足N1
≤N2
≤N3
≤...
≤Nn
。这是因为使用了二分查找(非常快速)。mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200); -> 3 mysql> SELECT INTERVAL(10, 1, 10, 100, 1000); -> 2 mysql> SELECT INTERVAL(22, 23, 30, 44, 200); -> 0
-
IS *
boolean_value*
测试一个值是否等于布尔值,其中
boolean_value
可以是TRUE
、FALSE
或UNKNOWN
。mysql> SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN; -> 1, 1, 1
-
IS NOT *
boolean_value*
测试一个值是否等于布尔值,其中
boolean_value
可以是TRUE
、FALSE
或UNKNOWN
。mysql> SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN; -> 1, 1, 0
-
IS NULL
测试一个值是否为
NULL
。mysql> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL; -> 0, 0, 1
为了与 ODBC 程序良好配合,MySQL 在使用
IS NULL
时支持以下额外功能:-
如果
sql_auto_is_null
变量设置为 1,则在成功插入自动生成的AUTO_INCREMENT
值的语句之后,可以通过发出以下形式的语句找到该值:SELECT * FROM *tbl_name* WHERE *auto_col* IS NULL
如果语句返回一行,则返回的值与调用
LAST_INSERT_ID()
函数的结果相同。有关详细信息,包括多行插入后的返回值,请参见第 14.15 节,“信息函数”。如果没有成功插入AUTO_INCREMENT
值,则SELECT
语句不返回任何行。通过设置
sql_auto_is_null = 0
可以禁用使用IS NULL
比较来检索AUTO_INCREMENT
值的行为。请参见第 7.1.8 节,“服务器系统变量”。sql_auto_is_null
的默认值为 0。 -
对于声明为
NOT NULL
的DATE
和DATETIME
列,可以通过类似以下语句找到特殊日期'0000-00-00'
:SELECT * FROM *tbl_name* WHERE *date_column* IS NULL
这是为了使一些 ODBC 应用程序正常工作而需要的,因为 ODBC 不支持
'0000-00-00'
日期值。参见获取自增值,以及 Connector/ODBC 连接参数中
FLAG_AUTO_IS_NULL
选项的描述。
-
-
IS NOT NULL
测试一个值是否不为
NULL
。mysql> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL; -> 1, 1, 0
-
ISNULL(*
expr*)
如果
expr
为NULL
,ISNULL()
返回1
,否则返回0
。mysql> SELECT ISNULL(1+1); -> 0 mysql> SELECT ISNULL(1/0); -> 1
ISNULL()
可用于代替=
来测试一个值是否为NULL
。(使用=
将值与NULL
进行比较总是返回NULL
。)ISNULL()
函数与IS NULL
比较运算符共享一些特殊行为。请参见IS NULL
的描述。 -
LEAST(*
value1*,*
value2*,...)
对于两个或更多参数,返回最小值的参数。参数将根据以下规则进行比较:
-
如果任何参数为
NULL
,则结果为NULL
。不需要进行比较。 -
如果所有参数都是整数值,则它们将作为整数进行比较。
-
如果至少一个参数是双精度,则它们将作为双精度值进行比较。否则,如果至少一个参数是
DECIMAL
- DECIMAL, NUMERIC")值,则它们将作为DECIMAL
- DECIMAL, NUMERIC")值进行比较。 -
如果参数包含数字和字符串的混合,则它们将作为字符串进行比较。
-
如果任何参数是非二进制(字符)字符串,则参数将作为非二进制字符串进行比较。
-
在所有其他情况下,参数将作为二进制字符串进行比较。
LEAST()
的返回类型是比较参数类型的聚合类型。mysql> SELECT LEAST(2,0); -> 0 mysql> SELECT LEAST(34.0,3.0,5.0,767.0); -> 3.0 mysql> SELECT LEAST('B','A','C'); -> 'A'
-
14.4.3 逻辑运算符
表 14.5 逻辑运算符
名称 | 描述 |
---|---|
AND , && |
逻辑 AND |
NOT , ! |
取反值 |
OR , || |
逻辑 OR |
XOR |
逻辑 XOR |
在 SQL 中,所有逻辑运算符的计算结果为TRUE
、FALSE
或NULL
(UNKNOWN
)。在 MySQL 中,这些分别实现为 1(TRUE
)、0(FALSE
)和NULL
。大部分内容适用于不同的 SQL 数据库服务器,尽管有些服务器可能会返回任何非零值作为TRUE
。
MySQL 将任何非零、非NULL
值计算为TRUE
。例如,以下语句都评估为TRUE
:
mysql> SELECT 10 IS TRUE;
-> 1
mysql> SELECT -10 IS TRUE;
-> 1
mysql> SELECT 'string' IS NOT NULL;
-> 1
-
NOT
,!
逻辑 NOT。如果操作数为
0
,则计算结果为1
,如果操作数为非零,则为0
,NOT NULL
返回NULL
。mysql> SELECT NOT 10; -> 0 mysql> SELECT NOT 0; -> 1 mysql> SELECT NOT NULL; -> NULL mysql> SELECT ! (1+1); -> 0 mysql> SELECT ! 1+1; -> 1
最后一个示例产生
1
,因为该表达式的计算方式与(!1)+1
相同。!
运算符是 MySQL 的非标准扩展。从 MySQL 8.0.17 开始,此运算符已被弃用;预计在未来的 MySQL 版本中将不再支持。应用程序应调整为使用标准 SQLNOT
运算符。 -
AND
,&&
逻辑 AND。如果所有操作数均为非零且非
NULL
,则计算结果为1
,如果一个或多个操作数为0
,则结果为0
,否则返回NULL
。mysql> SELECT 1 AND 1; -> 1 mysql> SELECT 1 AND 0; -> 0 mysql> SELECT 1 AND NULL; -> NULL mysql> SELECT 0 AND NULL; -> 0 mysql> SELECT NULL AND 0; -> 0
&&
运算符是 MySQL 的非标准扩展。从 MySQL 8.0.17 开始,此运算符已被弃用;预计在未来的 MySQL 版本中将不再支持。应用程序应调整为使用标准 SQLAND
运算符。 -
OR
,||
逻辑 OR。当两个操作数均为非
NULL
时,如果任一操作数为非零,则结果为1
,否则为0
。如果有一个操作数为NULL
,则结果为1
,如果另一个操作数为非零,则为NULL
。如果两个操作数均为NULL
,则结果为NULL
。mysql> SELECT 1 OR 1; -> 1 mysql> SELECT 1 OR 0; -> 1 mysql> SELECT 0 OR 0; -> 0 mysql> SELECT 0 OR NULL; -> NULL mysql> SELECT 1 OR NULL; -> 1
注意
如果启用了
PIPES_AS_CONCAT
SQL 模式,则||
表示 SQL 标准的字符串连接运算符(类似于CONCAT()
)。||
运算符是 MySQL 的非标准扩展。从 MySQL 8.0.17 开始,该运算符已被弃用;预计在未来的 MySQL 版本中将移除对其的支持。应用程序应调整为使用标准 SQL 的OR
运算符。例外情况:如果启用了PIPES_AS_CONCAT
,则不适用弃用规则,因为在这种情况下,||
表示字符串连接。 -
XOR
逻辑异或。如果任一操作数为
NULL
,则返回NULL
。对于非NULL
操作数,如果奇数个操作数为非零,则评估为1
,否则返回0
。mysql> SELECT 1 XOR 1; -> 0 mysql> SELECT 1 XOR 0; -> 1 mysql> SELECT 1 XOR NULL; -> NULL mysql> SELECT 1 XOR 1 XOR 1; -> 1
a XOR b
在数学上等同于(a AND (NOT b)) OR ((NOT a) and b)
。
14.4.4 分配运算符
原文:
dev.mysql.com/doc/refman/8.0/en/assignment-operators.html
表 14.6 分配运算符
名称 | 描述 |
---|---|
:= |
分配一个值 |
= |
分配一个值(作为SET 语句的一部分,或作为UPDATE 语句中的SET 子句) |
-
:=
分配运算符。导致运算符左侧的用户变量取右侧的值。右侧的值可以是文字值,存储值的另一个变量,或产生标量值的任何合法表达式,包括查询的结果(前提是这个值是标量值)。您可以在同一条
SET
语句中执行多个分配。您可以在同一条语句中执行多个分配。与
=
不同,:=
运算符永远不会被解释为比较运算符。这意味着您可以在任何有效的 SQL 语句(不仅仅是在SET
语句中)中使用:=
来为变量分配一个值。mysql> SELECT @var1, @var2; -> NULL, NULL mysql> SELECT @var1 := 1, @var2; -> 1, NULL mysql> SELECT @var1, @var2; -> 1, NULL mysql> SELECT @var1, @var2 := @var1; -> 1, 1 mysql> SELECT @var1, @var2; -> 1, 1 mysql> SELECT @var1:=COUNT(*) FROM t1; -> 4 mysql> SELECT @var1; -> 4
除了
SELECT
之外,您还可以在其他语句中使用:=
进行值分配,例如UPDATE
,如下所示:mysql> SELECT @var1; -> 4 mysql> SELECT * FROM t1; -> 1, 3, 5, 7 mysql> UPDATE t1 SET c1 = 2 WHERE c1 = @var1:= 1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> SELECT @var1; -> 1 mysql> SELECT * FROM t1; -> 2, 3, 5, 7
虽然在单个 SQL 语句中使用
:=
运算符既可以设置变量的值又可以读取变量的值,但不建议这样做。第 11.4 节,“用户定义变量”解释了为什么应该避免这样做。 -
=
此运算符用于在下面两种情况下执行值分配,分别在接下来的两段中描述。
在
SET
语句中,=
被视为一个赋值运算符,导致操作符左侧的用户变量取得右侧的值。(换句话说,在SET
语句中使用时,=
与:=
的作用是相同的。)右侧的值可以是一个字面值,存储值的另一个变量,或者产生标量值的任何合法表达式,包括查询的结果(前提是这个值是一个标量值)。你可以在同一个SET
语句中执行多个赋值操作。在
UPDATE
语句的SET
子句中,=
也充当一个赋值运算符;然而,在这种情况下,它会导致操作符左侧命名的列取得右侧给定的值,前提是UPDATE
中的任何WHERE
条件都得到满足。你可以在同一个SET
子句的UPDATE
语句中进行多个赋值操作。在任何其他上下文中,
=
被视为一个比较运算符。mysql> SELECT @var1, @var2; -> NULL, NULL mysql> SELECT @var1 := 1, @var2; -> 1, NULL mysql> SELECT @var1, @var2; -> 1, NULL mysql> SELECT @var1, @var2 := @var1; -> 1, 1 mysql> SELECT @var1, @var2; -> 1, 1
欲了解更多信息,请参阅第 15.7.6.1 节,“变量赋值的 SET 语法”,第 15.2.17 节,“UPDATE 语句”,以及第 15.2.15 节,“子查询”。
14.5 流程控制函数
原文:
dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html
表 14.7 流程控制运算符
名称 | 描述 |
---|---|
CASE |
Case 运算符 |
IF() |
如果/否则构造 |
IFNULL() |
如果/否则构造 |
NULLIF() |
如果expr1 = expr2 则返回NULL |
-
CASE WHEN *
condition* THEN *
result* [WHEN *
condition* THEN *
result* ...] [ELSE *
result*] END
第一个
CASE
语法返回第一个*value
=compare_value
*为真的*result*
。第二个语法返回第一个为真的条件的结果。如果没有比较或条件为真,则返回ELSE
后的结果,如果没有ELSE
部分则返回NULL
。注意
此处描述的
CASE
运算符的语法与第 15.6.5.1 节“CASE 语句”中描述的 SQLCASE
语句略有不同,用于存储程序内部。CASE
语句不能有ELSE NULL
子句,并以END CASE
而不是END
结束。CASE
表达式的返回类型是所有结果值的聚合类型:-
如果所有类型都是数值型,则聚合类型也是数值型:
-
如果至少有一个参数是双精度,则结果为双精度。
-
否则,如果至少有一个参数是
DECIMAL
,则结果为DECIMAL
。 -
否则,结果是整数类型(有一个例外):
-
如果所有整数类型都是全部有符号或全部无符号,结果是相同符号且精度是所有指定整数类型中最高的(即
TINYINT
、SMALLINT
、MEDIUMINT
、INT
或BIGINT
)。 -
如果有符号和无符号整数类型的组合,结果是有符号的,精度可能更高。例如,如果类型是有符号的
INT
和无符号的INT
,结果是有符号的BIGINT
。 -
例外情况是无符号的
BIGINT
与任何有符号整数类型相结合。结果是具有足够精度和标度为 0 的DECIMAL
。
-
-
-
如果所有类型都是
BIT
,结果是BIT
。否则,BIT
参数被视为类似于BIGINT
。 -
如果所有类型都是
YEAR
,结果是YEAR
。否则,YEAR
参数被视为类似于INT
。 -
如果所有类型都是字符字符串(
CHAR
或VARCHAR
),结果是具有由操作数的最长字符长度确定的最大长度的VARCHAR
。 -
如果所有类型都是字符或二进制字符串,结果是
VARBINARY
。 -
SET
和ENUM
被视为类似于VARCHAR
;结果是VARCHAR
。 -
如果所有类型都是
JSON
,结果是JSON
。 -
如果所有类型都是时间类型,结果就是时间类型:
-
如果所有时间类型都是
DATE
、TIME
或TIMESTAMP
,结果分别是DATE
、TIME
或TIMESTAMP
。 -
否则,对于时间类型的混合,结果是
DATETIME
。
-
-
如果所有类型都是
GEOMETRY
,结果就是GEOMETRY
。 -
如果任何类型是
BLOB
,结果是BLOB
。 -
对于所有其他类型组合,结果是
VARCHAR
。 -
对于类型聚合,字面
NULL
操作数将被忽略。
mysql> SELECT CASE 1 WHEN 1 THEN 'one' -> WHEN 2 THEN 'two' ELSE 'more' END; -> 'one' mysql> SELECT CASE WHEN 1>0 THEN 'true' ELSE 'false' END; -> 'true' mysql> SELECT CASE BINARY 'B' -> WHEN 'a' THEN 1 WHEN 'b' THEN 2 END; -> NULL
-
-
IF(*
expr1*,*
expr2*,*
expr3*)
如果
expr1
为TRUE
(*
expr1* <> 0
且*
expr1* IS NOT NULL
),IF()
返回expr2
。否则,返回expr3
。注意
还有一个
IF
语句,与此处描述的IF()
函数不同。请参见第 15.6.5.2 节,“IF 语句”。如果
expr2
或expr3
中只有一个明确为NULL
,则IF()
函数的结果类型是非NULL
表达式的类型。IF()
的默认返回类型(当它存储到临时表时可能很重要)计算如下:-
如果
expr2
或expr3
产生字符串,则结果是字符串。如果
expr2
和expr3
都是字符串,则结果是区分大小写的,如果任一字符串是区分大小写的。 -
如果
expr2
或expr3
产生浮点值,则结果是浮点值。 -
如果
expr2
或expr3
产生整数,则结果是整数。
mysql> SELECT IF(1>2,2,3); -> 3 mysql> SELECT IF(1<2,'yes','no'); -> 'yes' mysql> SELECT IF(STRCMP('test','test1'),'no','yes'); -> 'no'
-
-
IFNULL(*
expr1*,*
expr2*)
如果
expr1
不是NULL
,IFNULL()
返回expr1
;否则返回expr2
。mysql> SELECT IFNULL(1,0); -> 1 mysql> SELECT IFNULL(NULL,10); -> 10 mysql> SELECT IFNULL(1/0,10); -> 10 mysql> SELECT IFNULL(1/0,'yes'); -> 'yes'
IFNULL(*
expr1*,*
expr2*)
的默认返回类型是两个表达式中更“通用”的类型,按顺序为STRING
、REAL
或INTEGER
。考虑基于表达式的表或 MySQL 必须在临时表中内部存储IFNULL()
返回的值的情况:mysql> CREATE TABLE tmp SELECT IFNULL(1,'test') AS test; mysql> DESCRIBE tmp; +-------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+-------+ | test | varbinary(4) | NO | | | | +-------+--------------+------+-----+---------+-------+
在这个例子中,
test
列的类型是VARBINARY(4)
(一个字符串类型)。 -
NULLIF(*
expr1*,*
expr2*)
如果
*
expr1* = *
expr2*
为真,则返回NULL
,否则返回expr1
。这与CASE WHEN *
expr1* = *
expr2* THEN NULL ELSE *
expr1* END
相同。返回值与第一个参数具有相同的类型。
mysql> SELECT NULLIF(1,1); -> NULL mysql> SELECT NULLIF(1,2); -> 1
注意
MySQL 在参数不相等时会对
expr1
进行两次评估。
MySQL 8.0.22 中这些函数对系统变量值的处理发生了变化。对于这些函数中的每一个,如果第一个参数仅包含在第二个参数使用的字符集和校对规则中存在的字符(且它是常量),则后者的字符集和校对规则用于进行比较。在 MySQL 8.0.22 及更高版本中,系统变量值被处理为具有相同字符集和校对规则的列值。一些使用这些函数与系统变量的查询可能会被拒绝,出现 Illegal mix of collations。在这种情况下,您应该将系统变量转换为正确的字符集和校对规则。
14.6 数值函数和运算符
14.6.1 算术运算符
14.6.2 数学函数
表格 14.8 数值函数和运算符
名称 | 描述 |
---|---|
% , MOD |
取模运算符 |
* |
乘法运算符 |
+ |
加法运算符 |
- |
减法运算符 |
- |
改变参数的符号 |
/ |
除法运算符 |
ABS() |
返回绝对值 |
ACOS() |
返回反余弦 |
ASIN() |
返回反正弦 |
ATAN() |
返回反正切 |
ATAN2() , ATAN() |
返回两个参数的反正切 |
CEIL() |
返回不小于参数的最小整数值 |
CEILING() |
返回不小于参数的最小整数值 |
CONV() |
在不同进制之间转换数字 |
COS() |
返回余弦值 |
COT() |
返回余切 |
CRC32() |
计算循环冗余校验值 |
DEGREES() |
将弧度转换为角度 |
DIV |
整数除法 |
EXP() |
指数运算 |
FLOOR() |
返回不大于参数的最大整数值 |
LN() |
返回参数的自然对数 |
LOG() |
返回第一个参数的自然对数 |
LOG10() |
返回参数的以 10 为底的对数 |
LOG2() |
返回参数的以 2 为底的对数 |
MOD() |
返回余数 |
PI() |
返回圆周率的值 |
POW() |
返回参数的指定幂值 |
POWER() |
返回参数的指定幂次方 |
RADIANS() |
返回转换为弧度的参数 |
RAND() |
返回一个随机浮点值 |
ROUND() |
四舍五入参数 |
SIGN() |
返回参数的符号 |
SIN() |
返回参数的正弦值 |
SQRT() |
返回参数的平方根 |
TAN() |
返回参数的正切值 |
TRUNCATE() |
截断到指定的小数位数 |
名称 | 描述 |
14.6.1 算术运算符
原文:
dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html
表 14.9 算术运算符
名称 | 描述 |
---|---|
% , MOD |
取模运算符 |
* |
乘法运算符 |
+ |
加法运算符 |
- |
减法运算符 |
- |
改变参数的符号 |
/ |
除法运算符 |
DIV |
整数除法 |
常见的算术运算符都是可用的。结果根据以下规则确定:
-
对于
-
、+
和*
,如果两个操作数都是整数,则结果将以BIGINT
(64 位)精度计算。 -
如果两个操作数都是整数且其中任何一个是无符号的,则结果将是无符号整数。对于减法,如果启用了
NO_UNSIGNED_SUBTRACTION
SQL 模式,则结果将是有符号的,即使任何操作数是无符号的。 -
如果
+
、-
、/
、*
、%
的任何操作数是实数或字符串值,则结果的精度为具有最大精度的操作数的精度。 -
在使用
/
进行除法运算时,使用两个精确值操作数的结果的精度为第一个操作数的精度加上div_precision_increment
系统变量的值(默认为 4)。例如,表达式5.05 / 0.014
的结果具有六位小数的精度(360.714286
)。
这些规则适用于每个操作,因此嵌套计算意味着每个组件的精度。因此,(14620 / 9432456) / (24250 / 9432456)
,首先解析为(0.0014) / (0.0026)
,最终结果具有 8 位小数的精度(0.60288653
)。
由于这些规则及其应用方式,应注意确保计算的组件和子组件使用适当级别的精度。参见第 14.10 节,“转换函数和运算符”。
有关数值表达式计算中溢出处理的信息,请参见第 13.1.7 节,“超出范围和溢出处理”。
算术运算符适用于数字。对于其他类型的值,可能会提供替代操作。例如,要添加日期值,请使用DATE_ADD()
; 请参阅第 14.7 节,“日期和时间函数”。
-
+
加法:
mysql> SELECT 3+5; -> 8
-
-
减法:
mysql> SELECT 3-5; -> -2
-
-
一元负号。此运算符改变操作数的符号。
mysql> SELECT - 2; -> -2
注意
如果此运算符与
BIGINT
- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT")一起使用,则返回值也是BIGINT
- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT")。这意味着您应避免对可能具有值−2⁶³的整数使用-
。 -
*
乘法:
mysql> SELECT 3*5; -> 15 mysql> SELECT 18014398509481984*18014398509481984.0; -> 324518553658426726783156020576256.0 mysql> SELECT 18014398509481984*18014398509481984; -> out-of-range error
最后一个表达式会产生错误,因为整数乘法的结果超出了
BIGINT
- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT")计算的 64 位范围。(请参阅第 13.1 节,“数值数据类型”。) -
/
除法:
mysql> SELECT 3/5; -> 0.60
除以零会产生
NULL
结果:mysql> SELECT 102/(1-1); -> NULL
仅当在将其结果转换为整数的上下文中执行时,才使用
BIGINT
- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT")算术计算除法。 -
DIV
整数除法。舍弃除法结果小数点右侧的任何小数部分。
如果任一操作数具有非整数类型,则在将结果转换为
BIGINT
- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT")之前,将操作数转换为DECIMAL
- DECIMAL, NUMERIC")并使用DECIMAL
- DECIMAL, NUMERIC")算术进行除法。如果结果超出BIGINT
范围,则会发生错误。mysql> SELECT 5 DIV 2, -5 DIV 2, 5 DIV -2, -5 DIV -2; -> 2, -2, -2, 2
-
*
N* % *
M*
,*
N* MOD *
M*
取模运算。返回
N
除以M
的余数。有关更多信息,请参见第 14.6.2 节,“数学函数”中MOD()
函数的描述。
14.6.2 数学函数
原文:
dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html
Table 14.10 数学函数
名称 | 描述 |
---|---|
ABS() |
返回绝对值 |
ACOS() |
返回反余弦值 |
ASIN() |
返回反正弦值 |
ATAN() |
返回反正切值 |
ATAN2() , ATAN() |
返回两个参数的反正切 |
CEIL() |
返回不小于参数的最小整数值 |
CEILING() |
返回不小于参数的最小整数值 |
CONV() |
在不同进制之间转换数字 |
COS() |
返回余弦值 |
COT() |
返回余切值 |
CRC32() |
计算循环冗余校验值 |
DEGREES() |
将弧度转换为角度 |
EXP() |
求幂 |
FLOOR() |
返回不大于参数的最大整数值 |
LN() |
返回参数的自然对数 |
LOG() |
返回第一个参数的自然对数 |
LOG10() |
返回参数的以 10 为底的对数 |
LOG2() |
返回参数的以 2 为底的对数 |
MOD() |
返回余数 |
PI() |
返回圆周率的值 |
POW() |
返回指定幂次的参数 |
POWER() |
返回指定幂次的参数 |
RADIANS() |
返回转换为弧度的参数 |
RAND() |
返回一个随机浮点值 |
ROUND() |
四舍五入参数 |
SIGN() |
返回参数的符号 |
SIN() |
返回参数的正弦值 |
SQRT() |
返回参数的平方根 |
TAN() |
返回参数的正切 |
TRUNCATE() |
截断到指定的小数位数 |
名称 | 描述 |
所有数学函数在出现错误时返回NULL
。
-
ABS(*
X*)
返回
X
的绝对值,如果X
为NULL
,则返回NULL
。结果类型源自参数类型。这意味着
ABS(-9223372036854775808)
会产生错误,因为结果无法存储在有符号的BIGINT
值中。mysql> SELECT ABS(2); -> 2 mysql> SELECT ABS(-32); -> 32
此函数可安全用于
BIGINT
值。 -
ACOS(*
X*)
返回
X
的反余弦,即,其余弦值为X
的值。如果X
不在-1
到1
的范围内,或者X
为NULL
,则返回NULL
。mysql> SELECT ACOS(1); -> 0 mysql> SELECT ACOS(1.0001); -> NULL mysql> SELECT ACOS(0); -> 1.5707963267949
-
ASIN(*
X*)
返回
X
的反正弦,即,其正弦值为X
的值。如果X
不在-1
到1
的范围内,或者X
为NULL
,则返回NULL
。mysql> SELECT ASIN(0.2); -> 0.20135792079033 mysql> SELECT ASIN('foo'); +-------------+ | ASIN('foo') | +-------------+ | 0 | +-------------+ 1 row in set, 1 warning (0.00 sec) mysql> SHOW WARNINGS; +---------+------+-----------------------------------------+ | Level | Code | Message | +---------+------+-----------------------------------------+ | Warning | 1292 | Truncated incorrect DOUBLE value: 'foo' | +---------+------+-----------------------------------------+
-
ATAN(*
X*)
返回
X
的反正切。即,其正切值为X
的值。如果X
为NULL
,则返回NULL
。mysql> SELECT ATAN(2); -> 1.1071487177941 mysql> SELECT ATAN(-2); -> -1.1071487177941
-
ATAN(*
Y*,*
X*)
,ATAN2(*
Y*,*
X*)
返回两个变量
X
和Y
的反正切。它类似于计算*
Y* / *
X*
的反正切,只是使用两个参数的符号来确定结果的象限。如果X
或Y
为NULL
,则返回NULL
。mysql> SELECT ATAN(-2,2); -> -0.78539816339745 mysql> SELECT ATAN2(PI(),0); -> 1.5707963267949
-
CEIL(*
X*)
CEIL()
是CEILING()
的同义词。 -
CEILING(*
X*)
返回不小于
X
的最小整数值。如果X
为NULL
,则返回NULL
。mysql> SELECT CEILING(1.23); -> 2 mysql> SELECT CEILING(-1.23); -> -1
对于精确值数值参数,返回值具有精确值数值类型。对于字符串或浮点参数,返回值具有浮点类型。
-
CONV(*
N*,*
from_base*,*
to_base*)
在不同进制之间转换数字。返回从基数
from_base
转换为基数to_base
的数字N
的字符串表示。如果任何参数为NULL
,则返回NULL
。参数N
被解释为整数,但可以指定为整数或字符串。最小基数为2
,最大基数为36
。如果from_base
是负数,则N
被视为有符号数。否则,N
被视为无符号数。CONV()
以 64 位精度工作。如果
CONV()
的任何参数为NULL
,则返回NULL
。mysql> SELECT CONV('a',16,2); -> '1010' mysql> SELECT CONV('6E',18,8); -> '172' mysql> SELECT CONV(-17,10,-18); -> '-H' mysql> SELECT CONV(10+'10'+'10'+X'0a',10,10); -> '40'
-
COS(*
X*)
返回
X
的余弦值,其中X
以弧度给出。如果X
为NULL
,则返回NULL
。mysql> SELECT COS(PI()); -> -1
-
COT(*
X*)
返回
X
的余切值。如果X
为NULL
,则返回NULL
。mysql> SELECT COT(12); -> -1.5726734063977 mysql> SELECT COT(0); -> out-of-range error
-
CRC32(*
expr*)
计算循环冗余校验值并返回一个 32 位无符号值。如果参数为
NULL
,则结果为NULL
。预期参数为字符串,如果可能的话,如果参数不是字符串,则会被视为字符串。mysql> SELECT CRC32('MySQL'); -> 3259397556 mysql> SELECT CRC32('mysql'); -> 2501908538
-
DEGREES(*
X*)
返回将弧度转换为度的参数
X
。如果X
为NULL
,则返回NULL
。mysql> SELECT DEGREES(PI()); -> 180 mysql> SELECT DEGREES(PI() / 2); -> 90
-
EXP(*
X*)
返回e(自然对数的底)的
X
次幂的值。该函数的反函数是LOG()
(仅使用单个参数)或LN()
。如果
X
为NULL
,此函数返回NULL
。mysql> SELECT EXP(2); -> 7.3890560989307 mysql> SELECT EXP(-2); -> 0.13533528323661 mysql> SELECT EXP(0); -> 1
-
FLOOR(*
X*)
返回不大于
X
的最大整数值。如果X
为NULL
,则返回NULL
。mysql> SELECT FLOOR(1.23), FLOOR(-1.23); -> 1, -2
对于精确值数值参数,返回值具有精确值数值类型。对于字符串或浮点参数,返回值具有浮点类型。
-
FORMAT(*
X*,*
D*)
将数字
X
格式化为类似'#,###,###.##'
的格式,四舍五入到D
位小数,并将结果作为字符串返回。有关详细信息,请参阅第 14.8 节“字符串函数和运算符”。 -
HEX(N_or_S)
此函数可用于获取十进制数或字符串的十六进制表示;它的工作方式根据参数的类型而变化。有关详细信息,请参阅第 14.8 节“字符串函数和运算符”中此函数的描述。
-
LN(*
X*)
返回
X
的自然对数;即X
的以e为底的对数。如果X
小于或等于 0.0E0,则函数返回NULL
并报告警告“对数的参数无效”。如果X
为NULL
,则返回NULL
。mysql> SELECT LN(2); -> 0.69314718055995 mysql> SELECT LN(-2); -> NULL
此函数与
LOG(*
X*)
是同义词。该函数的反函数是EXP()
函数。 -
LOG(*
X*)
,LOG(*
B*,*
X*)
如果使用一个参数调用此函数,则返回
X
的自然对数。如果X
小于或等于 0.0E0,则函数返回NULL
并报告警告“对数的参数无效”。如果X
或B
为NULL
,则返回NULL
。此函数的倒数(使用单个参数调用时)是
EXP()
函数。mysql> SELECT LOG(2); -> 0.69314718055995 mysql> SELECT LOG(-2); -> NULL
如果使用两个参数调用此函数,则返回以
B
为底的X
的对数。如果X
小于或等于 0,或者B
小于或等于 1,则返回NULL
。mysql> SELECT LOG(2,65536); -> 16 mysql> SELECT LOG(10,100); -> 2 mysql> SELECT LOG(1,100); -> NULL
LOG(*
B*,*
X*)
等同于LOG(*
X*) / LOG(*
B*)
。 -
LOG2(*
X*)
返回
*
X*
的以 2 为底的对数。如果X
小于或等于 0.0E0,则函数返回NULL
并报告警告“对数的参数无效”。如果X
为NULL
,则返回NULL
。mysql> SELECT LOG2(65536); -> 16 mysql> SELECT LOG2(-100); -> NULL
LOG2()
用于查找一个数字需要多少位来存储。此函数等同于表达式LOG(*
X*) / LOG(2)
。 -
LOG10(*
X*)
返回
X
的以 10 为底的对数。如果X
小于或等于 0.0E0,则函数返回NULL
并报告警告“对数的参数无效”。如果X
为NULL
,则返回NULL
。mysql> SELECT LOG10(2); -> 0.30102999566398 mysql> SELECT LOG10(100); -> 2 mysql> SELECT LOG10(-100); -> NULL
LOG10(*
X*)
等同于LOG(10,*
X*)
。 -
MOD(*
N*,*
M*)
,*
N* % *
M*
,*
N* MOD *
M*
取模运算。返回
N
除以M
的余数。如果M
或N
为NULL
,则返回NULL
。mysql> SELECT MOD(234, 10); -> 4 mysql> SELECT 253 % 7; -> 1 mysql> SELECT MOD(29,9); -> 2 mysql> SELECT 29 MOD 9; -> 2
此函数可安全用于
BIGINT
值。MOD()
也适用于具有小数部分的值,并返回除法后的确切余数:mysql> SELECT MOD(34.5,3); -> 1.5
MOD(*
N*,0)
返回NULL
。 -
PI()
返回π(pi)的值。显示的小数位数默认为七位,但 MySQL 在内部使用完整的双精度值。
因为此函数的返回值是双精度值,其精确表示可能因平台或实现而异。这也适用于使用
PI()
的任何表达式。参见第 13.1.4 节,“浮点类型(近似值) - FLOAT,DOUBLE”。mysql> SELECT PI(); -> 3.141593 mysql> SELECT PI()+0.000000000000000000; -> 3.141592653589793000
-
POW(*
X*,*
Y*)
返回
X
的Y
次幂的值。如果X
或Y
为NULL
,则返回NULL
。mysql> SELECT POW(2,2); -> 4 mysql> SELECT POW(2,-2); -> 0.25
-
POWER(*
X*,*
Y*)
这是
POW()
的同义词。 -
RADIANS(*
X*)
返回将参数
X
从度转换为弧度的值。(注意π弧度等于 180 度。)如果X
为NULL
,则返回NULL
。mysql> SELECT RADIANS(90); -> 1.5707963267949
-
返回范围为
0
<=v
<1.0
的随机浮点值v
。要在范围i
<=R
<j
内获取随机整数R
,可以使用表达式FLOOR(*
i* + RAND() * (*
j*
−*
i*))
。例如,要在范围7
<=R
<12
内获取随机整数,请使用以下语句:SELECT FLOOR(7 + (RAND() * 5));
如果指定了整数参数
N
,则将其用作种子值:-
使用常量初始化参数时,种子在语句准备之前一次性初始化,然后执行。
-
使用非常量初始化参数(例如列名),种子在每次调用
RAND()
时都会被初始化为该值。
这种行为的一个含义是,对于相等的参数值,
RAND(*
N*)
每次都返回相同的值,从而产生一系列可重复的列值。在以下示例中,RAND(3)
产生的值序列在两个位置都是相同的。mysql> CREATE TABLE t (i INT); Query OK, 0 rows affected (0.42 sec) mysql> INSERT INTO t VALUES(1),(2),(3); Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> SELECT i, RAND() FROM t; +------+------------------+ | i | RAND() | +------+------------------+ | 1 | 0.61914388706828 | | 2 | 0.93845168309142 | | 3 | 0.83482678498591 | +------+------------------+ 3 rows in set (0.00 sec) mysql> SELECT i, RAND(3) FROM t; +------+------------------+ | i | RAND(3) | +------+------------------+ | 1 | 0.90576975597606 | | 2 | 0.37307905813035 | | 3 | 0.14808605345719 | +------+------------------+ 3 rows in set (0.00 sec) mysql> SELECT i, RAND() FROM t; +------+------------------+ | i | RAND() | +------+------------------+ | 1 | 0.35877890638893 | | 2 | 0.28941420772058 | | 3 | 0.37073435016976 | +------+------------------+ 3 rows in set (0.00 sec) mysql> SELECT i, RAND(3) FROM t; +------+------------------+ | i | RAND(3) | +------+------------------+ | 1 | 0.90576975597606 | | 2 | 0.37307905813035 | | 3 | 0.14808605345719 | +------+------------------+ 3 rows in set (0.01 sec)
在
WHERE
子句中使用RAND()
会为每一行(从一个表中选择)或每一行组合(从多个表连接中选择)评估。因此,对于优化器而言,RAND()
不是一个常量值,不能用于索引优化。有关更多信息,请参见第 10.2.1.20 节,“函数调用优化”。在
ORDER BY
或GROUP BY
子句中使用带有RAND()
值的列可能会产生意外结果,因为对于任一子句,RAND()
表达式可能会对同一行进行多次评估,每次返回不同的结果。如果目标是以随机顺序检索行,可以使用类似以下语句:SELECT * FROM *tbl_name* ORDER BY RAND();
要从一组行中选择随机样本,请将
ORDER BY RAND()
与LIMIT
结合使用:SELECT * FROM table1, table2 WHERE a=b AND c<d ORDER BY RAND() LIMIT 1000;
RAND()
并不是一个完美的随机生成器。它是一种快速生成随机数的方式,可在相同的 MySQL 版本的不同平台之间移植。此函数对基于语句的复制不安全。如果在将
binlog_format
设置为STATEMENT
时使用此函数,将记录警告。 -
-
ROUND(*
X*)
,ROUND(*
X*,*
D*)
将参数
X
四舍五入到D
位小数。舍入算法取决于X
的数据类型。如果未指定,D
默认为 0。D
可以为负,使得值X
小数点左边的D
位变为零。D
的最大绝对值为 30;超过 30(或-30)的任何数字将被截断。如果X
或D
为NULL
,则函数返回NULL
。mysql> SELECT ROUND(-1.23); -> -1 mysql> SELECT ROUND(-1.58); -> -2 mysql> SELECT ROUND(1.58); -> 2 mysql> SELECT ROUND(1.298, 1); -> 1.3 mysql> SELECT ROUND(1.298, 0); -> 1 mysql> SELECT ROUND(23.298, -1); -> 20 mysql> SELECT ROUND(.12345678901234567890123456789012345, 35); -> 0.123456789012345678901234567890
返回值与第一个参数的类型相同(假设它是整数、双精度或十进制)。这意味着对于整数参数,结果是一个整数(没有小数位):
mysql> SELECT ROUND(150.000,2), ROUND(150,2); +------------------+--------------+ | ROUND(150.000,2) | ROUND(150,2) | +------------------+--------------+ | 150.00 | 150 | +------------------+--------------+
ROUND()
根据第一个参数的类型使用以下规则:-
对于精确值数字,
ROUND()
使用“远离零的一半”或“向最近整数四舍五入”的规则:具有小数部分为.5 或更大的值,如果为正则四舍五入到下一个整数,如果为负则四舍五入到下一个整数。(换句话说,它远离零。)具有小于.5 的小数部分的值,如果为正则向下舍入到下一个整数,如果为负则向上舍入到下一个整数。 -
对于近似值数字,结果取决于 C 库。在许多系统上,这意味着
ROUND()
使用“四舍五入到最近偶数”的规则:具有恰好处于两个整数之间的小数部分的值将四舍五入为最接近的偶数。
以下示例显示了精确值和近似值的舍入方式不同:
mysql> SELECT ROUND(2.5), ROUND(25E-1); +------------+--------------+ | ROUND(2.5) | ROUND(25E-1) | +------------+--------------+ | 3 | 2 | +------------+--------------+
有关更多信息,请参阅第 14.24 节,“精确数学”。
在 MySQL 8.0.21 及更高版本中,
ROUND()
(以及TRUNCATE()
)返回的数据类型根据以下规则确定:-
当第一个参数是任何整数类型时,返回类型始终为
BIGINT
- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT")。 -
当第一个参数是任何浮点类型或任何非数值类型时,返回类型始终为
DOUBLE
- FLOAT, DOUBLE")。 -
当第一个参数是
DECIMAL
- DECIMAL, NUMERIC")值时,返回类型也是DECIMAL
。 -
返回值的类型属性也从第一个参数复制,除非第二个参数是常量值时,此时为
DECIMAL
。当所需小数位数少于参数的精度时,结果的精度和精度将相应调整。
此外,对于
ROUND()
(但不适用于TRUNCATE()
函数),精度会增加一位以适应增加有效数字的四舍五入。如果第二个参数为负数,则调整返回类型,使其精度为 0,具有相应的精度。例如,ROUND(99.999, 2)
返回100.00
—第一个参数为DECIMAL(5, 3)
,返回类型为DECIMAL(5, 2)
。如果第二个参数为负数,则返回类型的精度为 0,并具有相应的精度;
ROUND(99.999, -1)
返回100
,即DECIMAL(3, 0)
。
-
-
SIGN(*
X*)
返回参数的符号为
-1
、0
或1
,取决于X
是负数、零还是正数。如果X
为NULL
,则返回NULL
。mysql> SELECT SIGN(-32); -> -1 mysql> SELECT SIGN(0); -> 0 mysql> SELECT SIGN(234); -> 1
-
SIN(*
X*)
返回以弧度表示的
X
的正弦值。如果X
为NULL
,则返回NULL
。mysql> SELECT SIN(PI()); -> 1.2246063538224e-16 mysql> SELECT ROUND(SIN(PI())); -> 0
-
SQRT(*
X*)
返回非负数
X
的平方根。如果X
为NULL
,则函数返回NULL
。mysql> SELECT SQRT(4); -> 2 mysql> SELECT SQRT(20); -> 4.4721359549996 mysql> SELECT SQRT(-16); -> NULL
-
TAN(*
X*)
返回以弧度表示的
X
的正切值。如果X
为NULL
,则返回NULL
。mysql> SELECT TAN(PI()); -> -1.2246063538224e-16 mysql> SELECT TAN(PI()+1); -> 1.5574077246549
-
TRUNCATE(*
X*,*
D*)
返回将
X
截断为D
位小数的数字。如果D
为0
,则结果没有小数点或小数部分。D
可以为负数,以使值X
的小数点左边的D位变为零。如果X
或D
为NULL
,则函数返回NULL
。mysql> SELECT TRUNCATE(1.223,1); -> 1.2 mysql> SELECT TRUNCATE(1.999,1); -> 1.9 mysql> SELECT TRUNCATE(1.999,0); -> 1 mysql> SELECT TRUNCATE(-1.999,1); -> -1.9 mysql> SELECT TRUNCATE(122,-2); -> 100 mysql> SELECT TRUNCATE(10.28*100,0); -> 1028
所有数字都向零舍入。
在 MySQL 8.0.21 及更高版本中,
TRUNCATE()
返回的数据类型遵循确定ROUND()
函数返回类型的相同规则;有关详细信息,请参阅ROUND()
的描述。
14.7 日期和时间函数
原文:
dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html
本节描述了用于操作时间值的函数。有关每种日期和时间类型的值范围以及可以指定值的有效格式的描述,请参见第 13.2 节,“日期和时间数据类型”。
表格 14.11 日期和时间函数
名称 | 描述 |
---|---|
ADDDATE() |
将时间值(间隔)添加到日期值 |
ADDTIME() |
添加时间 |
CONVERT_TZ() |
将一个时区转换为另一个时区 |
CURDATE() |
返回当前日期 |
CURRENT_DATE() , CURRENT_DATE |
CURDATE()的同义词 |
CURRENT_TIME() , CURRENT_TIME |
CURTIME()的同义词 |
CURRENT_TIMESTAMP() , CURRENT_TIMESTAMP |
NOW()的同义词 |
CURTIME() |
返回当前时间 |
DATE() |
提取日期或日期时间表达式的日期部分 |
DATE_ADD() |
将时间值(间隔)添加到日期值 |
DATE_FORMAT() |
格式化指定的日期 |
DATE_SUB() |
从日期中减去一个时间值(间隔) |
DATEDIFF() |
计算两个日期之间的差值 |
DAY() |
DAYOFMONTH()的同义词 |
DAYNAME() |
返回星期几的名称 |
DAYOFMONTH() |
返回月份中的日期(0-31) |
DAYOFWEEK() |
返回参数的星期索引 |
DAYOFYEAR() |
返回一年中的日期(1-366) |
EXTRACT() |
提取日期的部分 |
FROM_DAYS() |
将天数转换为日期 |
FROM_UNIXTIME() |
将 Unix 时间戳格式化为日期 |
GET_FORMAT() |
返回日期格式字符串 |
HOUR() |
提取小时 |
LAST_DAY |
返回参数月份的最后一天 |
LOCALTIME() , LOCALTIME |
NOW()的同义词 |
LOCALTIMESTAMP , LOCALTIMESTAMP() |
NOW()的同义词 |
MAKEDATE() |
从年份和一年中的天数创建日期 |
MAKETIME() |
从小时、分钟、秒创建时间 |
MICROSECOND() |
返回参数的微秒 |
MINUTE() |
返回参数的分钟 |
MONTH() |
返回传递日期的月份 |
MONTHNAME() |
返回月份的名称 |
NOW() |
返回当前日期和时间 |
PERIOD_ADD() |
向年-月添加一个周期 |
PERIOD_DIFF() |
返回两个周期之间的月数 |
QUARTER() |
返回日期参数的季度 |
SEC_TO_TIME() |
将秒转换为'hh:mm:ss'格式 |
SECOND() |
返回秒数(0-59) |
STR_TO_DATE() |
将字符串转换为日期 |
SUBDATE() |
在使用三个参数调用时是 DATE_SUB()的同义词 |
SUBTIME() |
时间相减 |
SYSDATE() |
返回函数执行时的时间 |
TIME() |
提取传递表达式的时间部分 |
TIME_FORMAT() |
格式化为时间 |
TIME_TO_SEC() |
返回转换为秒的参数 |
TIMEDIFF() |
时间相减 |
TIMESTAMP() |
使用单个参数,此函数返回日期或日期时间表达式;使用两个参数,返回参数的总和 |
TIMESTAMPADD() |
向日期时间表达式添加一个间隔 |
TIMESTAMPDIFF() |
返回两个日期时间表达式的差异,使用指定的单位 |
TO_DAYS() |
返回转换为天数的日期参数 |
TO_SECONDS() |
返回自公元 0 年以来的秒数 |
UNIX_TIMESTAMP() |
返回 Unix 时间戳 |
UTC_DATE() |
返回当前的 UTC 日期 |
UTC_TIME() |
返回当前的 UTC 时间 |
UTC_TIMESTAMP() |
返回当前的 UTC 日期和时间 |
WEEK() |
返回周数 |
WEEKDAY() |
返回工作日索引 |
WEEKOFYEAR() |
返回日期的日历周(1-53) |
YEAR() |
返回年份 |
YEARWEEK() |
返回年份和周数 |
名称 | 描述 |
以下是一个使用日期函数的示例。以下查询选择所有date_col
值在过去 30 天内的行:
mysql> SELECT *something* FROM *tbl_name*
-> WHERE DATE_SUB(CURDATE(),INTERVAL 30 DAY) <= *date_col*;
查询还选择未来日期的行。
函数通常接受日期值,但会忽略时间部分。通常接受时间值的函数会接受日期时间值并忽略日期部分。
返回当前日期或时间的函数在每次查询执行开始时仅计算一次。这意味着在单个查询中多次引用诸如NOW()
的函数总是产生相同的结果。(对于我们的目的,单个查询还包括对存储程序(存储过程、触发器或事件)的调用以及该程序调用的所有子程序。)这个原则也适用于CURDATE()
、CURTIME()
、UTC_DATE()
、UTC_TIME()
、UTC_TIMESTAMP()
以及它们的任何同义词。
CURRENT_TIMESTAMP()
, CURRENT_TIME()
, CURRENT_DATE()
和FROM_UNIXTIME()
函数返回当前会话时区的值,该时区作为time_zone
系统变量的会话值可用。此外,UNIX_TIMESTAMP()
假定其参数是会话时区中的日期时间值。参见 Section 7.1.15, “MySQL Server Time Zone Support”。
一些日期函数可以与“零”日期或不完整日期一起使用,例如'2001-11-00'
,而其他函数则不能。通常用于提取日期部分的函数可以处理不完整日期,因此在其他情况下可能会返回 0 而不是非零值。例如:
mysql> SELECT DAYOFMONTH('2001-11-00'), MONTH('2005-00-00');
-> 0, 0
其他函数期望完整日期并对不完整日期返回NULL
。这些函数包括执行日期运算或将日期部分映射到名称的函数。例如:
mysql> SELECT DATE_ADD('2006-05-00',INTERVAL 1 DAY);
-> NULL
mysql> SELECT DAYNAME('2006-05-00');
-> NULL
当传递DATE()
函数值作为参数时,一些函数是严格的,并拒绝具有零天部分的不完整日期:CONVERT_TZ()
, DATE_ADD()
, DATE_SUB()
, DAYOFYEAR()
, TIMESTAMPDIFF()
, TO_DAYS()
, TO_SECONDS()
, WEEK()
, WEEKDAY()
, WEEKOFYEAR()
, YEARWEEK()
.
支持TIME
、DATETIME
和TIMESTAMP
值的分数秒,精度可达微秒。接受时间参数的函数接受具有分数秒的值。从时间函数返回的值包括适当的分数秒。
-
ADDDATE(*
date*,INTERVAL *
expr* *
unit*)
,ADDDATE(*
date*,*
days*)
当以第二个参数的
INTERVAL
形式调用时,ADDDATE()
是DATE_ADD()
的同义词。相关函数SUBDATE()
是DATE_SUB()
的同义词。有关INTERVAL
unit
参数的信息,请参见时间间隔。mysql> SELECT DATE_ADD('2008-01-02', INTERVAL 31 DAY); -> '2008-02-02' mysql> SELECT ADDDATE('2008-01-02', INTERVAL 31 DAY); -> '2008-02-02'
当以第二个参数的
days
形式调用时,MySQL 将其视为要添加到expr
的整数天数。mysql> SELECT ADDDATE('2008-01-02', 31); -> '2008-02-02'
如果
date
或days
为NULL
,此函数返回NULL
。 -
ADDTIME(*
expr1*,*
expr2*)
ADDTIME()
将expr2
添加到expr1
并返回结果。expr1
是时间或日期时间表达式,expr2
是时间表达式。如果expr1
或expr2
为NULL
,则返回NULL
。从 MySQL 8.0.28 开始,此函数和
SUBTIME()
函数的返回类型如下确定:-
如果第一个参数是动态参数(例如在准备好的语句中),返回类型为
TIME
。 -
否则,函数的解析类型源自第一个参数的解析类型。
mysql> SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002'); -> '2008-01-02 01:01:01.000001' mysql> SELECT ADDTIME('01:00:00.999999', '02:00:00.999998'); -> '03:00:01.999997'
-
-
CONVERT_TZ(*
dt*,*
from_tz*,*
to_tz*)
CONVERT_TZ()
将给定时区from_tz
的日期时间值dt
转换为给定时区to_tz
的值并返回结果。时区的指定方式如第 7.1.15 节“MySQL 服务器时区支持”中所述。如果任何参数无效或任何参数为NULL
,此函数返回NULL
。在 32 位平台上,此函数的支持值范围与
TIMESTAMP
类型相同(有关范围信息,请参见第 13.2.1 节“日期和时间数据类型语法”)。在 64 位平台上,从 MySQL 8.0.28 开始,最大支持值为'3001-01-18 23:59:59.999999'
UTC。无论平台或 MySQL 版本如何,如果从
from_tz
转换为 UTC 时的值超出支持范围,则不进行转换。mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET'); -> '2004-01-01 13:00:00' mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00'); -> '2004-01-01 22:00:00'
注意
要使用诸如
'MET'
或'Europe/Amsterdam'
之类的命名时区,必须正确设置时区表。有关说明,请参见第 7.1.15 节“MySQL 服务器时区支持”。 -
CURDATE()
返回当前日期作为值,格式为
'*
YYYY-MM-DD*'
或YYYYMMDD
,取决于函数在字符串或数字上下文中的使用方式。mysql> SELECT CURDATE(); -> '2008-06-13' mysql> SELECT CURDATE() + 0; -> 20080613
-
CURRENT_DATE
,CURRENT_DATE()
CURRENT_DATE
和CURRENT_DATE()
是CURDATE()
的同义词。 -
CURRENT_TIME
,CURRENT_TIME([*
fsp*])
CURRENT_TIME
和CURRENT_TIME()
是CURTIME()
的同义词。 -
CURRENT_TIMESTAMP
,CURRENT_TIMESTAMP([*
fsp*])
CURRENT_TIMESTAMP
和CURRENT_TIMESTAMP()
是NOW()
的同义词。 -
返回当前时间作为值,格式为
'hh:mm:ss'
或hhmmss
,取决于函数在字符串或数字上下文中的使用方式。该值以会话时区表示。如果给定
fsp
参数以指定从 0 到 6 的小数秒精度,则返回值包括相应数量的小数秒部分。mysql> SELECT CURTIME(); +-----------+ | CURTIME() | +-----------+ | 19:25:37 | +-----------+ mysql> SELECT CURTIME() + 0; +---------------+ | CURTIME() + 0 | +---------------+ | 192537 | +---------------+ mysql> SELECT CURTIME(3); +--------------+ | CURTIME(3) | +--------------+ | 19:25:37.840 | +--------------+
-
DATE(*
expr*)
提取日期或日期时间表达式
expr
的日期部分。如果expr
为NULL
,则返回NULL
。mysql> SELECT DATE('2003-12-31 01:02:03'); -> '2003-12-31'
-
DATEDIFF(*
expr1*,*
expr2*)
DATEDIFF()
返回expr1
和expr2
之间相差的天数值,以天数表示从一个日期到另一个日期。expr1
和expr2
是日期或日期时间表达式。计算中仅使用值的日期部分。mysql> SELECT DATEDIFF('2007-12-31 23:59:59','2007-12-30'); -> 1 mysql> SELECT DATEDIFF('2010-11-30 23:59:59','2010-12-31'); -> -31
如果
expr1
或expr2
为NULL
,此函数返回NULL
。 -
DATE_ADD(*
date*,INTERVAL *
expr* *
unit*)
,DATE_SUB(*
date*,INTERVAL *
expr* *
unit*)
这些函数执行日期算术运算。
date
参数指定起始日期或日期时间值。expr
是指定要从起始日期中添加或减去的间隔值的表达式。expr
被评估为字符串;它可以以-
开头表示负间隔。unit
是指示应解释表达式的单位的关键字。有关时间间隔语法的更多信息,包括完整的
unit
指定符列表,每个unit
值的expr
参数的预期形式,以及在时间算术中操作数解释的规则,请参阅时间间隔。返回值取决于参数:
-
如果
date
为NULL
,函数将返回NULL
。 -
如果
date
参数是DATE
值,并且您的计算仅涉及YEAR
、MONTH
和DAY
部分(即没有时间部分),则返回DATE
。 -
(MySQL 8.0.28 及更高版本:)如果
date
参数是TIME
值,并且计算仅涉及HOURS
、MINUTES
和SECONDS
部分(即没有日期部分),则返回TIME
。 -
如果第一个参数是
DATETIME
(或TIMESTAMP
)值,或者第一个参数是DATE
且unit
值使用HOURS
、MINUTES
或SECONDS
,或者第一个参数是TIME
且unit
值使用YEAR
、MONTH
或DAY
,则返回DATETIME
。 -
(MySQL 8.0.28 及更高版本:)如果第一个参数是动态参数(例如,准备语句的参数),且第二个参数是仅包含
YEAR
、MONTH
或DAY
值组合的间隔,则其解析类型为DATE
;否则,其类型为DATETIME
。 -
否则为字符串(类型
VARCHAR
)。
注意
在 MySQL 8.0.22 至 8.0.27 中,在准备语句中使用时,这些函数无论参数类型如何都返回
DATETIME
值。(Bug #103781)为了确保结果是
DATETIME
,您可以使用CAST()
将第一个参数转换为DATETIME
。mysql> SELECT DATE_ADD('2018-05-01',INTERVAL 1 DAY); -> '2018-05-02' mysql> SELECT DATE_SUB('2018-05-01',INTERVAL 1 YEAR); -> '2017-05-01' mysql> SELECT DATE_ADD('2020-12-31 23:59:59', -> INTERVAL 1 SECOND); -> '2021-01-01 00:00:00' mysql> SELECT DATE_ADD('2018-12-31 23:59:59', -> INTERVAL 1 DAY); -> '2019-01-01 23:59:59' mysql> SELECT DATE_ADD('2100-12-31 23:59:59', -> INTERVAL '1:1' MINUTE_SECOND); -> '2101-01-01 00:01:00' mysql> SELECT DATE_SUB('2025-01-01 00:00:00', -> INTERVAL '1 1:1:1' DAY_SECOND); -> '2024-12-30 22:58:59' mysql> SELECT DATE_ADD('1900-01-01 00:00:00', -> INTERVAL '-1 10' DAY_HOUR); -> '1899-12-30 14:00:00' mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY); -> '1997-12-02' mysql> SELECT DATE_ADD('1992-12-31 23:59:59.000002', -> INTERVAL '1.999999' SECOND_MICROSECOND); -> '1993-01-01 00:00:01.000001'
当向
DATE
或DATETIME
值添加MONTH
间隔时,并且结果日期包含给定月份中不存在的日期时,日期将调整为该月的最后一天,如下所示:mysql> SELECT DATE_ADD('2024-03-30', INTERVAL 1 MONTH) AS d1, > DATE_ADD('2024-03-31', INTERVAL 1 MONTH) AS d2; +------------+------------+ | d1 | d2 | +------------+------------+ | 2024-04-30 | 2024-04-30 | +------------+------------+ 1 row in set (0.00 sec)
-
-
DATE_FORMAT(*
date*,*
format*)
根据
format
字符串格式化date
值。如果任一参数为NULL
,函数将返回NULL
。下表中显示的指示符可用于
format
字符串。在格式指示符字符之前需要%
字符。这些指示符也适用于其他函数:STR_TO_DATE()
,TIME_FORMAT()
,UNIX_TIMESTAMP()
。指示符 描述 %a
缩写星期名称 ( Sun
..Sat
)%b
缩写月份名称 ( Jan
..Dec
)%c
月份,数字 ( 0
..12
)%D
带有英文后缀的日期 ( 0th
,1st
,2nd
,3rd
, …)%d
日期,数字 ( 00
..31
)%e
日期,数字 ( 0
..31
)%f
微秒 ( 000000
..999999
)%H
小时 ( 00
..23
)%h
小时 ( 01
..12
)%I
小时 ( 01
..12
)%i
分钟,数字 ( 00
..59
)%j
一年中的日期 ( 001
..366
)%k
小时 ( 0
..23
)%l
小时 ( 1
..12
)%M
月份名称 ( January
..December
)%m
月份,数字 ( 00
..12
)%p
AM
或PM
%r
时间,12 小时制 ( hh:mm:ss
后跟AM
或PM
)%S
秒数 ( 00
..59
)%s
秒数 ( 00
..59
)%T
时间,24 小时制 ( hh:mm:ss
)%U
周数 ( 00
..53
), 星期日为一周的第一天;WEEK()
模式 0%u
周数 ( 00
..53
), 星期一为一周的第一天;WEEK()
模式 1%V
周数 ( 01
..53
), 星期日为一周的第一天;WEEK()
模式 2; 与%X
一起使用%v
周数 ( 01
..53
), 星期一为一周的第一天;WEEK()
模式 3; 与%x
一起使用%W
星期名称 ( Sunday
..Saturday
)%w
星期几 ( 0
=星期日..6
=星期六)%X
一周的年份,星期日为一周的第一天,数字,四位数; 与 %V
一起使用%x
一周的年份,星期一为一周的第一天,数字,四位数; 与 %v
一起使用%Y
年份,数字,四位数 %y
年份,数字 (两位数) %%
一个字面上的 %
字符%*
x*
x
,对于上面未列出的任何“x
”指示符 描述 月份和日期指示符的范围从零开始,因为 MySQL 允许存储不完整的日期,如
'2014-00-00'
。用于日期和月份名称和缩写的语言由
lc_time_names
系统变量的值控制(第 12.16 节,“MySQL 服务器区域设置支持”)。对于
%U
、%u
、%V
和%v
格式说明符,请参阅WEEK()
函数的描述,了解有关模式值的信息。模式影响周编号的方式。DATE_FORMAT()
返回一个字符串,其中包含由character_set_connection
和collation_connection
给定的字符集和校对规则,以便返回包含非 ASCII 字符的月份和星期几名称。mysql> SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y'); -> 'Sunday October 2009' mysql> SELECT DATE_FORMAT('2007-10-04 22:23:00', '%H:%i:%s'); -> '22:23:00' mysql> SELECT DATE_FORMAT('1900-10-04 22:23:00', -> '%D %y %a %d %m %b %j'); -> '4th 00 Thu 04 10 Oct 277' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', -> '%H %k %I %r %T %S %w'); -> '22 22 10 10:23:00 PM 22:23:00 00 6' mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V'); -> '1998 52' mysql> SELECT DATE_FORMAT('2006-06-00', '%d'); -> '00'
-
DATE_SUB(*
date*,INTERVAL *
expr* *
unit*)
查看
DATE_ADD()
的描述。 -
DAY(*
date*)
DAY()
是DAYOFMONTH()
的同义词。 -
DAYNAME(*
date*)
返回
date
的星期几名称。名称所使用的语言由lc_time_names
系统变量的值控制(参见第 12.16 节,“MySQL 服务器区域设置支持”)。如果date
为NULL
,则返回NULL
。mysql> SELECT DAYNAME('2007-02-03'); -> 'Saturday'
-
DAYOFMONTH(*
date*)
返回
date
的月份中的日期,范围为1
到31
,对于日期如'0000-00-00'
或'2008-00-00'
等具有零日期部分的日期,返回0
。如果date
为NULL
,则返回NULL
。mysql> SELECT DAYOFMONTH('2007-02-03'); -> 3
-
DAYOFWEEK(*
date*)
返回
date
的星期索引(1
= 星期日,2
= 星期一,...,7
= 星期六)。这些索引值对应于 ODBC 标准。如果date
为NULL
,则返回NULL
。mysql> SELECT DAYOFWEEK('2007-02-03'); -> 7
-
DAYOFYEAR(*
date*)
返回
date
的一年中的日期,范围为1
到366
。如果date
为NULL
,则返回NULL
。mysql> SELECT DAYOFYEAR('2007-02-03'); -> 34
-
EXTRACT(*
unit* FROM *
date*)
EXTRACT()
函数使用与DATE_ADD()
或DATE_SUB()
相同类型的unit
说明符,但是从日期中提取部分而不是执行日期算数。有关unit
参数的信息,请参阅时间间隔。如果date
为NULL
,则返回NULL
。mysql> SELECT EXTRACT(YEAR FROM '2019-07-02'); -> 2019 mysql> SELECT EXTRACT(YEAR_MONTH FROM '2019-07-02 01:02:03'); -> 201907 mysql> SELECT EXTRACT(DAY_MINUTE FROM '2019-07-02 01:02:03'); -> 20102 mysql> SELECT EXTRACT(MICROSECOND -> FROM '2003-01-02 10:30:00.000123'); -> 123
-
FROM_DAYS(*
N*)
给定一个日期数
N
,返回一个DATE
值。如果N
为NULL
,则返回NULL
。mysql> SELECT FROM_DAYS(730669); -> '2000-07-03'
谨慎使用
FROM_DAYS()
处理旧日期。它不适用于格里高利历(1582 年之前)之前的值。请参阅第 13.2.7 节,“MySQL 使用的日历是什么?”。 -
FROM_UNIXTIME(*
unix_timestamp*[,*
format*])
将
unix_timestamp
表示为日期时间或字符字符串值。返回的值使用会话时区表示。(客户端可以设置会话时区,如第 7.1.15 节,“MySQL 服务器时区支持”中所述。)unix_timestamp
是一个内部时间戳值,表示自'1970-01-01 00:00:00'
UTC 以来的秒数,例如UNIX_TIMESTAMP()
函数生成的值。如果省略
format
,此函数将返回一个DATETIME
值。如果
unix_timestamp
或format
为NULL
,此函数将返回NULL
。如果
unix_timestamp
是整数,则DATETIME
的小数秒精度为零。当unix_timestamp
是十进制值时,DATETIME
的小数秒精度与十进制值的精度相同,最多为 6。当unix_timestamp
是浮点数时,日期时间的小数秒精度为 6。在 32 位平台上,
unix_timestamp
的最大有用值为 2147483647.999999,返回'2038-01-19 03:14:07.999999'
UTC。在运行 MySQL 8.0.28 或更高版本的 64 位平台上,有效最大值为 32536771199.999999,返回'3001-01-18 23:59:59.999999'
UTC。无论平台或版本如何,unix_timestamp
的值大于有效最大值都将返回0
。format
用于以与DATE_FORMAT()
函数使用的格式字符串相同的方式格式化结果。如果提供了format
,则返回的值是一个VARCHAR
。mysql> SELECT FROM_UNIXTIME(1447430881); -> '2015-11-13 10:08:01' mysql> SELECT FROM_UNIXTIME(1447430881) + 0; -> 20151113100801 mysql> SELECT FROM_UNIXTIME(1447430881, -> '%Y %D %M %h:%i:%s %x'); -> '2015 13th November 10:08:01 2015'
注意
如果您使用
UNIX_TIMESTAMP()
和FROM_UNIXTIME()
在非 UTC 时区和 Unix 时间戳值之间进行转换,转换是有损的,因为映射在两个方向上不是一对一的。有关详细信息,请参阅UNIX_TIMESTAMP()
函数的描述。 -
GET_FORMAT({DATE|TIME|DATETIME}, {'EUR'|'USA'|'JIS'|'ISO'|'INTERNAL'})
返回一个格式字符串。此函数与
DATE_FORMAT()
和STR_TO_DATE()
函数结合使用时很有用。如果
format
为NULL
,则此函数返回NULL
。第一个和第二个参数的可能值会导致多个可能的格式字符串(有关使用的占位符,请参见
DATE_FORMAT()
函数描述中的表格)。ISO 格式指的是 ISO 9075,而不是 ISO 8601。函数调用 结果 GET_FORMAT(DATE,'USA')
'%m.%d.%Y'
GET_FORMAT(DATE,'JIS')
'%Y-%m-%d'
GET_FORMAT(DATE,'ISO')
'%Y-%m-%d'
GET_FORMAT(DATE,'EUR')
'%d.%m.%Y'
GET_FORMAT(DATE,'INTERNAL')
'%Y%m%d'
GET_FORMAT(DATETIME,'USA')
'%Y-%m-%d %H.%i.%s'
GET_FORMAT(DATETIME,'JIS')
'%Y-%m-%d %H:%i:%s'
GET_FORMAT(DATETIME,'ISO')
'%Y-%m-%d %H:%i:%s'
GET_FORMAT(DATETIME,'EUR')
'%Y-%m-%d %H.%i.%s'
GET_FORMAT(DATETIME,'INTERNAL')
'%Y%m%d%H%i%s'
GET_FORMAT(TIME,'USA')
'%h:%i:%s %p'
GET_FORMAT(TIME,'JIS')
'%H:%i:%s'
GET_FORMAT(TIME,'ISO')
'%H:%i:%s'
GET_FORMAT(TIME,'EUR')
'%H.%i.%s'
GET_FORMAT(TIME,'INTERNAL')
'%H%i%s'
函数调用 结果 TIMESTAMP
也可以作为GET_FORMAT()
的第一个参数使用,此时函数返回与DATETIME
相同的值。mysql> SELECT DATE_FORMAT('2003-10-03',GET_FORMAT(DATE,'EUR')); -> '03.10.2003' mysql> SELECT STR_TO_DATE('10.31.2003',GET_FORMAT(DATE,'USA')); -> '2003-10-31'
-
HOUR(*
time*)
返回
time
的小时。对于一天中的时间值,返回值的范围是0
到23
。但是,TIME
值的范围实际上要大得多,因此HOUR
可能返回大于23
的值。如果time
为NULL
,则返回NULL
。mysql> SELECT HOUR('10:05:03'); -> 10 mysql> SELECT HOUR('272:59:59'); -> 272
-
LAST_DAY(*
date*)
获取一个日期或日期时间值,并返回该月的最后一天的相应值。如果参数无效或为
NULL
,则返回NULL
。mysql> SELECT LAST_DAY('2003-02-05'); -> '2003-02-28' mysql> SELECT LAST_DAY('2004-02-05'); -> '2004-02-29' mysql> SELECT LAST_DAY('2004-01-01 01:01:01'); -> '2004-01-31' mysql> SELECT LAST_DAY('2003-03-32'); -> NULL
-
LOCALTIME
,LOCALTIME([*
fsp*])
LOCALTIME
和LOCALTIME()
是NOW()
的同义词。 -
LOCALTIMESTAMP
,LOCALTIMESTAMP([*
fsp*])
LOCALTIMESTAMP
和LOCALTIMESTAMP()
是NOW()
的同义词。 -
MAKEDATE(*
year*,*
dayofyear*)
返回一个日期,给定年份和一年中的天数。
dayofyear
必须大于 0,否则结果为NULL
。如果任一参数为NULL
,结果也为NULL
。mysql> SELECT MAKEDATE(2011,31), MAKEDATE(2011,32); -> '2011-01-31', '2011-02-01' mysql> SELECT MAKEDATE(2011,365), MAKEDATE(2014,365); -> '2011-12-31', '2014-12-31' mysql> SELECT MAKEDATE(2011,0); -> NULL
-
MAKETIME(*
hour*,*
minute*,*
second*)
返回从
hour
、minute
和second
参数计算的时间值。如果任一参数为NULL
,则返回NULL
。second
参数可以有小数部分。mysql> SELECT MAKETIME(12,15,30); -> '12:15:30'
-
MICROSECOND(*
expr*)
返回从时间或日期时间表达式
expr
中计算的微秒,范围从0
到999999
的数字。如果expr
为NULL
,则返回NULL
。mysql> SELECT MICROSECOND('12:00:00.123456'); -> 123456 mysql> SELECT MICROSECOND('2019-12-31 23:59:59.000010'); -> 10
-
MINUTE(*
time*)
返回
time
的分钟,范围为0
到59
,如果time
为NULL
,则返回NULL
。mysql> SELECT MINUTE('2008-02-03 10:05:03'); -> 5
-
MONTH(*
date*)
返回
date
的月份,对于一月到十二月的范围为1
到12
,对于具有零月部分的日期(如'0000-00-00'
或'2008-00-00'
)为0
。如果date
为NULL
,则返回NULL
。mysql> SELECT MONTH('2008-02-03'); -> 2
-
MONTHNAME(*
date*)
返回
date
的月份的全名。名称的语言由lc_time_names
系统变量的值控制(第 12.16 节,“MySQL 服务器区域设置支持”)。如果date
为NULL
,则返回NULL
。mysql> SELECT MONTHNAME('2008-02-03'); -> 'February'
-
返回当前日期和时间作为一个值,格式为
'*
YYYY-MM-DD hh:mm:ss*'
或YYYYMMDDhhmmss
,取决于函数在字符串或数字上下文中的使用。该值以会话时区表示。如果给定
fsp
参数以指定从 0 到 6 的小数秒精度,则返回值包括相应数量的小数秒部分。mysql> SELECT NOW(); -> '2007-12-15 23:50:26' mysql> SELECT NOW() + 0; -> 20071215235026.000000
NOW()
返回一个常量时间,表示语句开始执行的时间。(在存储函数或触发器中,NOW()
返回函数或触发语句开始执行的时间。)这与SYSDATE()
的行为不同,后者返回执行时的确切时间。mysql> SELECT NOW(), SLEEP(2), NOW(); +---------------------+----------+---------------------+ | NOW() | SLEEP(2) | NOW() | +---------------------+----------+---------------------+ | 2006-04-12 13:47:36 | 0 | 2006-04-12 13:47:36 | +---------------------+----------+---------------------+ mysql> SELECT SYSDATE(), SLEEP(2), SYSDATE(); +---------------------+----------+---------------------+ | SYSDATE() | SLEEP(2) | SYSDATE() | +---------------------+----------+---------------------+ | 2006-04-12 13:47:44 | 0 | 2006-04-12 13:47:46 | +---------------------+----------+---------------------+
此外,
SET TIMESTAMP
语句会影响由NOW()
返回的值,但不会影响SYSDATE()
的返回值。这意味着二进制日志中的时间戳设置不会影响对SYSDATE()
的调用。将时间戳设置为非零值会导致每次后续调用NOW()
都返回该值。将时间戳设置为零会取消此效果,使得NOW()
再次返回当前日期和时间。有关这两个函数之间的差异的更多信息,请参阅
SYSDATE()
的描述。 -
PERIOD_ADD(*
P*,*
N*)
将
N
个月添加到格式为YYMM
或YYYYMM
的期间P
中。返回格式为YYYYMM
的值。注意
期间参数
P
不是日期值。如果
P
或N
为NULL
,则此函数返回NULL
。mysql> SELECT PERIOD_ADD(200801,2); -> 200803
-
PERIOD_DIFF(*
P1*,*
P2*)
返回期间
P1
和P2
之间的月份数。P1
和P2
应该是格式为YYMM
或YYYYMM
的值。请注意,期间参数P1
和P2
不是日期值。如果
P1
或P2
为NULL
,则此函数返回NULL
。mysql> SELECT PERIOD_DIFF(200802,200703); -> 11
-
QUARTER(*
date*)
返回
date
的年份季度,范围为1
到4
,如果date
为NULL
则返回NULL
。mysql> SELECT QUARTER('2008-04-01'); -> 2
-
SECOND(*
time*)
返回
time
的秒数,范围为0
到59
,如果time
为NULL
则返回NULL
。mysql> SELECT SECOND('10:05:03'); -> 3
-
SEC_TO_TIME(*
seconds*)
返回
seconds
参数转换为小时、分钟和秒的TIME
值。结果的范围受限于TIME
数据类型的范围。如果参数对应的值超出该范围,则会发出警告。如果
seconds
为NULL
,则函数返回NULL
。mysql> SELECT SEC_TO_TIME(2378); -> '00:39:38' mysql> SELECT SEC_TO_TIME(2378) + 0; -> 3938
-
STR_TO_DATE(*
str*,*
format*)
这是
DATE_FORMAT()
函数的反向操作。它接受一个字符串str
和一个格式字符串format
。如果格式字符串同时包含日期和时间部分,则STR_TO_DATE()
返回一个DATETIME
值,如果字符串仅包含日期或时间部分,则返回一个DATE
或TIME
值。如果str
或format
为NULL
,则函数返回NULL
。如果从str
中提取的日期、时间或日期时间值无法按照服务器遵循的规则解析,则STR_TO_DATE()
返回NULL
并生成警告。服务器扫描
str
,尝试将format
与其匹配。格式字符串可以包含文字字符和以%
开头的格式说明符。format
中的文字字符必须与str
中的文字字符完全匹配。format
中的格式说明符必须与str
中的日期或时间部分匹配。有关可用于format
中的说明符,请参见DATE_FORMAT()
函数说明。mysql> SELECT STR_TO_DATE('01,5,2013','%d,%m,%Y'); -> '2013-05-01' mysql> SELECT STR_TO_DATE('May 1, 2013','%M %d,%Y'); -> '2013-05-01'
扫描从
str
的开头开始,如果发现format
不匹配,则失败。str
末尾的额外字符将被忽略。mysql> SELECT STR_TO_DATE('a09:30:17','a%h:%i:%s'); -> '09:30:17' mysql> SELECT STR_TO_DATE('a09:30:17','%h:%i:%s'); -> NULL mysql> SELECT STR_TO_DATE('09:30:17a','%h:%i:%s'); -> '09:30:17'
未指定的日期或时间部分的值为 0,因此在
str
中未完全指定的值将产生一个结果,其中一些或所有部分设置为 0:mysql> SELECT STR_TO_DATE('abc','abc'); -> '0000-00-00' mysql> SELECT STR_TO_DATE('9','%m'); -> '0000-09-00' mysql> SELECT STR_TO_DATE('9','%s'); -> '00:00:09'
日期值的部分的范围检查如第 13.2.2 节,“日期、日期时间和时间戳类型”中所述。这意味着,例如,“零”日期或部分值为 0 的日期是允许的,除非 SQL 模式设置为不允许这些值。
mysql> SELECT STR_TO_DATE('00/00/0000', '%m/%d/%Y'); -> '0000-00-00' mysql> SELECT STR_TO_DATE('04/31/2004', '%m/%d/%Y'); -> '2004-04-31'
如果启用了
NO_ZERO_DATE
SQL 模式,则不允许零日期。在这种情况下,STR_TO_DATE()
返回NULL
并生成警告:mysql> SET sql_mode = ''; mysql> SELECT STR_TO_DATE('00/00/0000', '%m/%d/%Y'); +---------------------------------------+ | STR_TO_DATE('00/00/0000', '%m/%d/%Y') | +---------------------------------------+ | 0000-00-00 | +---------------------------------------+ mysql> SET sql_mode = 'NO_ZERO_DATE'; mysql> SELECT STR_TO_DATE('00/00/0000', '%m/%d/%Y'); +---------------------------------------+ | STR_TO_DATE('00/00/0000', '%m/%d/%Y') | +---------------------------------------+ | NULL | +---------------------------------------+ mysql> SHOW WARNINGS\G *************************** 1\. row *************************** Level: Warning Code: 1411 Message: Incorrect datetime value: '00/00/0000' for function str_to_date
在 MySQL 8.0.35 之前,可以将无效的日期字符串(例如
'2021-11-31'
)传递给此函数。在 MySQL 8.0.35 及更高版本中,STR_TO_DATE()
执行完整的范围检查,并在转换后的日期无效时引发错误。注意
你不能使用格式
"%X%V"
将年周字符串转换为日期,因为如果周跨越月边界,则年和周的组合不能唯一标识年和月。要将年周转换为日期,还应指定星期几:mysql> SELECT STR_TO_DATE('200442 Monday', '%X%V %W'); -> '2004-10-18'
您还应该注意,对于日期和日期时间值的日期部分,
STR_TO_DATE()
仅检查年、月和日的有效性。更准确地说,这意味着检查年份以确保它在 0-9999 的范围内,检查月份以确保它在 1-12 的范围内,检查日期以确保它在 1-31 的范围内,但服务器不会检查这些值的组合。例如,SELECT STR_TO_DATE('23-2-31', '%Y-%m-%d')
返回2023-02-31
。启用或禁用ALLOW_INVALID_DATES
服务器 SQL 模式对此行为没有影响。有关更多信息,请参阅第 13.2.2 节,“DATE、DATETIME 和 TIMESTAMP 类型”。 -
SUBDATE(*
date*,INTERVAL *
expr* *
unit*)
,SUBDATE(*
expr*,*
days*)
当使用第二个参数的
INTERVAL
形式调用时,SUBDATE()
是DATE_SUB()
的同义词。有关INTERVAL
unit
参数的信息,请参阅DATE_ADD()
的讨论。mysql> SELECT DATE_SUB('2008-01-02', INTERVAL 31 DAY); -> '2007-12-02' mysql> SELECT SUBDATE('2008-01-02', INTERVAL 31 DAY); -> '2007-12-02'
第二种形式允许使用整数值作为
days
。在这种情况下,它被解释为要从日期或日期时间表达式expr
中减去的天数。mysql> SELECT SUBDATE('2008-01-02 12:00:00', 31); -> '2007-12-02 12:00:00'
如果任何参数为
NULL
,则此函数返回NULL
。 -
SUBTIME(*
expr1*,*
expr2*)
SUBTIME()
返回expr1
−expr2
,以与expr1
相同格式的值表示。expr1
是时间或日期时间表达式,expr2
是时间表达式。此函数返回类型的分辨率与
ADDTIME()
函数的执行方式相同;有关更多信息,请参阅该函数的描述。mysql> SELECT SUBTIME('2007-12-31 23:59:59.999999','1 1:1:1.000002'); -> '2007-12-30 22:58:58.999997' mysql> SELECT SUBTIME('01:00:00.999999', '02:00:00.999998'); -> '-00:59:59.999999'
如果
expr1
或expr2
为NULL
,则此函数返回NULL
。 -
返回当前日期和时间作为值,格式为
'*
YYYY-MM-DD hh:mm:ss*'
或YYYYMMDDhhmmss
,具体取决于函数在字符串或数字上下文中的使用方式。如果给定
fsp
参数以指定从 0 到 6 的小数秒精度,则返回值包括该数量的小数秒部分。SYSDATE()
返回其执行时的时间。这与NOW()
的行为不同,后者返回指示语句开始执行的时间的常量时间。(在存储函数或触发器中,NOW()
返回函数或触发语句开始执行的时间。)mysql> SELECT NOW(), SLEEP(2), NOW(); +---------------------+----------+---------------------+ | NOW() | SLEEP(2) | NOW() | +---------------------+----------+---------------------+ | 2006-04-12 13:47:36 | 0 | 2006-04-12 13:47:36 | +---------------------+----------+---------------------+ mysql> SELECT SYSDATE(), SLEEP(2), SYSDATE(); +---------------------+----------+---------------------+ | SYSDATE() | SLEEP(2) | SYSDATE() | +---------------------+----------+---------------------+ | 2006-04-12 13:47:44 | 0 | 2006-04-12 13:47:46 | +---------------------+----------+---------------------+
此外,
SET TIMESTAMP
语句会影响NOW()
返回的值,但不会影响SYSDATE()
返回的值。这意味着二进制日志中的时间戳设置对SYSDATE()
的调用没有影响。因为
SYSDATE()
甚至在同一语句中可能返回不同的值,并且不受SET TIMESTAMP
的影响,因此它是不确定的,因此在使用基于语句的二进制日志记录时不安全。如果这是一个问题,您可以使用基于行的日志记录。或者,您可以使用
--sysdate-is-now
选项,使SYSDATE()
成为NOW()
的别名。如果在复制源服务器和副本上都使用该选项,则有效。SYSDATE()
的不确定性特性也意味着无法使用索引来评估引用它的表达式。 -
TIME(*
expr*)
提取时间或日期时间表达式
expr
的时间部分,并将其作为字符串返回。如果expr
为NULL
,则返回NULL
。此函数对基于语句的复制不安全。如果在
binlog_format
设置为STATEMENT
时使用此函数,将记录警告。mysql> SELECT TIME('2003-12-31 01:02:03'); -> '01:02:03' mysql> SELECT TIME('2003-12-31 01:02:03.000123'); -> '01:02:03.000123'
-
TIMEDIFF(*
expr1*,*
expr2*)
TIMEDIFF()
将expr1
−expr2
表示为时间值。expr1
和expr2
是转换为TIME
或DATETIME
表达式的字符串;在转换后,它们必须是相同类型的。如果expr1
或expr2
为NULL
,则返回NULL
。TIMEDIFF()
返回的结果受限于允许的TIME
值的范围。或者,您可以使用TIMESTAMPDIFF()
和UNIX_TIMESTAMP()
中的任一函数,两者都返回整数。mysql> SELECT TIMEDIFF('2000-01-01 00:00:00', -> '2000-01-01 00:00:00.000001'); -> '-00:00:00.000001' mysql> SELECT TIMEDIFF('2008-12-31 23:59:59.000001', -> '2008-12-30 01:01:01.000002'); -> '46:58:57.999999'
-
TIMESTAMP(*
expr*)
,TIMESTAMP(*
expr1*,*
expr2*)
使用单个参数时,该函数将日期或日期时间表达式
expr
作为日期时间值返回。使用两个参数时,它将时间表达式expr2
添加到日期或日期时间表达式expr1
中,并将结果作为日期时间值返回。如果expr
、expr1
或expr2
为NULL
,则返回NULL
。mysql> SELECT TIMESTAMP('2003-12-31'); -> '2003-12-31 00:00:00' mysql> SELECT TIMESTAMP('2003-12-31 12:00:00','12:00:00'); -> '2004-01-01 00:00:00'
-
TIMESTAMPADD(*
unit*,*
interval*,*
datetime_expr*)
将整数表达式
interval
添加到日期或日期时间表达式datetime_expr
中。interval
的单位由unit
参数给出,应为以下值之一:MICROSECOND
(微秒)、SECOND
、MINUTE
、HOUR
、DAY
、WEEK
、MONTH
、QUARTER
或YEAR
。unit
值可以使用如下所示的关键字之一指定,也可以使用SQL_TSI_
前缀。例如,DAY
和SQL_TSI_DAY
都是合法的。如果
interval
或datetime_expr
为NULL
,则此函数返回NULL
。mysql> SELECT TIMESTAMPADD(MINUTE, 1, '2003-01-02'); -> '2003-01-02 00:01:00' mysql> SELECT TIMESTAMPADD(WEEK,1,'2003-01-02'); -> '2003-01-09'
当向
DATE
或DATETIME
值添加MONTH
间隔时,如果结果日期包含给定月份中不存在的日期,则将日期调整为该月的最后一天,如下所示:mysql> SELECT TIMESTAMPADD(MONTH, 1, DATE '2024-03-30') AS t1, > TIMESTAMPADD(MONTH, 1, DATE '2024-03-31') AS t2; +------------+------------+ | t1 | t2 | +------------+------------+ | 2024-04-30 | 2024-04-30 | +------------+------------+ 1 row in set (0.00 sec)
-
TIMESTAMPDIFF(*
unit*,*
datetime_expr1*,*
datetime_expr2*)
返回
datetime_expr2
−datetime_expr1
,其中datetime_expr1
和datetime_expr2
是日期或日期时间表达式。一个表达式可以是日期,另一个可以是日期时间;日期值在必要时被视为具有时间部分'00:00:00'
的日期时间。结果(整数)的单位由unit
参数给出。unit
的合法值与TIMESTAMPADD()
函数的描述中列出的相同。如果
datetime_expr1
或datetime_expr2
为NULL
,则此函数返回NULL
。mysql> SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01'); -> 3 mysql> SELECT TIMESTAMPDIFF(YEAR,'2002-05-01','2001-01-01'); -> -1 mysql> SELECT TIMESTAMPDIFF(MINUTE,'2003-02-01','2003-05-01 12:05:55'); -> 128885
注意
该函数的日期或日期时间参数的顺序与使用 2 个参数调用
TIMESTAMP()
函数时相反。 -
TIME_FORMAT(*
time*,*
format*)
这类似于
DATE_FORMAT()
函数,但format
字符串可能仅包含有关小时、分钟、秒和微秒的格式说明符。其他说明符会产生NULL
或0
。如果time
或format
为NULL
,则TIME_FORMAT()
返回NULL
。如果
time
值包含大于23
的小时部分,则%H
和%k
小时格式说明符会产生大于通常范围的0..23
的值。其他小时格式说明符会将小时值对12
取模。mysql> SELECT TIME_FORMAT('100:00:00', '%H %k %h %I %l'); -> '100 100 04 04 4'
-
TIME_TO_SEC(*
time*)
返回将
time
参数转换为秒的结果。如果time
为NULL
,则返回NULL
。mysql> SELECT TIME_TO_SEC('22:23:00'); -> 80580 mysql> SELECT TIME_TO_SEC('00:39:38'); -> 2378
-
TO_DAYS(*
date*)
给定一个日期
date
,返回一个日期编号(自公元 0 年以来的天数)。如果date
为NULL
,则返回NULL
。mysql> SELECT TO_DAYS(950501); -> 728779 mysql> SELECT TO_DAYS('2007-10-07'); -> 733321
TO_DAYS()
不适用于格里高利历(1582 年)出现之前的值,因为它没有考虑到在日历更改时丢失的天数。对于 1582 年之前的日期(可能是其他地区的较晚年份),此函数的结果不可靠。有关详细信息,请参阅第 13.2.7 节,“MySQL 使用的日历是什么?”。请记住,MySQL 将日期中的两位年份值转换为四位形式,使用的规则在第 13.2 节,“日期和时间数据类型”中。例如,
'2008-10-07'
和'08-10-07'
被视为相同的日期:mysql> SELECT TO_DAYS('2008-10-07'), TO_DAYS('08-10-07'); -> 733687, 733687
在 MySQL 中,零日期被定义为
'0000-00-00'
,即使这个日期本身被认为是无效的。这意味着,对于'0000-00-00'
和'0000-01-01'
,TO_DAYS()
返回以下值:mysql> SELECT TO_DAYS('0000-00-00'); +-----------------------+ | to_days('0000-00-00') | +-----------------------+ | NULL | +-----------------------+ 1 row in set, 1 warning (0.00 sec) mysql> SHOW WARNINGS; +---------+------+----------------------------------------+ | Level | Code | Message | +---------+------+----------------------------------------+ | Warning | 1292 | Incorrect datetime value: '0000-00-00' | +---------+------+----------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT TO_DAYS('0000-01-01'); +-----------------------+ | to_days('0000-01-01') | +-----------------------+ | 1 | +-----------------------+ 1 row in set (0.00 sec)
无论是否启用
ALLOW_INVALID_DATES
SQL 服务器模式,这都是正确的。 -
TO_SECONDS(*
expr*)
给定一个日期或日期时间
expr
,返回自公元 0 年以来的秒数。如果expr
不是有效的日期或日期时间值(包括NULL
),则返回NULL
。mysql> SELECT TO_SECONDS(950501); -> 62966505600 mysql> SELECT TO_SECONDS('2009-11-29'); -> 63426672000 mysql> SELECT TO_SECONDS('2009-11-29 13:43:32'); -> 63426721412 mysql> SELECT TO_SECONDS( NOW() ); -> 63426721458
像
TO_DAYS()
一样,TO_SECONDS()
不适用于格里高利历(1582 年)出现之前的值,因为它没有考虑到在日历更改时丢失的天数。对于 1582 年之前的日期(可能是其他地区的较晚年份),此函数的结果不可靠。有关详细信息,请参阅第 13.2.7 节,“MySQL 使用的日历是什么?”。像
TO_DAYS()
一样,TO_SECONDS()
,将日期中的两位年份值转换为四位形式,使用的规则在第 13.2 节,“日期和时间数据类型”中。在 MySQL 中,零日期被定义为
'0000-00-00'
,即使这个日期本身被认为是无效的。这意味着,对于'0000-00-00'
和'0000-01-01'
,TO_SECONDS()
返回以下值:mysql> SELECT TO_SECONDS('0000-00-00'); +--------------------------+ | TO_SECONDS('0000-00-00') | +--------------------------+ | NULL | +--------------------------+ 1 row in set, 1 warning (0.00 sec) mysql> SHOW WARNINGS; +---------+------+----------------------------------------+ | Level | Code | Message | +---------+------+----------------------------------------+ | Warning | 1292 | Incorrect datetime value: '0000-00-00' | +---------+------+----------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT TO_SECONDS('0000-01-01'); +--------------------------+ | TO_SECONDS('0000-01-01') | +--------------------------+ | 86400 | +--------------------------+ 1 row in set (0.00 sec)
无论是否启用
ALLOW_INVALID_DATES
SQL 服务器模式,这都是正确的。 -
如果调用
UNIX_TIMESTAMP()
时没有date
参数,它将返回一个表示自'1970-01-01 00:00:00'
UTC 以来的秒数的 Unix 时间戳。如果使用
date
参数调用UNIX_TIMESTAMP()
,它将返回自'1970-01-01 00:00:00'
UTC 以来的秒数值。服务器将date
解释为会话时区中的值,并将其转换为 UTC 中的内部 Unix 时间戳值。(客户端可以根据第 7.1.15 节“MySQL 服务器时区支持”中的描述设置会话时区。)date
参数可以是DATE
、DATETIME
或TIMESTAMP
字符串,或以YYMMDD
、YYMMDDhhmmss
、YYYYMMDD
或YYYYMMDDhhmmss
格式的数字。如果参数包括时间部分,则可以选择包括小数秒部分。如果没有给定参数或参数不包括小数秒部分,则返回值为整数,或者给定包括小数秒部分的参数,则返回
DECIMAL
。当
date
参数是TIMESTAMP
列时,UNIX_TIMESTAMP()
直接返回内部时间戳值,没有隐式的“字符串到 Unix 时间戳”的转换。在 MySQL 8.0.28 之前,参数值的有效范围与
TIMESTAMP
数据类型相同:'1970-01-01 00:00:01.000000'
UTC 到'2038-01-19 03:14:07.999999'
UTC。对于运行在 64 位平台上的 MySQL 8.0.28 及更高版本,UNIX_TIMESTAMP()
的参数值的有效范围为'1970-01-01 00:00:01.000000'
UTC 到'3001-01-19 03:14:07.999999'
UTC(对应 32536771199.999999 秒)。无论 MySQL 版本或平台架构如何,如果将超出范围的日期传递给
UNIX_TIMESTAMP()
,它将返回0
。如果date
为NULL
,则返回NULL
。mysql> SELECT UNIX_TIMESTAMP(); -> 1447431666 mysql> SELECT UNIX_TIMESTAMP('2015-11-13 10:20:19'); -> 1447431619 mysql> SELECT UNIX_TIMESTAMP('2015-11-13 10:20:19.012'); -> 1447431619.012
如果使用
UNIX_TIMESTAMP()
和FROM_UNIXTIME()
在非协调世界时时区和 Unix 时间戳值之间进行转换,转换是有损的,因为映射在两个方向上不是一对一的。例如,由于夏令时等本地时区更改的惯例,可能导致UNIX_TIMESTAMP()
将两个在非协调世界时时区中不同的值映射到相同的 Unix 时间戳值。FROM_UNIXTIME()
将该值映射回原始值中的一个。以下是一个示例,使用在MET
时区中不同的值:mysql> SET time_zone = 'MET'; mysql> SELECT UNIX_TIMESTAMP('2005-03-27 03:00:00'); +---------------------------------------+ | UNIX_TIMESTAMP('2005-03-27 03:00:00') | +---------------------------------------+ | 1111885200 | +---------------------------------------+ mysql> SELECT UNIX_TIMESTAMP('2005-03-27 02:00:00'); +---------------------------------------+ | UNIX_TIMESTAMP('2005-03-27 02:00:00') | +---------------------------------------+ | 1111885200 | +---------------------------------------+ mysql> SELECT FROM_UNIXTIME(1111885200); +---------------------------+ | FROM_UNIXTIME(1111885200) | +---------------------------+ | 2005-03-27 03:00:00 | +---------------------------+
注意
要使用诸如
'MET'
或'Europe/Amsterdam'
之类的命名时区,必须正确设置时区表。有关说明,请参见第 7.1.15 节,“MySQL 服务器时区支持”。如果要减去
UNIX_TIMESTAMP()
列,可能需要将它们转换为有符号整数。参见第 14.10 节,“转换函数和运算符”。 -
UTC_DATE
,UTC_DATE()
返回当前的协调世界时日期作为一个值,格式为
'*
YYYY-MM-DD*'
或YYYYMMDD
,取决于函数在字符串或数字上下文中的使用方式。mysql> SELECT UTC_DATE(), UTC_DATE() + 0; -> '2003-08-14', 20030814
-
UTC_TIME
,UTC_TIME([*
fsp*])
返回当前的协调世界时时间作为一个值,格式为
'hh:mm:ss'
或hhmmss
,取决于函数在字符串或数字上下文中的使用方式。如果给定
fsp
参数以指定从 0 到 6 的小数秒精度,则返回值包括相应数量的小数秒部分。mysql> SELECT UTC_TIME(), UTC_TIME() + 0; -> '18:07:53', 180753.000000
-
UTC_TIMESTAMP
,UTC_TIMESTAMP([*
fsp*])
返回当前的协调世界时日期和时间作为一个值,格式为
'*
YYYY-MM-DD hh:mm:ss*'
或YYYYMMDDhhmmss
,取决于函数在字符串或数字上下文中的使用方式。如果给定
fsp
参数以指定从 0 到 6 的小数秒精度,则返回值包括相应数量的小数秒部分。mysql> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0; -> '2003-08-14 18:08:04', 20030814180804.000000
-
此函数返回
date
的周数。WEEK()
的两参数形式使您能够指定周从星期日或星期一开始,返回值应该在0
到53
或1
到53
的范围内。如果省略mode
参数,则使用default_week_format
系统变量的值。请参见第 7.1.8 节,“服务器系统变量”。对于NULL
日期值,函数返回NULL
。以下表描述了
mode
参数的工作方式。模式 一周的第一天 范围 第 1 周是第一周 … 0 星期日 0-53 今年有一个星期日 1 星期一 0-53 今年有 4 天或更多天 2 星期日 1-53 今年有一个星期日 3 星期一 1-53 今年有 4 天或更多天 4 星期日 0-53 今年有 4 天或更多天 5 星期一 0-53 今年有一个星期一 6 星期日 1-53 今年有 4 天或更多天 7 星期一 1-53 今年有一个星期一 对于具有“今年有 4 天或更多天”的
mode
值,周数按照 ISO 8601:1988 编号:-
如果包含 1 月 1 日的那一周有 4 天或更多天,那么它就是第 1 周。
-
否则,它就是上一年的最后一周,下一周就是第 1 周。
mysql> SELECT WEEK('2008-02-20'); -> 7 mysql> SELECT WEEK('2008-02-20',0); -> 7 mysql> SELECT WEEK('2008-02-20',1); -> 8 mysql> SELECT WEEK('2008-12-31',1); -> 53
如果一个日期落在上一年的最后一周,且您没有使用
2
、3
、6
或7
作为可选的mode
参数,则 MySQL 将返回0
:mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0); -> 2000, 0
有人可能会认为
WEEK()
应该返回52
,因为给定的日期实际上出现在 1999 年的第 52 周。但WEEK()
返回0
,以便返回值是“给定年份中的周数”。这使得当与从日期中提取日期部分的其他函数结合使用时,WEEK()
函数是可靠的。如果您希望结果相对于包含给定日期的一周的第一天的年份进行评估,请使用
0
、2
、5
或7
作为可选的mode
参数。mysql> SELECT WEEK('2000-01-01',2); -> 52
或者,使用
YEARWEEK()
函数:mysql> SELECT YEARWEEK('2000-01-01'); -> 199952 mysql> SELECT MID(YEARWEEK('2000-01-01'),5,2); -> '52'
-
-
WEEKDAY(*
date*)
返回
date
的星期索引(0
= 星期一,1
= 星期二,…6
= 星期日)。如果date
为NULL
,则返回NULL
。mysql> SELECT WEEKDAY('2008-02-03 22:23:00'); -> 6 mysql> SELECT WEEKDAY('2007-11-06'); -> 1
-
WEEKOFYEAR(*
date*)
返回日期的日历周作为范围从
1
到53
的数字。如果date
为NULL
,则返回NULL
。WEEKOFYEAR()
是一个兼容函数,等效于WEEK(*
date*,3)
。mysql> SELECT WEEKOFYEAR('2008-02-20'); -> 8
-
YEAR(*
date*)
返回
date
的年份,范围为1000
到9999
,或者对于“零”日期为0
。如果date
为NULL
,则返回NULL
。mysql> SELECT YEAR('1987-01-01'); -> 1987
-
YEARWEEK(*
date*)
,YEARWEEK(*
date*,*
mode*)
返回日期的年份和周数。结果中的年份可能与年份参数中的年份在一年中的第一周和最后一周不同。如果
date
为NULL
,则返回NULL
。mode
参数的工作方式与WEEK()
函数的mode
参数完全相同。对于单参数语法,使用mode
值为 0。与WEEK()
不同,default_week_format
的值不会影响YEARWEEK()
。mysql> SELECT YEARWEEK('1987-01-01'); -> 198652
周数与
WEEK()
函数对可选参数0
或1
返回的周数 (0
) 不同,因为WEEK()
然后返回给定年份上下文中的周数。
14.8 字符串函数和运算符
14.8.1 字符串比较函数和运算符
14.8.2 正则表达式
14.8.3 函数结果的字符集和排序规则
表 14.12 字符串函数和运算符
名称 | 描述 |
---|---|
ASCII() |
返回最左字符的数值 |
BIN() |
返回包含数字二进制表示的字符串 |
BIT_LENGTH() |
返回参数的位长度 |
CHAR() |
返回每个传递整数的字符 |
CHAR_LENGTH() |
返回参数中的字符数 |
CHARACTER_LENGTH() |
CHAR_LENGTH()的同义词 |
CONCAT() |
返回连接的字符串 |
CONCAT_WS() |
返回带有分隔符的连接字符串 |
ELT() |
返回索引号处的字符串 |
EXPORT_SET() |
返回一个字符串,对于值位设置的每个位,您会得到一个打开的字符串,对于未设置的位,您会得到一个关闭的字符串 |
FIELD() |
第一个参数在后续参数中的索引(位置) |
FIND_IN_SET() |
第一个参数在第二个参数中的索引(位置) |
FORMAT() |
返回格式化为指定小数位数的数字 |
FROM_BASE64() |
解码 base64 编码的字符串并返回结果 |
HEX() |
十进制或字符串值的十六进制表示 |
INSERT() |
在指定位置插入子字符串,最多指定数量的字符 |
INSTR() |
返回子字符串的第一个出现的索引 |
LCASE() |
LOWER()的同义词 |
LEFT() |
返回指定数量的最左字符 |
LENGTH() |
返回字符串的字节长度 |
LIKE |
简单的模式匹配 |
LOAD_FILE() |
加载指定文件 |
LOCATE() |
返回子字符串的第一个出现位置 |
LOWER() |
返回小写参数 |
LPAD() |
返回左侧填充了指定字符串的字符串参数 |
LTRIM() |
移除前导空格 |
MAKE_SET() |
返回一组逗号分隔的字符串,其中对应位在 bits 中设置 |
MATCH() |
执行全文搜索 |
MID() |
返回从指定位置开始的子字符串 |
NOT LIKE |
简单模式匹配的否定 |
NOT REGEXP |
REGEXP 的否定 |
OCT() |
返回包含数字的八进制表示的字符串 |
OCTET_LENGTH() |
LENGTH() 的同义词 |
ORD() |
返回参数的最左字符的字符代码 |
POSITION() |
LOCATE() 的同义词 |
QUOTE() |
为在 SQL 语句中使用而转义参数 |
REGEXP |
字符串是否匹配正则表达式 |
REGEXP_INSTR() |
返回匹配正则表达式的子字符串的起始索引 |
REGEXP_LIKE() |
字符串是否匹配正则表达式 |
REGEXP_REPLACE() |
替换与正则表达式匹配的子字符串 |
REGEXP_SUBSTR() |
返回匹配正则表达式的子字符串 |
REPEAT() |
重复指定次数的字符串 |
REPLACE() |
替换指定字符串的出现次数 |
REVERSE() |
反转字符串中的字符 |
RIGHT() |
返回指定右侧字符数 |
RLIKE |
字符串是否匹配正则表达式 |
RPAD() |
追加指定次数的字符串 |
RTRIM() |
移除尾部空格 |
SOUNDEX() |
返回一个 Soundex 字符串 |
SOUNDS LIKE |
比较声音 |
SPACE() |
返回指定数量的空格字符串 |
STRCMP() |
比较两个字符串 |
SUBSTR() |
返回指定的子字符串 |
SUBSTRING() |
返回指定的子字符串 |
SUBSTRING_INDEX() |
返回指定分隔符之前的字符串子串 |
TO_BASE64() |
返回转换为 base-64 字符串的参数 |
TRIM() |
删除前导和尾随空格 |
UCASE() |
UPPER()的同义词 |
UNHEX() |
返回包含数字的十六进制表示的字符串 |
UPPER() |
转换为大写 |
WEIGHT_STRING() |
返回字符串的权重字符串 |
名称 | 描述 |
如果结果的长度大于max_allowed_packet
系统变量的值,则返回NULL
。有关详细信息,请参阅第 7.1.1 节,“配置服务器”。
对于操作字符串位置的函数,第一个位置编号为 1。
对于需要长度参数的函数,非整数参数将四舍五入为最接近的整数。
-
ASCII(*
str*)
返回字符串
str
的最左字符的数值。如果str
为空字符串,则返回0
。如果str
为NULL
,则返回NULL
。ASCII()
适用于 8 位字符。mysql> SELECT ASCII('2'); -> 50 mysql> SELECT ASCII(2); -> 50 mysql> SELECT ASCII('dx'); -> 100
另请参见
ORD()
函数。 -
BIN(*
N*)
返回
N
的二进制值的字符串表示,其中N
是长整型(BIGINT
)数字。这等效于CONV(*
N*,10,2)
。如果N
为NULL
,则返回NULL
。mysql> SELECT BIN(12); -> '1100'
-
BIT_LENGTH(*
str*)
返回字符串
str
的位数。如果str
为NULL
,则返回NULL
。mysql> SELECT BIT_LENGTH('text'); -> 32
-
CHAR(*
N*,... [USING *
charset_name*])
CHAR()
将每个参数N
解释为整数,并返回由这些整数的代码值给出的字符组成的字符串。跳过NULL
值。mysql> SELECT CHAR(77,121,83,81,'76'); +--------------------------------------------------+ | CHAR(77,121,83,81,'76') | +--------------------------------------------------+ | 0x4D7953514C | +--------------------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT CHAR(77,77.3,'77.3'); +--------------------------------------------+ | CHAR(77,77.3,'77.3') | +--------------------------------------------+ | 0x4D4D4D | +--------------------------------------------+ 1 row in set (0.00 sec)
默认情况下,
CHAR()
返回一个二进制字符串。要生成给定字符集中的字符串,请使用可选的USING
子句:mysql> SELECT CHAR(77,121,83,81,'76' USING utf8mb4); +---------------------------------------+ | CHAR(77,121,83,81,'76' USING utf8mb4) | +---------------------------------------+ | MySQL | +---------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT CHAR(77,77.3,'77.3' USING utf8mb4); +------------------------------------+ | CHAR(77,77.3,'77.3' USING utf8mb4) | +------------------------------------+ | MMM | +------------------------------------+ 1 row in set, 1 warning (0.00 sec) mysql> SHOW WARNINGS; +---------+------+-------------------------------------------+ | Level | Code | Message | +---------+------+-------------------------------------------+ | Warning | 1292 | Truncated incorrect INTEGER value: '77.3' | +---------+------+-------------------------------------------+ 1 row in set (0.00 sec)
如果提供了
USING
并且结果字符串对于给定的字符集是非法的,则会发出警告。此外,如果启用了严格的 SQL 模式,则CHAR()
的结果将变为NULL
。如果从mysql客户端内调用
CHAR()
,二进制字符串将根据--binary-as-hex
的值以十六进制表示。有关该选项的更多信息,请参见 Section 6.5.1, “mysql — The MySQL Command-Line Client”。大于 255 的
CHAR()
参数将转换为多个结果字节。例如,CHAR(256)
等同于CHAR(1,0)
,而CHAR(256*256)
等同于CHAR(1,0,0)
:mysql> SELECT HEX(CHAR(1,0)), HEX(CHAR(256)); +----------------+----------------+ | HEX(CHAR(1,0)) | HEX(CHAR(256)) | +----------------+----------------+ | 0100 | 0100 | +----------------+----------------+ 1 row in set (0.00 sec) mysql> SELECT HEX(CHAR(1,0,0)), HEX(CHAR(256*256)); +------------------+--------------------+ | HEX(CHAR(1,0,0)) | HEX(CHAR(256*256)) | +------------------+--------------------+ | 010000 | 010000 | +------------------+--------------------+ 1 row in set (0.00 sec)
-
CHAR_LENGTH(*
str*)
返回
str
的字符串长度,以代码点计算。多字节字符计为一个代码点。这意味着,对于包含两个 3 字节字符的字符串,LENGTH()
返回6
,而CHAR_LENGTH()
返回2
,如下所示:mysql> SET @dolphin:='海豚'; Query OK, 0 rows affected (0.01 sec) mysql> SELECT LENGTH(@dolphin), CHAR_LENGTH(@dolphin); +------------------+-----------------------+ | LENGTH(@dolphin) | CHAR_LENGTH(@dolphin) | +------------------+-----------------------+ | 6 | 2 | +------------------+-----------------------+ 1 row in set (0.00 sec)
如果
str
为NULL
,则CHAR_LENGTH()
返回NULL
。 -
CHARACTER_LENGTH(*
str*)
CHARACTER_LENGTH()
是CHAR_LENGTH()
的同义词。 -
CONCAT(*
str1*,*
str2*,...)
返回从连接参数结果的字符串。可能有一个或多个参数。如果所有参数都是非二进制字符串,则结果是非二进制字符串。如果参数包含任何二进制字符串,则结果是二进制字符串。数值参数转换为其等效的非二进制字符串形式。
如果任何参数为
NULL
,CONCAT()
返回NULL
。mysql> SELECT CONCAT('My', 'S', 'QL'); -> 'MySQL' mysql> SELECT CONCAT('My', NULL, 'QL'); -> NULL mysql> SELECT CONCAT(14.3); -> '14.3'
对于带引号的字符串,可以通过将字符串放在一起来执行连接:
mysql> SELECT 'My' 'S' 'QL'; -> 'MySQL'
如果从mysql客户端内调用
CONCAT()
,二进制字符串结果将根据--binary-as-hex
的值以十六进制表示。有关该选项的更多信息,请参见 Section 6.5.1, “mysql — The MySQL Command-Line Client”。 -
CONCAT_WS(*
分隔符*,*
str1*,*
str2*,...)
CONCAT_WS()
代表带分隔符连接,是CONCAT()
的特殊形式。第一个参数是其余参数的分隔符。分隔符添加在要连接的字符串之间。分隔符可以是字符串,其余参数也可以是字符串。如果分隔符为NULL
,则结果为NULL
。mysql> SELECT CONCAT_WS(',','First name','Second name','Last Name'); -> 'First name,Second name,Last Name' mysql> SELECT CONCAT_WS(',','First name',NULL,'Last Name'); -> 'First name,Last Name'
CONCAT_WS()
不会跳过空字符串。但是,在分隔符参数之后,它会跳过任何NULL
值。 -
ELT(*
N*,*
str1*,*
str2*,*
str3*,...)
ELT()
返回字符串列表中第N
个元素:如果N
=1
,则返回str1
,如果N
=2
,则返回str2
,依此类推。如果N
小于1
,大于参数数量或为NULL
,则返回NULL
。ELT()
是FIELD()
的补充。mysql> SELECT ELT(1, 'Aa', 'Bb', 'Cc', 'Dd'); -> 'Aa' mysql> SELECT ELT(4, 'Aa', 'Bb', 'Cc', 'Dd'); -> 'Dd'
-
EXPORT_SET(*
bits*,*
on*,*
off*[,*
separator*[,*
number_of_bits*]])
返回一个字符串,对于值
bits
中设置的每个位,您会得到一个on
字符串,对于值中未设置的每个位,您会得到一个off
字符串。从右到左(从低位到高位)检查bits
中的位。字符串从左到右添加到结果中,由separator
字符串分隔(默认为逗号字符,
)。检查的位数由number_of_bits
给出,如果未指定,默认为64
。如果number_of_bits
大于64
,则会被静默截断为64
。它被视为无符号整数,因此值为−1 实际上等同于64
。mysql> SELECT EXPORT_SET(5,'Y','N',',',4); -> 'Y,N,Y,N' mysql> SELECT EXPORT_SET(6,'1','0',',',10); -> '0,1,1,0,0,0,0,0,0,0'
-
FIELD(*
str*,*
str1*,*
str2*,*
str3*,...)
返回
str
在str1
、str2
、str3
、...
列表中的索引(位置)。如果未找到str
,则返回0
。如果
FIELD()
的所有参数都是字符串,则所有参数将作为字符串进行比较。如果所有参数都是数字,则它们将作为数字进行比较。否则,参数将作为双精度数进行比较。如果
str
为NULL
,则返回值为0
,因为NULL
与任何值的相等比较失败。FIELD()
是ELT()
的补充。mysql> SELECT FIELD('Bb', 'Aa', 'Bb', 'Cc', 'Dd', 'Ff'); -> 2 mysql> SELECT FIELD('Gg', 'Aa', 'Bb', 'Cc', 'Dd', 'Ff'); -> 0
-
FIND_IN_SET(*
str*,*
strlist*)
如果字符串
str
在由N
个子字符串组成的字符串列表strlist
中,则返回 1 到N
的值。字符串列表是由,
字符分隔的子字符串组成的字符串。如果第一个参数是常量字符串,第二个参数是SET
类型的列,则FIND_IN_SET()
函数会优化使用位运算。如果str
不在strlist
中或strlist
为空字符串,则返回0
。如果任一参数为NULL
,则返回NULL
。如果第一个参数包含逗号(,
)字符,则此函数无法正常工作。mysql> SELECT FIND_IN_SET('b','a,b,c,d'); -> 2
-
将数字
X
格式化为类似'#,###,###.##'
的格式,四舍五入到D
位小数,并将结果作为字符串返回。如果D
为0
,则结果没有小数点或小数部分。如果X
或D
为NULL
,则函数返回NULL
。可选的第三个参数允许指定要用于结果数字的小数点、千位分隔符和分隔符之间的分组的区域设置。允许的区域设置值与
lc_time_names
系统变量的合法值相同(请参阅第 12.16 节,“MySQL 服务器区域设置支持”)。如果区域设置为NULL
或未指定,则默认区域设置为'en_US'
。mysql> SELECT FORMAT(12332.123456, 4); -> '12,332.1235' mysql> SELECT FORMAT(12332.1,4); -> '12,332.1000' mysql> SELECT FORMAT(12332.2,0); -> '12,332' mysql> SELECT FORMAT(12332.2,2,'de_DE'); -> '12.332,20'
-
FROM_BASE64(*
str*)
将一个使用
TO_BASE64()
使用的 base-64 编码规则编码的字符串解码,并将解码结果作为二进制字符串返回。如果参数为NULL
或不是有效的 base-64 字符串,则结果为NULL
。有关编码和解码规则的详细信息,请参阅TO_BASE64()
的描述。mysql> SELECT TO_BASE64('abc'), FROM_BASE64(TO_BASE64('abc')); -> 'JWJj', 'abc'
如果在mysql客户端内部调用
FROM_BASE64()
,二进制字符串将使用十六进制表示。您可以通过在启动mysql客户端时将--binary-as-hex
的值设置为0
来禁用此行为。有关该选项的更多信息,请参阅第 6.5.1 节,“mysql — The MySQL Command-Line Client”。 -
HEX(*
str*)
,HEX(*
N*)
对于字符串参数
str
,HEX()
返回一个十六进制字符串表示str
,其中str
中每个字符的每个字节都转换为两个十六进制数字。(因此,多字节字符会变成两个以上的数字。)此操作的逆操作由UNHEX()
函数执行。对于数值参数
N
,HEX()
返回将N
的值视为长整型(BIGINT
- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"))数字的十六进制字符串表示。这等效于CONV(*
N*,10,16)
。此操作的逆操作由CONV(HEX(*
N*),16,10)
执行。对于
NULL
参数,此函数返回NULL
。mysql> SELECT X'616263', HEX('abc'), UNHEX(HEX('abc')); -> 'abc', 616263, 'abc' mysql> SELECT HEX(255), CONV(HEX(255),16,10); -> 'FF', 255
-
INSERT(*
str*,*
pos*,*
len*,*
newstr*)
返回字符串
str
,从位置pos
开始的子字符串,长度为len
个字符,被字符串newstr
替换。如果pos
不在字符串长度范围内,则返回原始字符串。如果len
不在剩余字符串的长度范围内,则从位置pos
开始替换剩余字符串。如果任何参数为NULL
,则返回NULL
。mysql> SELECT INSERT('Quadratic', 3, 4, 'What'); -> 'QuWhattic' mysql> SELECT INSERT('Quadratic', -1, 4, 'What'); -> 'Quadratic' mysql> SELECT INSERT('Quadratic', 3, 100, 'What'); -> 'QuWhat'
此函数支持多字节字符。
-
INSTR(*
str*,*
substr*)
返回字符串
str
中子字符串substr
第一次出现的位置。这与LOCATE()
的两参数形式相同,只是参数的顺序相反。mysql> SELECT INSTR('foobarbar', 'bar'); -> 4 mysql> SELECT INSTR('xbar', 'foobar'); -> 0
此函数支持多字节字符,仅在至少一个参数为二进制字符串时区分大小写。如果任一参数为
NULL
,此函数返回NULL
。 -
LCASE(*
str*)
LCASE()
是LOWER()
的同义词。在视图中使用的
LCASE()
在存储视图定义时会被重写为LOWER()
。(Bug #12844279) -
LEFT(*
str*,*
len*)
返回字符串
str
中最左边的len
个字符,如果任何参数为NULL
,则返回NULL
。mysql> SELECT LEFT('foobarbar', 5); -> 'fooba'
此函数支持多字节字符。
-
LENGTH(*
str*)
返回字符串
str
的长度,以字节为单位。多字节字符计为多个字节。这意味着对于包含五个 2 字节字符的字符串,LENGTH()
返回10
,而CHAR_LENGTH()
返回5
。如果str
为NULL
,则返回NULL
。mysql> SELECT LENGTH('text'); -> 4
注意
Length()
OpenGIS 空间函数在 MySQL 中被命名为ST_Length()
。 -
LOAD_FILE(*
file_name*)
读取文件并将文件内容作为字符串返回。要使用此函数,文件必须位于服务器主机上,必须指定文件的完整路径名,并且必须具有
FILE
权限。文件必须可被服务器读取,且其大小必须小于max_allowed_packet
字节。如果secure_file_priv
系统变量设置为非空目录名称,则要加载的文件必须位于该目录中。(在 MySQL 8.0.17 之前,文件必须可被所有人读取,而不仅仅是服务器可读取。)如果文件不存在或由于不满足前述条件之一而无法读取,则函数返回
NULL
。character_set_filesystem
系统变量控制给定为文字字符串的文件名的解释。mysql> UPDATE t SET blob_col=LOAD_FILE('/tmp/picture') WHERE id=1;
-
LOCATE(*
substr*,*
str*)
,LOCATE(*
substr*,*
str*,*
pos*)
第一个语法返回子字符串
substr
在字符串str
中第一次出现的位置。第二个语法返回子字符串substr
在字符串str
中从位置pos
开始第一次出现的位置。如果str
中没有substr
,则返回0
。如果任何参数为NULL
,则返回NULL
。mysql> SELECT LOCATE('bar', 'foobarbar'); -> 4 mysql> SELECT LOCATE('xbar', 'foobar'); -> 0 mysql> SELECT LOCATE('bar', 'foobarbar', 5); -> 7
此函数是多字节安全的,仅在至少一个参数为二进制字符串时区分大小写。
-
LOWER(*
str*)
返回根据当前字符集映射将所有字符更改为小写的字符串
str
,如果str
为NULL
,则返回NULL
。默认字符集为utf8mb4
。mysql> SELECT LOWER('QUADRATICALLY'); -> 'quadratically'
当应用于二进制字符串(
BINARY
,VARBINARY
,BLOB
)时,LOWER()
(和UPPER()
)是无效的。要对二进制字符串执行大小写转换,首先使用适合存储在字符串中的数据的字符集将其转换为非二进制字符串:mysql> SET @str = BINARY 'New York'; mysql> SELECT LOWER(@str), LOWER(CONVERT(@str USING utf8mb4)); +-------------+------------------------------------+ | LOWER(@str) | LOWER(CONVERT(@str USING utf8mb4)) | +-------------+------------------------------------+ | New York | new york | +-------------+------------------------------------+
对于 Unicode 字符集的排序规则,如果在排序规则名称中指定了 Unicode 排序算法(UCA)版本,则
LOWER()
和UPPER()
将按照该版本的 UCA 工作,如果未指定版本,则按照 UCA 4.0.0 工作。例如,utf8mb4_0900_ai_ci
和utf8mb3_unicode_520_ci
分别按照 UCA 9.0.0 和 5.2.0 工作,而utf8mb3_unicode_ci
按照 UCA 4.0.0 工作。参见第 12.10.1 节,“Unicode 字符集”。此函数是多字节安全的。
在视图中使用的
LCASE()
被重写为LOWER()
。 -
LPAD(*
str*,*
len*,*
padstr*)
返回左填充了字符串
padstr
到长度为len
字符的字符串str
。如果str
比len
长,则返回值被缩短为len
个字符。mysql> SELECT LPAD('hi',4,'??'); -> '??hi' mysql> SELECT LPAD('hi',1,'??'); -> 'h'
如果其任何参数为
NULL
,则返回NULL
。 -
LTRIM(*
str*)
返回去除前导空格字符的字符串
str
。如果str
为NULL
,则返回NULL
。mysql> SELECT LTRIM(' barbar'); -> 'barbar'
此函数是多字节安全的。
-
MAKE_SET(*
bits*,*
str1*,*
str2*,...)
返回一个集合值(一个包含由
,
字符分隔的子字符串的字符串),其中包含具有对应位在bits
中设置的字符串。str1
对应于位 0,str2
对应于位 1,依此类推。str1
、str2
、...
中的NULL
值不会附加到结果中。mysql> SELECT MAKE_SET(1,'a','b','c'); -> 'a' mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world'); -> 'hello,world' mysql> SELECT MAKE_SET(1 | 4,'hello','nice',NULL,'world'); -> 'hello' mysql> SELECT MAKE_SET(0,'a','b','c'); -> ''
-
MID(*
str*,*
pos*,*
len*)
MID(*
str*,*
pos*,*
len*)
是SUBSTRING(*
str*,*
pos*,*
len*)
的同义词。 -
OCT(*
N*)
返回
N
的八进制值的字符串表示,其中N
是一个长长整型(BIGINT
)数字。这等同于CONV(*
N*,10,8)
。如果N
为NULL
,则返回NULL
。mysql> SELECT OCT(12); -> '14'
-
OCTET_LENGTH(*
str*)
OCTET_LENGTH()
是LENGTH()
的同义词。 -
ORD(*
str*)
如果字符串
str
的最左边字符是一个多字节字符,则返回该字符的代码,使用以下公式从其组成字节的数值计算:(1st byte code) + (2nd byte code * 256) + (3rd byte code * 256²) ...
如果最左边的字符不是一个多字节字符,
ORD()
返回与ASCII()
函数相同的值。如果str
为NULL
,则函数返回NULL
。mysql> SELECT ORD('2'); -> 50
-
POSITION(*
substr* IN *
str*)
POSITION(*
substr* IN *
str*)
是LOCATE(*
substr*,*
str*)
的同义词。 -
QUOTE(*
str*)
引用一个字符串以生成一个结果,该结果可以作为 SQL 语句中的正确转义数据值使用。返回的字符串用单引号括起来,并且每个反斜杠(
\
)、单引号('
)、ASCIINUL
和 Control+Z 的实例前面都有一个反斜杠。如果参数为NULL
,返回值是不用单引号括起来的单词NULL
。mysql> SELECT QUOTE('Don\'t!'); -> 'Don\'t!' mysql> SELECT QUOTE(NULL); -> NULL
有关比较,请参阅第 11.1.1 节,“字符串文字”中的文字引用规则以及 C API 中的 mysql_real_escape_string_quote()。
-
REPEAT(*
str*,*
count*)
返回由字符串
str
重复count
次组成的字符串。如果count
小于 1,则返回空字符串。如果str
或count
是NULL
,则返回NULL
。mysql> SELECT REPEAT('MySQL', 3); -> 'MySQLMySQLMySQL'
-
REPLACE(*
str*,*
from_str*,*
to_str*)
返回将所有出现的字符串
from_str
替换为字符串to_str
的字符串str
。在搜索from_str
时,REPLACE()
执行区分大小写的匹配。mysql> SELECT REPLACE('www.mysql.com', 'w', 'Ww'); -> 'WwWwWw.mysql.com'
这个函数是多字节安全的。如果任何参数是
NULL
,则返回NULL
。 -
REVERSE(*
str*)
返回字符串
str
的字符顺序颠倒,如果str
是NULL
,则返回NULL
。mysql> SELECT REVERSE('abc'); -> 'cba'
这个函数是多字节安全的。
-
RIGHT(*
str*,*
len*)
返回字符串
str
中最右边的len
个字符,如果任何参数���NULL
,则返回NULL
。mysql> SELECT RIGHT('foobarbar', 4); -> 'rbar'
这个函数是多字节安全的。
-
RPAD(*
str*,*
len*,*
padstr*)
返回字符串
str
,右侧用字符串padstr
填充到长度为len
个字符。如果str
比len
长,则返回值被缩短为len
个字符。如果str
、padstr
或len
是NULL
,则函数返回NULL
。mysql> SELECT RPAD('hi',5,'?'); -> 'hi???' mysql> SELECT RPAD('hi',1,'?'); -> 'h'
这个函数是多字节安全的。
-
RTRIM(*
str*)
返回删除尾随空格字符的字符串
str
。mysql> SELECT RTRIM('barbar '); -> 'barbar'
这个函数是多字节安全的,如果
str
是NULL
,则返回NULL
。 -
SOUNDEX(*
str*)
从
str
返回一个 soundex 字符串,如果str
是NULL
,则返回NULL
。两个听起来几乎相同的字符串应该具有相同的 soundex 字符串。标准的 soundex 字符串长度为四个字符,但SOUNDEX()
函数返回一个任意长的字符串。您可以对结果使用SUBSTRING()
来获取标准的 soundex 字符串。str
中的所有非字母字符都将被忽略。所有 A-Z 范围之外的国际字母字符都被视为元音。重要
在使用
SOUNDEX()
时,您应该注意以下限制:-
此函数目前的实现仅适用于英语语言的字符串。其他语言的字符串可能产生不可靠的结果。
-
不能保证此函数与使用多字节字符集(包括
utf-8
)的字符串提供一致的结果。有关更多信息,请参见 Bug #22638。
mysql> SELECT SOUNDEX('Hello'); -> 'H400' mysql> SELECT SOUNDEX('Quadratically'); -> 'Q36324'
注意
此函数实现原始 Soundex 算法,而不是更流行的增强版本(也由 D. Knuth 描述)。区别在于原始版本首先丢弃元音,其次是重复字符,而增强版本首先丢弃重复字符,其次是元音。
-
-
*
expr1* SOUNDS LIKE *
expr2*
这与
SOUNDEX(*
expr1*) = SOUNDEX(*
expr2*)
相同。 -
SPACE(*
N*)
返回由
N
个空格字符组成的字符串,如果N
为NULL
,则返回NULL
。mysql> SELECT SPACE(6); -> ' '
-
SUBSTR(*
str*,*
pos*)
,SUBSTR(*
str* FROM *
pos*)
,SUBSTR(*
str*,*
pos*,*
len*)
,SUBSTR(*
str* FROM *
pos* FOR *
len*)
SUBSTR()
是SUBSTRING()
的同义词。 -
SUBSTRING(*
str*,*
pos*)
,SUBSTRING(*
str* FROM *
pos*)
,SUBSTRING(*
str*,*
pos*,*
len*)
,SUBSTRING(*
str* FROM *
pos* FOR *
len*)
没有
len
参数的形式返回从位置pos
开始的字符串str
的子字符串。有len
参数的形式返回从位置pos
开始,长度为len
的子字符串。使用FROM
的形式是标准的 SQL 语法。也可以对pos
使用负值。在这种情况下,子字符串的开头是距离字符串末尾pos
个字符,而不是距离开头。在这个函数的任何形式中,pos
都可以使用负值。pos
的值为 0 时返回空字符串。对于
SUBSTRING()
的所有形式,要提取子字符串的字符串中第一个字符的位置被认为是1
。mysql> SELECT SUBSTRING('Quadratically',5); -> 'ratically' mysql> SELECT SUBSTRING('foobarbar' FROM 4); -> 'barbar' mysql> SELECT SUBSTRING('Quadratically',5,6); -> 'ratica' mysql> SELECT SUBSTRING('Sakila', -3); -> 'ila' mysql> SELECT SUBSTRING('Sakila', -5, 3); -> 'aki' mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2); -> 'ki'
此函数是多字节安全的。如果其任何参数为
NULL
,则返回NULL
。如果
len
小于 1,则结果为空字符串。 -
SUBSTRING_INDEX(*
str*,*
delim*,*
count*)
返回字符串
str
中在定界符delim
出现count
次之前的子字符串。如果count
为正数,则返回最终定界符(从左边计数)左侧的所有内容。如果count
为负数,则返回最终定界符(从右边计数)右侧的所有内容。在搜索delim
时,SUBSTRING_INDEX()
执行区分大小写的匹配。mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2); -> 'www.mysql' mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2); -> 'mysql.com'
此函数是多字节安全的。
如果
SUBSTRING_INDEX()
的任何参数为NULL
,则返回NULL
。 -
TO_BASE64(*
str*)
将字符串参数转换为 base-64 编码形式,并将结果作为具有连接字符集和排序规则的字符字符串返回。如果参数不是字符串,则在进行转换之前将其转换为字符串。如果参数为
NULL
,则结果为NULL
。可以使用FROM_BASE64()
函数解码 base-64 编码的字符串。mysql> SELECT TO_BASE64('abc'), FROM_BASE64(TO_BASE64('abc')); -> 'JWJj', 'abc'
存在不同的 base-64 编码方案。这些是
TO_BASE64()
和FROM_BASE64()
使用的编码和解码规则:-
字母值为 62 的编码为
'+'
。 -
字母值为 63 的编码为
'/'
。 -
编码输出由 4 个可打印字符组成。每 3 个字节的输入数据使用 4 个字符进行编码。如果最后一组不完整,则使用
'='
字符填充至长度为 4。 -
每 76 个编码输出字符后添加一个换行符,将长输出分成多行。
-
解码识别并忽略换行符、回车符、制表符和空格。
-
-
TRIM([{BOTH | LEADING | TRAILING} [*
remstr*] FROM] *
str*)
,TRIM([*
remstr* FROM] *
str*)
返回去除所有
remstr
前缀或后缀的字符串str
。如果未给出BOTH
、LEADING
或TRAILING
中的任何一个标识符,则假定为BOTH
。remstr
是可选的,如果未指定,则删除空格。mysql> SELECT TRIM(' bar '); -> 'bar' mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx'); -> 'barxxx' mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx'); -> 'bar' mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz'); -> 'barx'
此函数是多字节安全的。如果其任何参数为
NULL
,则返回NULL
。 -
UCASE(*
str*)
UCASE()
是UPPER()
的同义词。在视图中使用的
UCASE()
会被重写为UPPER()
。 -
UNHEX(*
str*)
对于字符串参数
str
,UNHEX(*
str*)
将参数中的每对字符解释为十六进制数,并将其转换为由该数字表示的字节。返回值是一个二进制字符串。mysql> SELECT UNHEX('4D7953514C'); -> 'MySQL' mysql> SELECT X'4D7953514C'; -> 'MySQL' mysql> SELECT UNHEX(HEX('string')); -> 'string' mysql> SELECT HEX(UNHEX('1267')); -> '1267'
参数字符串中的字符必须是合法的十六进制数字:
'0'
..'9'
,'A'
..'F'
,'a'
..'f'
。如果参数包含任何非十六进制数字,或者本身为NULL
,则结果为NULL
:mysql> SELECT UNHEX('GG'); +-------------+ | UNHEX('GG') | +-------------+ | NULL | +-------------+ mysql> SELECT UNHEX(NULL); +-------------+ | UNHEX(NULL) | +-------------+ | NULL | +-------------+
如果
UNHEX()
的参数是BINARY
列,则还可能出现NULL
结果,因为存储时值会使用0x00
字节进行填充,但在检索时这些字节不会被去除。例如,'41'
被存储到CHAR(3)
列中为'41 '
,检索时为'41'
(去除了尾随填充空格),因此列值的UNHEX()
返回X'41'
。相比之下,'41'
被存储到BINARY(3)
列中为'41\0'
,检索时为'41\0'
(尾随填充0x00
字节未被去除)。'\0'
不是合法的十六进制数字,因此列值的UNHEX()
返回NULL
。对于数值参数
N
,UNHEX()
不执行HEX(*
N*)
的逆操作。请改用CONV(HEX(*
N*),16,10)
。请参阅HEX()
的描述。如果在mysql客户端中调用
UNHEX()
,二进制字符串将以十六进制表示形式显示,具体取决于--binary-as-hex
的值。有关该选项的更多信息,请参阅第 6.5.1 节,“mysql — MySQL 命令行客户端”。 -
UPPER(*
str*)
返回根据当前字符集映射将所有字符更改为大写的字符串
str
,如果str
为NULL
则返回NULL
。默认字符集为utf8mb4
。mysql> SELECT UPPER('Hej'); -> 'HEJ'
有关如何对二进制字符串(
BINARY
,VARBINARY
,BLOB
)执行大小写转换以及有关 Unicode 字符集的大小写折叠的信息,请参阅LOWER()
的描述,这些信息也适用于UPPER()
。此函数支持多字节。
在视图中使用的
UCASE()
将被重写为UPPER()
。 -
WEIGHT_STRING(*
str* [AS {CHAR|BINARY}(*
N*)] [*
flags*])
此函数返回输入字符串的权重字符串。返回值是一个二进制字符串,表示字符串的比较和排序值,如果参数为
NULL
则返回NULL
。具有以下属性:-
如果
WEIGHT_STRING(*
str1*)
=WEIGHT_STRING(*
str2*)
,那么*
str1* = *
str2*
(str1
和str2
被视为相等) -
如果
WEIGHT_STRING(*
str1*)
<WEIGHT_STRING(*
str2*)
,那么*
str1* < *
str2*
(str1
在str2
之前排序)
WEIGHT_STRING()
是一个用于内部调试的函数。其行为可能会在 MySQL 版本之间发生变化而无需通知。它可用于测试和调试排序规则,特别是在添加新的排序规则时。参见 第 12.14 节,“向字符集添加排序规则”。这个列表简要总结了参数。更多细节在列表后的讨论中给出。
-
str
:输入字符串表达式。 -
AS
子句:可选;将输入字符串转换为给定类型和长度。 -
flags
:可选;未使用。
输入字符串
str
是一个字符串表达式。如果输入是非二进制(字符)字符串,如CHAR
、VARCHAR
或TEXT
值,则返回值包含字符串的排序规则权重。如果输入是二进制(字节)字符串,如BINARY
、VARBINARY
或BLOB
值,则返回值与输入相同(二进制字符串中每个字节的权重是字节值)。如果输入为NULL
,WEIGHT_STRING()
返回NULL
。示例:
mysql> SET @s = _utf8mb4 'AB' COLLATE utf8mb4_0900_ai_ci; mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s)); +------+---------+------------------------+ | @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) | +------+---------+------------------------+ | AB | 4142 | 1C471C60 | +------+---------+------------------------+
mysql> SET @s = _utf8mb4 'ab' COLLATE utf8mb4_0900_ai_ci; mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s)); +------+---------+------------------------+ | @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) | +------+---------+------------------------+ | ab | 6162 | 1C471C60 | +------+---------+------------------------+
mysql> SET @s = CAST('AB' AS BINARY); mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s)); +------+---------+------------------------+ | @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) | +------+---------+------------------------+ | AB | 4142 | 4142 | +------+---------+------------------------+
mysql> SET @s = CAST('ab' AS BINARY); mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s)); +------+---------+------------------------+ | @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) | +------+---------+------------------------+ | ab | 6162 | 6162 | +------+---------+------------------------+
前面的示例使用
HEX()
来显示WEIGHT_STRING()
的结果。因为结果是一个二进制值,当结果包含不可打印的值时,HEX()
尤其有用,可以将其显示为可打印形式:mysql> SET @s = CONVERT(X'C39F' USING utf8mb4) COLLATE utf8mb4_czech_ci; mysql> SELECT HEX(WEIGHT_STRING(@s)); +------------------------+ | HEX(WEIGHT_STRING(@s)) | +------------------------+ | 0FEA0FEA | +------------------------+
对于非
NULL
的返回值,如果值的长度在VARBINARY
的最大长度内,则值的数据类型为VARBINARY
,否则数据类型为BLOB
。AS
子句可以用于将输入字符串转换为非二进制或二进制字符串,并强制其达到给定长度:-
AS CHAR(*
N*)
将字符串转换为非二进制字符串,并在右侧用空格填充到长度为N
个字符。N
必须至少为 1。如果N
小于输入字符串的长度,则字符串将被截断为N
个字符。截断不会发出警告。 -
AS BINARY(*
N*)
类似,但将字符串转换为二进制字符串,N
以字节为单位(而非字符),填充使用0x00
字节(而非空格)。
mysql> SET NAMES 'latin1'; mysql> SELECT HEX(WEIGHT_STRING('ab' AS CHAR(4))); +-------------------------------------+ | HEX(WEIGHT_STRING('ab' AS CHAR(4))) | +-------------------------------------+ | 41422020 | +-------------------------------------+ mysql> SET NAMES 'utf8mb4'; mysql> SELECT HEX(WEIGHT_STRING('ab' AS CHAR(4))); +-------------------------------------+ | HEX(WEIGHT_STRING('ab' AS CHAR(4))) | +-------------------------------------+ | 1C471C60 | +-------------------------------------+
mysql> SELECT HEX(WEIGHT_STRING('ab' AS BINARY(4))); +---------------------------------------+ | HEX(WEIGHT_STRING('ab' AS BINARY(4))) | +---------------------------------------+ | 61620000 | +---------------------------------------+
flags
子句目前未被使用。如果在mysql客户端中调用
WEIGHT_STRING()
,二进制字符串将以十六进制表示,具体取决于--binary-as-hex
的值。有关该选项的更多信息,请参见第 6.5.1 节,“mysql — The MySQL Command-Line Client”。 -
14.8.1 字符串比较函数和运算符
原文:
dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html
表 14.13 字符串比较函数和运算符
名称 | 描述 |
---|---|
LIKE |
简单模式匹配 |
NOT LIKE |
简单模式匹配的否定 |
STRCMP() |
比较两个字符串 |
如果将二进制字符串作为参数传递给字符串函数,则结果字符串也是二进制字符串。将数字转换为字符串时被视为二进制字符串。这仅影响比较。
通常,如果字符串比较中的任何表达式是区分大小写的,则比较将以区分大小写的方式执行。
如果在 mysql 客户端中调用字符串函数,则二进制字符串将以十六进制表示形式显示,具体取决于 --binary-as-hex
的值。有关该选项的更多信息,请参见 第 6.5.1 节,“mysql — MySQL 命令行客户端”。
-
*
expr* LIKE *
pat* [ESCAPE '*
escape_char*']
使用 SQL 模式进行模式匹配。返回
1
(TRUE
)或0
(FALSE
)。如果expr
或pat
中的任一者是NULL
,结果为NULL
。模式不一定是一个字面字符串。例如,它可以被指定为一个字符串表达式或表列。在后一种情况下,该列必须被定义为 MySQL 字符串类型之一(参见 第 13.3 节,“字符串数据类型”)。
根据 SQL 标准,
LIKE
按字符进行匹配,因此它可能产生与=
比较运算符不同的结果:mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci; +-----------------------------------------+ | 'ä' LIKE 'ae' COLLATE latin1_german2_ci | +-----------------------------------------+ | 0 | +-----------------------------------------+ mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci; +--------------------------------------+ | 'ä' = 'ae' COLLATE latin1_german2_ci | +--------------------------------------+ | 1 | +--------------------------------------+
特别是,尾随空格始终是有意义的。这与使用
=
运算符执行的比较不同,对于非二进制字符串(CHAR
、VARCHAR
和TEXT
值)的尾随空格的重要性取决于用于比较的排序规则的填充属性。有关更多信息,请参见 比较中的尾随空格处理。使用
LIKE
可以在模式中使用以下两个通配符:-
%
匹配任意数量的字符,甚至零个字符。 -
_
匹配正好一个字符。
mysql> SELECT 'David!' LIKE 'David_'; -> 1 mysql> SELECT 'David!' LIKE '%D%v%'; -> 1
要测试通配符字符的文字实例,需在其前面加上转义字符。如果不指定
ESCAPE
字符,则假定为\
,除非启用了NO_BACKSLASH_ESCAPES
SQL 模式。在这种情况下,不使用转义字符。-
\%
匹配一个%
字符。 -
\_
匹配一个_
字符。
mysql> SELECT 'David!' LIKE 'David\_'; -> 0 mysql> SELECT 'David_' LIKE 'David\_'; -> 1
要指定不同的转义字符,请使用
ESCAPE
子句:mysql> SELECT 'David_' LIKE 'David|_' ESCAPE '|'; -> 1
转义序列应为一个字符长,用于指定转义字符,或为空以指定不使用转义字符。表达式必须在执行时评估为常量。如果启用了
NO_BACKSLASH_ESCAPES
SQL 模式,则序列不能是空的。以下语句说明字符串比较不区分大小写,除非操作数之一是区分大小写的(使用区分大小写的排序规则或是二进制字符串):
mysql> SELECT 'abc' LIKE 'ABC'; -> 1 mysql> SELECT 'abc' LIKE _utf8mb4 'ABC' COLLATE utf8mb4_0900_as_cs; -> 0 mysql> SELECT 'abc' LIKE _utf8mb4 'ABC' COLLATE utf8mb4_bin; -> 0 mysql> SELECT 'abc' LIKE BINARY 'ABC'; -> 0
作为对标准 SQL 的扩展,MySQL 允许在数值表达式上使用
LIKE
。mysql> SELECT 10 LIKE '1%'; -> 1
在这种情况下,MySQL 尝试对表达式进行隐式转换为字符串。参见第 14.3 节,“表达式评估中的类型转换”。
注意
MySQL 在字符串中使用 C 转义语法(例如,
\n
表示换行符)。如果要让LIKE
字符串包含文字\
,必须将其双写。(除非启用了NO_BACKSLASH_ESCAPES
SQL 模式,在这种情况下不使用转义字符。)例如,要搜索\n
,请指定为\\n
。要搜索\
,请指定为\\\\
;这是因为解析器会将反斜杠剥离一次,然后在进行模式匹配时再次剥离,留下一个单独的反斜杠进行匹配。例外情况:在模式字符串的末尾,可以指定反斜杠为
\\
。在字符串的末尾,反斜杠代表自身,因为后面没有需要转义的内容。假设一个表包含以下值:mysql> SELECT filename FROM t1; +--------------+ | filename | +--------------+ | C: | | C:\ | | C:\Programs | | C:\Programs\ | +--------------+
要测试以反斜杠结尾的值,可以使用以下任一模式匹配这些值:
mysql> SELECT filename, filename LIKE '%\\' FROM t1; +--------------+---------------------+ | filename | filename LIKE '%\\' | +--------------+---------------------+ | C: | 0 | | C:\ | 1 | | C:\Programs | 0 | | C:\Programs\ | 1 | +--------------+---------------------+ mysql> SELECT filename, filename LIKE '%\\\\' FROM t1; +--------------+-----------------------+ | filename | filename LIKE '%\\\\' | +--------------+-----------------------+ | C: | 0 | | C:\ | 1 | | C:\Programs | 0 | | C:\Programs\ | 1 | +--------------+-----------------------+
-
-
*
expr* NOT LIKE *
pat* [ESCAPE '*
escape_char*']
这与
NOT (*
expr* LIKE *
pat* [ESCAPE '*
escape_char*'])
相同。注意
包含
NULL
的列进行NOT LIKE
比较的聚合查询可能产生意外结果。例如,考虑以下表和数据:CREATE TABLE foo (bar VARCHAR(10)); INSERT INTO foo VALUES (NULL), (NULL);
查询
SELECT COUNT(*) FROM foo WHERE bar LIKE '%baz%';
返回0
。你可能会认为SELECT COUNT(*) FROM foo WHERE bar NOT LIKE '%baz%';
会返回2
。然而,事实并非如此:第二个查询返回0
。这是因为NULL NOT LIKE *
expr*
总是返回NULL
,无论expr
的值如何。对于涉及NULL
和使用NOT RLIKE
或NOT REGEXP
进行比较的聚合查询,必须显式测试NOT NULL
,使用OR
(而不是AND
),如下所示:SELECT COUNT(*) FROM foo WHERE bar NOT LIKE '%baz%' OR bar IS NULL;
-
STRCMP(*
expr1*,*
expr2*)
STRCMP()
如果字符串相同则返回0
,如果第一个参数根据当前排序顺序小于第二个参数则返回-1
,如果任一参数为NULL
则返回NULL
,否则返回1
。mysql> SELECT STRCMP('text', 'text2'); -> -1 mysql> SELECT STRCMP('text2', 'text'); -> 1 mysql> SELECT STRCMP('text', 'text'); -> 0
STRCMP()
使用参数的排序规则执行比较。mysql> SET @s1 = _utf8mb4 'x' COLLATE utf8mb4_0900_ai_ci; mysql> SET @s2 = _utf8mb4 'X' COLLATE utf8mb4_0900_ai_ci; mysql> SET @s3 = _utf8mb4 'x' COLLATE utf8mb4_0900_as_cs; mysql> SET @s4 = _utf8mb4 'X' COLLATE utf8mb4_0900_as_cs; mysql> SELECT STRCMP(@s1, @s2), STRCMP(@s3, @s4); +------------------+------------------+ | STRCMP(@s1, @s2) | STRCMP(@s3, @s4) | +------------------+------------------+ | 0 | -1 | +------------------+------------------+
如果排序规则不兼容,则其中一个参数必须转换为与另一个兼容。参见 Section 12.8.4, “Collation Coercibility in Expressions”。
mysql> SET @s1 = _utf8mb4 'x' COLLATE utf8mb4_0900_ai_ci; mysql> SET @s2 = _utf8mb4 'X' COLLATE utf8mb4_0900_ai_ci; mysql> SET @s3 = _utf8mb4 'x' COLLATE utf8mb4_0900_as_cs; mysql> SET @s4 = _utf8mb4 'X' COLLATE utf8mb4_0900_as_cs; --> mysql> SELECT STRCMP(@s1, @s3); ERROR 1267 (HY000): Illegal mix of collations (utf8mb4_0900_ai_ci,IMPLICIT) and (utf8mb4_0900_as_cs,IMPLICIT) for operation 'strcmp' mysql> SELECT STRCMP(@s1, @s3 COLLATE utf8mb4_0900_ai_ci); +---------------------------------------------+ | STRCMP(@s1, @s3 COLLATE utf8mb4_0900_ai_ci) | +---------------------------------------------+ | 0 | +---------------------------------------------+
14.8.2 正则表达式
表 14.14 正则表达式函数和运算符
名称 | 描述 |
---|---|
NOT REGEXP |
REGEXP 的否定 |
REGEXP |
字符串是否匹配正则表达式 |
REGEXP_INSTR() |
返回匹配正则表达式的子字符串的起始索引 |
REGEXP_LIKE() |
字符串是否匹配正则表达式 |
REGEXP_REPLACE() |
替换匹配正则表达式的子字符串 |
REGEXP_SUBSTR() |
返回匹配正则表达式的子字符串 |
RLIKE |
字符串是否匹配正则表达式 |
正则表达式是指定复杂搜索模式的强大方式。本节讨论了用于正则表达式匹配的函数和运算符,并举例说明了一些特殊字符和结构,可用于正则表达式操作。另请参见第 5.3.4.7 节,“模式匹配”。
MySQL 使用国际化组件 Unicode(ICU)实现正则表达式支持,提供完整的 Unicode 支持并且是多字节安全的。(在 MySQL 8.0.4 之前,MySQL 使用 Henry Spencer 的正则表达式实现,以字节方式操作,不是多字节安全的。有关使用正则表达式的应用程序可能受到实现更改影响的信息,请参见正则表达式兼容性注意事项.)
在 MySQL 8.0.22 之前,可以使用二进制字符串参数与这些函数,但结果不一致。在 MySQL 8.0.22 及更高版本中,使用任何 MySQL 正则表达式函数的二进制字符串将被拒绝,并显示ER_CHARACTER_SET_MISMATCH
。
-
正则表达式函数和运算符描述
-
正则表达式语法
-
正则表达式资源控制
-
正则表达式兼容性注意事项
正则表达式函数和运算符描述
-
*
expr* NOT REGEXP *
pat*
,*
expr* NOT RLIKE *
pat*
这与
NOT (*
expr* REGEXP *
pat*)
相同。 -
*
expr* REGEXP *
pat*
,*
expr* RLIKE *
pat*
如果字符串
expr
与模式pat
指定的正则表达式匹配,则返回 1,否则返回 0。如果expr
或pat
为NULL
,则返回值为NULL
。REGEXP
和RLIKE
是REGEXP_LIKE()
的同义词。有关匹配发生的更多信息,请参阅
REGEXP_LIKE()
的描述。mysql> SELECT 'Michael!' REGEXP '.*'; +------------------------+ | 'Michael!' REGEXP '.*' | +------------------------+ | 1 | +------------------------+ mysql> SELECT 'new*\n*line' REGEXP 'new\\*.\\*line'; +---------------------------------------+ | 'new*\n*line' REGEXP 'new\\*.\\*line' | +---------------------------------------+ | 0 | +---------------------------------------+ mysql> SELECT 'a' REGEXP '^[a-d]'; +---------------------+ | 'a' REGEXP '^[a-d]' | +---------------------+ | 1 | +---------------------+
-
REGEXP_INSTR(*
expr*, *
pat*[, *
pos*[, *
occurrence*[, *
return_option*[, *
match_type*]]]])
返回字符串
expr
中与模式pat
指定的正则表达式匹配的子字符串的起始索引,如果没有匹配则返回 0。如果expr
或pat
为NULL
,则返回值为NULL
。字符索引从 1 开始。REGEXP_INSTR()
接受这些可选参数:-
pos
:开始搜索的expr
中的位置。如果省略,则默认为 1。 -
occurrence
:要搜索的匹配的哪个出现。如果省略,则默认为 1。 -
return_option
:要返回的位置类型。如果此值为 0,REGEXP_INSTR()
将返回匹配子字符串的第一个字符的位置。如果此值为 1,REGEXP_INSTR()
将返回匹配子字符串后面的位置。如果省略,则默认为 0。 -
match_type
:指定如何执行匹配的字符串。其含义如REGEXP_LIKE()
中描述的。
有关匹配发生的更多信息,请参阅
REGEXP_LIKE()
的描述。mysql> SELECT REGEXP_INSTR('dog cat dog', 'dog'); +------------------------------------+ | REGEXP_INSTR('dog cat dog', 'dog') | +------------------------------------+ | 1 | +------------------------------------+ mysql> SELECT REGEXP_INSTR('dog cat dog', 'dog', 2); +---------------------------------------+ | REGEXP_INSTR('dog cat dog', 'dog', 2) | +---------------------------------------+ | 9 | +---------------------------------------+ mysql> SELECT REGEXP_INSTR('aa aaa aaaa', 'a{2}'); +-------------------------------------+ | REGEXP_INSTR('aa aaa aaaa', 'a{2}') | +-------------------------------------+ | 1 | +-------------------------------------+ mysql> SELECT REGEXP_INSTR('aa aaa aaaa', 'a{4}'); +-------------------------------------+ | REGEXP_INSTR('aa aaa aaaa', 'a{4}') | +-------------------------------------+ | 8 | +-------------------------------------+
-
-
REGEXP_LIKE(*
expr*, *
pat*[, *
match_type*])
如果字符串
expr
与模式pat
指定的正则表达式匹配,则返回 1,否则返回 0。如果expr
或pat
为NULL
,则返回值为NULL
。模式可以是扩展正则表达式,其语法在正则表达式语法中讨论。模式不必是一个字面字符串。例如,它可以被指定为一个字符串表达式或表列。
可选的
match_type
参数是一个字符串,可以包含任何或所有以下字符,指定如何执行匹配:-
c
:区分大小写匹配。 -
i
:不区分大小写匹配。 -
m
:多行模式。识别字符串内的行终止符。默认行为是仅在字符串表达式的开头和结尾匹配行终止符。 -
n
:.
字符匹配行终止符。默认情况下,.
匹配会在行尾停止。 -
u
:仅适用于 Unix 换行符。只有换行符被.
、^
和$
匹配操作符识别为换行符。
如果在
match_type
中指定了指定矛盾选项的字符,则最右边的选项优先。默认情况下,正则表达式操作在决定字符类型和执行比较时使用
expr
和pat
参数的字符集和排序规则。如果参数具有不同的字符集或排序规则,则会应用强制转换规则,如第 12.8.4 节“表达式中的排序规则可转换性”中所述。可以使用显式排序标识符指定参数以更改比较行为。mysql> SELECT REGEXP_LIKE('CamelCase', 'CAMELCASE'); +---------------------------------------+ | REGEXP_LIKE('CamelCase', 'CAMELCASE') | +---------------------------------------+ | 1 | +---------------------------------------+ mysql> SELECT REGEXP_LIKE('CamelCase', 'CAMELCASE' COLLATE utf8mb4_0900_as_cs); +------------------------------------------------------------------+ | REGEXP_LIKE('CamelCase', 'CAMELCASE' COLLATE utf8mb4_0900_as_cs) | +------------------------------------------------------------------+ | 0 | +------------------------------------------------------------------+
match_type
可以用c
或i
字符指定以覆盖默认的大小写敏感性。例外:如果任一参数是二进制字符串,则参数将作为二进制字符串进行大小写敏感处理,即使match_type
包含i
字符。注意
MySQL 在字符串中使用 C 转义语法(例如,
\n
表示换行符)。如果您希望您的expr
或pat
参数包含文字\
,则必须将其加倍。(除非启用了NO_BACKSLASH_ESCAPES
SQL 模式,在这种情况下不使用转义字符。)mysql> SELECT REGEXP_LIKE('Michael!', '.*'); +-------------------------------+ | REGEXP_LIKE('Michael!', '.*') | +-------------------------------+ | 1 | +-------------------------------+ mysql> SELECT REGEXP_LIKE('new*\n*line', 'new\\*.\\*line'); +----------------------------------------------+ | REGEXP_LIKE('new*\n*line', 'new\\*.\\*line') | +----------------------------------------------+ | 0 | +----------------------------------------------+ mysql> SELECT REGEXP_LIKE('a', '^[a-d]'); +----------------------------+ | REGEXP_LIKE('a', '^[a-d]') | +----------------------------+ | 1 | +----------------------------+
mysql> SELECT REGEXP_LIKE('abc', 'ABC'); +---------------------------+ | REGEXP_LIKE('abc', 'ABC') | +---------------------------+ | 1 | +---------------------------+ mysql> SELECT REGEXP_LIKE('abc', 'ABC', 'c'); +--------------------------------+ | REGEXP_LIKE('abc', 'ABC', 'c') | +--------------------------------+ | 0 | +--------------------------------+
-
-
REGEXP_REPLACE(*
expr*, *
pat*, *
repl*[, *
pos*[, *
occurrence*[, *
match_type*]]])
用替换字符串
repl
替换与模式pat
指定的正则表达式匹配的字符串expr
中的出现,并返回结果字符串。如果expr
、pat
或repl
为NULL
,则返回值为NULL
。REGEXP_REPLACE()
接受这些可选参数:-
pos
:在expr
中开始搜索的位置。如果省略,默认为 1。 -
occurrence
:要替换的匹配的哪个出现。如果省略,默认为 0(表示“替换所有出现”)。 -
match_type
:一个指定如何执行匹配的字符串。其含义如REGEXP_LIKE()
中所述。
在 MySQL 8.0.17 之前,此函数返回的结果使用
UTF-16
字符集;在 MySQL 8.0.17 及更高版本中,使用搜索匹配的表达式的字符集和排序规则。(Bug #94203,Bug #29308212)有关匹配发生的更多信息,请参阅
REGEXP_LIKE()
的描述。mysql> SELECT REGEXP_REPLACE('a b c', 'b', 'X'); +-----------------------------------+ | REGEXP_REPLACE('a b c', 'b', 'X') | +-----------------------------------+ | a X c | +-----------------------------------+ mysql> SELECT REGEXP_REPLACE('abc def ghi', '[a-z]+', 'X', 1, 3); +----------------------------------------------------+ | REGEXP_REPLACE('abc def ghi', '[a-z]+', 'X', 1, 3) | +----------------------------------------------------+ | abc def X | +----------------------------------------------------+
-
-
REGEXP_SUBSTR(*
expr*, *
pat*[, *
pos*[, *
occurrence*[, *
match_type*]]])
返回与模式
pat
指定的正则表达式匹配的字符串expr
的子字符串,如果没有匹配则返回NULL
。如果expr
或pat
为NULL
,则返回值为NULL
。REGEXP_SUBSTR()
接受这些可选参数:-
pos
:在expr
中开始搜索的位置。如果省略,默认为 1。 -
occurrence
:要搜索的匹配的哪个出现。如果省略,默认为 1。 -
match_type
:指定如何执行匹配的字符串。其含义与REGEXP_LIKE()
中描述的相同。
在 MySQL 8.0.17 之前,此函数返回的结果使用
UTF-16
字符集;在 MySQL 8.0.17 及更高版本中,使用搜索匹配的表达式的字符集和校对规则。(Bug #94203,Bug #29308212)有关匹配发生的更多信息,请参阅
REGEXP_LIKE()
的描述。mysql> SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+'); +----------------------------------------+ | REGEXP_SUBSTR('abc def ghi', '[a-z]+') | +----------------------------------------+ | abc | +----------------------------------------+ mysql> SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+', 1, 3); +----------------------------------------------+ | REGEXP_SUBSTR('abc def ghi', '[a-z]+', 1, 3) | +----------------------------------------------+ | ghi | +----------------------------------------------+
-
正则表达式语法
正则表达式描述了一组字符串。最简单的正则表达式是没有特殊字符的正则表达式。例如,正则表达式hello
匹配hello
,不匹配其他任何内容。
复杂的正则表达式使用特定的特殊构造,以便能够匹配多个字符串。例如,正则表达式hello|world
包含|
交替运算符,匹配hello
或world
。
作为一个更复杂的例子,正则表达式B[an]*s
匹配任何字符串Bananas
,Baaaaas
,Bs
,以及任何以B
开头,以s
结尾,并且在中间包含任意数量的a
或n
字符的字符串。
以下列表涵盖了一些基本的特殊字符和构造,可用于正则表达式中。有关 ICU 库支持的完整正则表达式语法的信息,请访问国际 Unicode 组件网站。
-
^
匹配字符串的开头。
mysql> SELECT REGEXP_LIKE('fo\nfo', '^fo$'); -> 0 mysql> SELECT REGEXP_LIKE('fofo', '^fo'); -> 1
-
$
匹配字符串的结尾。
mysql> SELECT REGEXP_LIKE('fo\no', '^fo\no$'); -> 1 mysql> SELECT REGEXP_LIKE('fo\no', '^fo$'); -> 0
-
.
匹配任何字符(包括回车和换行符,尽管要匹配字符串中间的这些字符,必须给定
m
(多行)匹配控制字符或(?m)
模式内修改器)。mysql> SELECT REGEXP_LIKE('fofo', '^f.*$'); -> 1 mysql> SELECT REGEXP_LIKE('fo\r\nfo', '^f.*$'); -> 0 mysql> SELECT REGEXP_LIKE('fo\r\nfo', '^f.*$', 'm'); -> 1 mysql> SELECT REGEXP_LIKE('fo\r\nfo', '(?m)^f.*$'); -> 1
-
a*
匹配零个或多个
a
字符的序列。mysql> SELECT REGEXP_LIKE('Ban', '^Ba*n'); -> 1 mysql> SELECT REGEXP_LIKE('Baaan', '^Ba*n'); -> 1 mysql> SELECT REGEXP_LIKE('Bn', '^Ba*n'); -> 1
-
a+
匹配一个或多个
a
字符的序列。mysql> SELECT REGEXP_LIKE('Ban', '^Ba+n'); -> 1 mysql> SELECT REGEXP_LIKE('Bn', '^Ba+n'); -> 0
-
a?
匹配零个或一个
a
字符。mysql> SELECT REGEXP_LIKE('Bn', '^Ba?n'); -> 1 mysql> SELECT REGEXP_LIKE('Ban', '^Ba?n'); -> 1 mysql> SELECT REGEXP_LIKE('Baan', '^Ba?n'); -> 0
-
de|abc
交替;匹配
de
或abc
中的任一序列。mysql> SELECT REGEXP_LIKE('pi', 'pi|apa'); -> 1 mysql> SELECT REGEXP_LIKE('axe', 'pi|apa'); -> 0 mysql> SELECT REGEXP_LIKE('apa', 'pi|apa'); -> 1 mysql> SELECT REGEXP_LIKE('apa', '^(pi|apa)$'); -> 1 mysql> SELECT REGEXP_LIKE('pi', '^(pi|apa)$'); -> 1 mysql> SELECT REGEXP_LIKE('pix', '^(pi|apa)$'); -> 0
-
(abc)*
匹配序列
abc
的零个或多个实例。mysql> SELECT REGEXP_LIKE('pi', '^(pi)*$'); -> 1 mysql> SELECT REGEXP_LIKE('pip', '^(pi)*$'); -> 0 mysql> SELECT REGEXP_LIKE('pipi', '^(pi)*$'); -> 1
-
{1}
,{2,3}
重复;
{*
n*}
和{*
m*,*
n*}
表示一种更通用的写正则表达式的方式,可以匹配前一个原子(或“片段”)的模式的多个出现。m
和n
是整数。-
a*
可以写成
a{0,}
。 -
a+
可以写成
a{1,}
。 -
a?
可以写成
a{0,1}
。
要更精确地说,
a{*
n*}
精确匹配n
个a
。a{*
n*,}
匹配n
个或更多个a
。a{*
m*,*
n*}
匹配m
到n
个a
,包括两端。如果同时给出m
和n
,则m
必须小于或等于n
。mysql> SELECT REGEXP_LIKE('abcde', 'a[bcd]{2}e'); -> 0 mysql> SELECT REGEXP_LIKE('abcde', 'a[bcd]{3}e'); -> 1 mysql> SELECT REGEXP_LIKE('abcde', 'a[bcd]{1,10}e'); -> 1
-
-
[a-dX]
,[^a-dX]
匹配任何是(或不是,如果使用
^
)a
、b
、c
、d
或X
的字符。两个字符之间的-
形成一个范围,匹配从第一个字符到第二个字符的所有字符。例如,[0-9]
匹配任何十进制数字。要包含文字]
字符,它必须紧跟在开方括号[
之后。要包含文字-
字符,它必须写在最前面或最后面。在[]
对中没有定义特殊含义的任何字符只匹配它本身。mysql> SELECT REGEXP_LIKE('aXbc', '[a-dXYZ]'); -> 1 mysql> SELECT REGEXP_LIKE('aXbc', '^[a-dXYZ]$'); -> 0 mysql> SELECT REGEXP_LIKE('aXbc', '^[a-dXYZ]+$'); -> 1 mysql> SELECT REGEXP_LIKE('aXbc', '^[^a-dXYZ]+$'); -> 0 mysql> SELECT REGEXP_LIKE('gheis', '^[^a-dXYZ]+$'); -> 1 mysql> SELECT REGEXP_LIKE('gheisa', '^[^a-dXYZ]+$'); -> 0
-
[=character_class=]
在方括号表达式(使用
[
和]
编写)中,[=character_class=]
表示一个等价类。它匹配所有具有相同排序值的字符,包括它本身。例如,如果o
和(+)
是等价类的成员,则[[=o=]]
、[[=(+)=]]
和[o(+)]
都是同义词。等价类不能用作范围的端点。 -
[:character_class:]
在方括号表达式(使用
[
和]
编写)中,[:character_class:]
表示一个匹配属于该类的所有字符的字符类。以下表列出了标准类名。这些名称代表ctype(3)
手册页中定义的字符类。特定区域设置可能提供其他类名。字符类不能用作范围的端点。字符类名 含义 alnum
字母数字字符 alpha
字母字符 blank
空白字符 cntrl
控制字符 digit
数字字符 graph
图形字符 lower
小写字母字符 print
图形或空格字符 punct
标点字符 space
空格、制表符、换行符和回车符 upper
大写字母字符 xdigit
十六进制数字字符 字符类名 含义 mysql> SELECT REGEXP_LIKE('justalnums', '[[:alnum:]]+'); -> 1 mysql> SELECT REGEXP_LIKE('!!', '[[:alnum:]]+'); -> 0
由于 ICU 知道
utf16_general_ci
中的所有字母字符,因此某些字符类的性能可能不如字符范围高。例如,[a-zA-Z]
比[[:alpha:]]
更快,[0-9]
通常比[[:digit:]]
更快。如果您正在迁移使用[[:alpha:]]
或[[:digit:]]
的应用程序从旧版本的 MySQL,您应该将这些替换为等效的范围以在 MySQL 8.0 中使用。
要在正则表达式中使用特殊字符的文字实例,请在其前面加上两个反斜杠(\)字符。MySQL 解析器解释其中一个反斜杠,而正则表达式库解释另一个。例如,要匹配包含特殊+
字符的字符串1+2
,只有以下正则表达式中的最后一个是正确的:
mysql> SELECT REGEXP_LIKE('1+2', '1+2'); -> 0
mysql> SELECT REGEXP_LIKE('1+2', '1\+2'); -> 0
mysql> SELECT REGEXP_LIKE('1+2', '1\\+2'); -> 1
正则表达式资源控制
REGEXP_LIKE()
和类似函数使用可以通过设置系统变量来控制的资源:
-
匹配引擎使用内部堆栈的内存。要控制堆栈的最大可用内存(以字节为单位),请设置
regexp_stack_limit
系统变量。 -
匹配引擎以步骤方式运行。要控制引擎执行的最大步骤数(从而间接影响执行时间),请设置
regexp_time_limit
系统变量。因为此限制表示为步骤数,所以它只间接影响执行时间。通常,它的数量级为毫秒。
正则表达式兼容性考虑
在 MySQL 8.0.4 之前,MySQL 使用 Henry Spencer 正则表达式库来支持正则表达式操作,而不是国际 Unicode 组件(ICU)。以下讨论描述了 Spencer 和 ICU 库之间可能影响应用程序的差异:
-
使用 Spencer 库,
REGEXP
和RLIKE
运算符以字节方式工作,因此它们不是多字节安全的,可能会在使用多字节字符集时产生意外结果。此外,这些运算符通过它们的字节值比较字符,即使给定排序将它们视为相等,重音字符也可能不相等。ICU 具有完整的 Unicode 支持,并且是多字节安全的。其正则表达式函数将所有字符串视为
UTF-16
。您应该记住,位置索引是基于 16 位块而不是代码点的。这意味着,当传递给这些函数时,使用多个块的字符可能会产生意想不到的结果,例如下面所示:mysql> SELECT REGEXP_INSTR('🍣🍣b', 'b'); +--------------------------+ | REGEXP_INSTR('??b', 'b') | +--------------------------+ | 5 | +--------------------------+ 1 row in set (0.00 sec) mysql> SELECT REGEXP_INSTR('🍣🍣bxxx', 'b', 4); +--------------------------------+ | REGEXP_INSTR('??bxxx', 'b', 4) | +--------------------------------+ | 5 | +--------------------------------+ 1 row in set (0.00 sec)
Unicode 基本多文种平面内的字符(包括大多数现代语言使用的字符)在这方面是安全的:
mysql> SELECT REGEXP_INSTR('бжb', 'b'); +----------------------------+ | REGEXP_INSTR('бжb', 'b') | +----------------------------+ | 3 | +----------------------------+ 1 row in set (0.00 sec) mysql> SELECT REGEXP_INSTR('עבb', 'b'); +----------------------------+ | REGEXP_INSTR('עבb', 'b') | +----------------------------+ | 3 | +----------------------------+ 1 row in set (0.00 sec) mysql> SELECT REGEXP_INSTR('µå周çб', '周'); +------------------------------------+ | REGEXP_INSTR('µå周çб', '周') | +------------------------------------+ | 3 | +------------------------------------+ 1 row in set (0.00 sec)
表情符号,例如第一个两个示例中使用的“寿司”字符
🍣
(U+1F363),不包括在基本多语言平面中,而是在 Unicode 的补充多语言平面中。当REGEXP_SUBSTR()
或类似函数从字符中间开始搜索时,表情符号和其他 4 字节字符可能会出现问题。以下示例中的两个语句中的每个都从第一个参数的第二个 2 字节位置开始。第一个语句适用于仅由 2 字节(BMP)字符组成的字符串。第二个语句包含 4 字节字符,结果中错误解释了这些字符,因为前两个字节被剥离,因此字符数据的其余部分错位。mysql> SELECT REGEXP_SUBSTR('周周周周', '.*', 2); +----------------------------------------+ | REGEXP_SUBSTR('周周周周', '.*', 2) | +----------------------------------------+ | 周周周 | +----------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT REGEXP_SUBSTR('🍣🍣🍣🍣', '.*', 2); +--------------------------------+ | REGEXP_SUBSTR('????', '.*', 2) | +--------------------------------+ | ?㳟揘㳟揘㳟揘 | +--------------------------------+ 1 row in set (0.00 sec)
-
对于
.
运算符,Spencer 库在字符串表达式中的任何位置(包括中间)匹配行终止字符(回车,换行)。要在 ICU 中匹配字符串中间的行终止字符,请指定m
匹配控制字符。 -
Spencer 库支持单词开头和单词结尾边界标记(
[[:<:]]
和[[:>:]]
表示)。ICU 不支持。对于 ICU,您可以使用\b
来匹配单词边界;双反斜杠因为 MySQL 将其解释为字符串中的转义字符。 -
Spencer 库支持整理元素括号表达式(
[.characters.]
表示)。ICU 不支持。 -
对于重复计数(
{n}
和{m,n}
表示),Spencer 库最多为 255。ICU 没有此限制,尽管可以通过设置regexp_time_limit
系统变量来限制匹配引擎步骤的最大数量。 -
ICU 将括号解释为元字符。要在正则表达式中指定字面上的开放
(
或关闭括号`),必须进行转义:mysql> SELECT REGEXP_LIKE('(', '('); ERROR 3692 (HY000): Mismatched parenthesis in regular expression. mysql> SELECT REGEXP_LIKE('(', '\\('); +-------------------------+ | REGEXP_LIKE('(', '\\(') | +-------------------------+ | 1 | +-------------------------+ mysql> SELECT REGEXP_LIKE(')', ')'); ERROR 3692 (HY000): Mismatched parenthesis in regular expression. mysql> SELECT REGEXP_LIKE(')', '\\)'); +-------------------------+ | REGEXP_LIKE(')', '\\)') | +-------------------------+ | 1 | +-------------------------+
-
ICU 还将方括号解释为元字符,但只有开放方括号需要转义才能用作字面字符:
mysql> SELECT REGEXP_LIKE('[', '['); ERROR 3696 (HY000): The regular expression contains an unclosed bracket expression. mysql> SELECT REGEXP_LIKE('[', '\\['); +-------------------------+ | REGEXP_LIKE('[', '\\[') | +-------------------------+ | 1 | +-------------------------+ mysql> SELECT REGEXP_LIKE(']', ']'); +-----------------------+ | REGEXP_LIKE(']', ']') | +-----------------------+ | 1 | +-----------------------+
14.8.3 函数结果的字符集和排序规则
原文:
dev.mysql.com/doc/refman/8.0/en/string-functions-charset.html
MySQL 有许多返回字符串的运算符和函数。本节回答了一个问题:这样的字符串的字符集和排序规则是什么?
对于接受字符串输入并返回字符串结果的简单函数,输出的字符集和排序规则与主要输入值相同。例如,UPPER(*
X*)
返回一个与 X
相同字符集和排序规则的字符串。对于 INSTR()
、LCASE()
、LOWER()
、LTRIM()
、MID()
、REPEAT()
、REPLACE()
、REVERSE()
、RIGHT()
、RPAD()
、RTRIM()
、SOUNDEX()
、SUBSTRING()
、TRIM()
、UCASE()
和 UPPER()
也适用相同规则。
注意
与所有其他函数不同,REPLACE()
函数始终忽略字符串输入的排序规则并执行区分大小写的比较。
如果字符串输入或函数结果是二进制字符串,则该字符串具有 binary
字符集和排序规则。可以通过使用 CHARSET()
和 COLLATION()
函数来检查,两者对于二进制字符串参数都返回 binary
:
mysql> SELECT CHARSET(BINARY 'a'), COLLATION(BINARY 'a');
+---------------------+-----------------------+
| CHARSET(BINARY 'a') | COLLATION(BINARY 'a') |
+---------------------+-----------------------+
| binary | binary |
+---------------------+-----------------------+
对于将多个字符串输入组合并返回单个字符串输出的操作,标准 SQL 的“聚合规则”适用于确定结果的排序规则:
-
如果明确出现
COLLATE *
Y*
,则使用Y
。 -
如果明确出现
COLLATE *
Y*
和COLLATE *
Z*
,则引发错误。 -
否则,如果所有排序规则都是
Y
,则使用Y
。 -
否则,结果没有排序规则。
例如,使用 CASE ... WHEN a THEN b WHEN b THEN c COLLATE *
X* END
,结果的排序规则是 X
。对于 UNION
、||
、CONCAT()
、ELT()
、GREATEST()
、IF()
和 LEAST()
也适用相同规则。
对于转换为字符数据的操作,操作结果字符串的字符集和排序由确定默认连接字符集和排序的character_set_connection
和collation_connection
系统变量定义(参见第 12.4 节,“连接字符集和排序”)。这仅适用于BIN_TO_UUID()
、CAST()
、CONV()
、FORMAT()
、HEX()
和SPACE()
。
对于虚拟生成列的表达式,前述原则有一个例外。在这种表达式中,无论连接字符集如何,都使用表字符集来处理BIN_TO_UUID()
、CONV()
或HEX()
的结果。
如果对字符串函数返回的结果的字符集或排序有任何疑问,请使用CHARSET()
或COLLATION()
函数来查找:
mysql> SELECT USER(), CHARSET(USER()), COLLATION(USER());
+----------------+-----------------+--------------------+
| USER() | CHARSET(USER()) | COLLATION(USER()) |
+----------------+-----------------+--------------------+
| test@localhost | utf8mb3 | utf8mb3_general_ci |
+----------------+-----------------+--------------------+
mysql> SELECT CHARSET(COMPRESS('abc')), COLLATION(COMPRESS('abc'));
+--------------------------+----------------------------+
| CHARSET(COMPRESS('abc')) | COLLATION(COMPRESS('abc')) |
+--------------------------+----------------------------+
| binary | binary |
+--------------------------+----------------------------+
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 全文解析器插件
MATCH (*
col1*,*
col2*,...) AGAINST (*
expr* [*
search_modifier*])
*search_modifier:*
{
IN NATURAL LANGUAGE MODE
| IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
| IN BOOLEAN MODE
| WITH QUERY EXPANSION
}
MySQL 支持全文索引和搜索:
-
MySQL 中的全文索引是
FULLTEXT
类型的索引。 -
全文索引只能用于
InnoDB
或MyISAM
表,并且只能为CHAR
、VARCHAR
或TEXT
列创建。 -
MySQL 提供了内置的全文 ngram 解析器,支持中文、日文和韩文(CJK),以及用于日文的可安装的 MeCab 全文解析器插件。解析差异在第 14.9.8 章“ngram 全文解析器”和第 14.9.9 章“MeCab 全文解析器插件”中有详细说明。
-
在创建表时,可以在
CREATE TABLE
语句中给出FULLTEXT
索引定义,或者稍后使用ALTER TABLE
或CREATE INDEX
添加。 -
对于大型数据集,将数据加载到没有
FULLTEXT
索引的表中,然后在此之后创建索引,比将数据加载到已有FULLTEXT
索引的表中要快得多。
使用MATCH() AGAINST()
语法执行全文搜索。MATCH()
接受一个逗号分隔的列表,列出要搜索的列。AGAINST
接受要搜索的字符串,以及一个可选的修饰符,指示要执行的搜索类型。搜索字符串必须是在查询评估期间保持不变的字符串值。例如,表列就不符合这个规则,因为每行可能不同。
以前,MySQL 允许在MATCH()
中使用一个 rollup 列,但使用这种结构的查询性能不佳且结果不可靠。(这是因为MATCH()
不是根据其参数的函数实现,而是根据基表的底层扫描中当前行的行 ID 的函数实现。)从 MySQL 8.0.28 开始,MySQL 不再允许这样的查询;更具体地说,任何符合此处列出的所有标准的查询都将被拒绝,并显示ER_FULLTEXT_WITH_ROLLUP
:
-
MATCH()
出现在查询块的SELECT
列表、GROUP BY
子句、HAVING
子句或ORDER BY
子句中。 -
查询块包含一个
GROUP BY ... WITH ROLLUP
子句。 -
调用
MATCH()
函数的参数是分组列之一。
这里显示了一些此类查询的示例:
# MATCH() in SELECT list...
SELECT MATCH (a) AGAINST ('abc') FROM t GROUP BY a WITH ROLLUP;
SELECT 1 FROM t GROUP BY a, MATCH (a) AGAINST ('abc') WITH ROLLUP;
# ...in HAVING clause...
SELECT 1 FROM t GROUP BY a WITH ROLLUP HAVING MATCH (a) AGAINST ('abc');
# ...and in ORDER BY clause
SELECT 1 FROM t GROUP BY a WITH ROLLUP ORDER BY MATCH (a) AGAINST ('abc');
在WHERE
子句中允许使用带有 rollup 列的MATCH()
。
有三种类型的全文搜索:
-
自然语言搜索将搜索字符串解释为自然人类语言中的短语(自由文本中的短语)。除了双引号(")字符外,没有特殊运算符。停用词列表适用。有关停用词列表的更多信息,请参见第 14.9.4 节,“全文停用词”。
如果给定
IN NATURAL LANGUAGE MODE
修饰符或未给定修饰符,则全文搜索是自然语言搜索。有关更多信息,请参见第 14.9.1 节,“自然语言全文搜索”。 -
布尔搜索使用特殊查询语言的规则解释搜索字符串。字符串包含要搜索的单词。它还可以包含指定要求的运算符,例如一个单词必须存在或不存在于匹配行中,或者它应该比通常更高或更低权重。某些常见单词(停用词)被省略在搜索索引中,如果在搜索字符串中存在则不匹配。
IN BOOLEAN MODE
修饰符指定布尔搜索。有关更多信息,请参见第 14.9.2 节,“布尔全文搜索”。 -
查询扩展搜索是自然语言搜索的修改。搜索字符串用于执行自然语言搜索。然后从搜索返回的最相关行中添加单词到搜索字符串,并再次进行搜索。查询返回第二次搜索的行。
IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
或WITH QUERY EXPANSION
修饰符指定查询扩展搜索。有关更多信息,请参见第 14.9.3 节,“带查询扩展的全文搜索”。
有关FULLTEXT
查询性能的信息,请参见 Section 10.3.5, “Column Indexes”。
关于InnoDB
FULLTEXT
索引的更多信息,请参见 Section 17.6.2.4, “InnoDB Full-Text Indexes”。
全文搜索的限制条件列在 Section 14.9.5, “Full-Text Restrictions”。
myisam_ftdump实用程序会转储MyISAM
全文索引的内容。这对于调试全文查询可能会有所帮助。请参见 Section 6.6.3, “myisam_ftdump — Display Full-Text Index information”。
14.9.1 自然语言全文搜索
原文:
dev.mysql.com/doc/refman/8.0/en/fulltext-natural-language.html
默认情况下或使用IN NATURAL LANGUAGE MODE
修饰符时,MATCH()
函数针对文本集合执行自然语言搜索。集合是包含在FULLTEXT
索引中的一个或多个列的集合。搜索字符串作为参数传递给AGAINST()
。对于表中的每一行,MATCH()
返回一个相关性值;即,搜索字符串与列中文本之间的相似度量,在MATCH()
列表中命名的列中。
mysql> CREATE TABLE articles (
-> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
-> title VARCHAR(200),
-> body TEXT,
-> FULLTEXT (title,body)
-> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.08 sec)
mysql> INSERT INTO articles (title,body) VALUES
-> ('MySQL Tutorial','DBMS stands for DataBase ...'),
-> ('How To Use MySQL Well','After you went through a ...'),
-> ('Optimizing MySQL','In this tutorial, we show ...'),
-> ('1001 MySQL Tricks','1\. Never run mysqld as root. 2\. ...'),
-> ('MySQL vs. YourSQL','In the following database comparison ...'),
-> ('MySQL Security','When configured properly, MySQL ...');
Query OK, 6 rows affected (0.01 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM articles
-> WHERE MATCH (title,body)
-> AGAINST ('database' IN NATURAL LANGUAGE MODE);
+----+-------------------+------------------------------------------+
| id | title | body |
+----+-------------------+------------------------------------------+
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)
默认情况下,搜索是以不区分大小写的方式执行的。要执行区分大小写的全文搜索,请为索引列使用区分大小写或二进制排序规则。例如,使用utf8mb4
字符集的列可以分配utf8mb4_0900_as_cs
或utf8mb4_bin
排序规则,以使其对全文搜索区分大小写。
当MATCH()
在WHERE
子句中使用时,如前面示例所示,只要满足以下条件,返回的行将自动按相关性最高的顺序排序:
-
不得有显式的
ORDER BY
子句。 -
搜索必须使用全文索引扫描,而不是表扫描。
-
如果查询涉及表连接,则全文索引扫描必须是连接中最左边的非常量表。
鉴于刚刚列出的条件,当需要或希望时,通常更容易通过使用ORDER BY
指定显式排序顺序。
相关性值是非负浮点数。零相关性表示没有相似性。相关性是基于行中的单词数、行中唯一单词数、集合中的总单词数以及包含特定单词的行数进行计算的。
注意
“文档”一词可以与“行”一词互换使用,两个术语都指的是行的索引部分。“集合”一词指的是索引列,并包括所有行。
要简单计算匹配项,可以使用如下查询:
mysql> SELECT COUNT(*) FROM articles
-> WHERE MATCH (title,body)
-> AGAINST ('database' IN NATURAL LANGUAGE MODE);
+----------+
| COUNT(*) |
+----------+
| 2 |
+----------+
1 row in set (0.00 sec)
你可能会发现将查询重写为以下形式更快:
mysql> SELECT
-> COUNT(IF(MATCH (title,body) AGAINST ('database' IN NATURAL LANGUAGE MODE), 1, NULL))
-> AS count
-> FROM articles;
+-------+
| count |
+-------+
| 2 |
+-------+
1 row in set (0.03 sec)
第一个查询做了一些额外的工作(按相关性对结果进行排序),但也可以根据WHERE
子句使用索引查找。如果搜索匹配的行数较少,索引查找可能会使第一个查询更快。第二个查询执行全表扫描,如果搜索词在大多数行中存在,可能比索引查找更快。
对于自然语言全文搜索,MATCH()
函数中命名的列必须与表中某个FULLTEXT
索引中包含的相同列相同。对于上述查询,请注意MATCH()
函数中命名的列(title
和body
)与article
表的FULLTEXT
索引定义中命名的列相同。要分别搜索title
或body
,您需要为每个列创建单独的FULLTEXT
索引。
你还可以执行布尔搜索或带有查询扩展的搜索。这些搜索类型在第 14.9.2 节,“布尔全文搜索”和第 14.9.3 节,“带有查询扩展的全文搜索”中有描述。
使用索引的全文搜索在MATCH()
子句中只能命名来自单个表的列,因为索引不能跨越多个表。对于MyISAM
表,如果没有索引,可以执行布尔搜索(尽管速度较慢),在这种情况下,可以命名来自多个表的列。
上面的示例是一个基本示例,展示了如何在返回的行按相关性递减的顺序中使用MATCH()
函数。下一个示例展示了如何显式检索相关性值。返回的行没有排序,因为SELECT
语句中既没有WHERE
也没有ORDER BY
子句:
mysql> SELECT id, MATCH (title,body)
-> AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) AS score
-> FROM articles;
+----+---------------------+
| id | score |
+----+---------------------+
| 1 | 0.22764469683170319 |
| 2 | 0 |
| 3 | 0.22764469683170319 |
| 4 | 0 |
| 5 | 0 |
| 6 | 0 |
+----+---------------------+
6 rows in set (0.00 sec)
下面的示例更为复杂。该查询返回相关性值,并按相关性递减的顺序对行进行排序。为了实现这个结果,在SELECT
列表中指定MATCH()
两次:一次在SELECT
列表中,一次在WHERE
子句中。这不会增加额外开销,因为 MySQL 优化器注意到两次MATCH()
调用是相同的,并且只调用一次全文搜索代码。
mysql> SELECT id, body, MATCH (title,body)
-> AGAINST ('Security implications of running MySQL as root'
-> IN NATURAL LANGUAGE MODE) AS score
-> FROM articles
-> WHERE MATCH (title,body)
-> AGAINST('Security implications of running MySQL as root'
-> IN NATURAL LANGUAGE MODE);
+----+-------------------------------------+-----------------+
| id | body | score |
+----+-------------------------------------+-----------------+
| 4 | 1\. Never run mysqld as root. 2\. ... | 1.5219271183014 |
| 6 | When configured properly, MySQL ... | 1.3114095926285 |
+----+-------------------------------------+-----------------+
2 rows in set (0.00 sec)
用双引号("
)括起来的短语仅匹配包含该短语的行文字,就像它被输入的那样。全文引擎将短语拆分为单词,并在FULLTEXT
索引中为这些单词执行搜索。非单词字符不需要完全匹配:短语搜索只需要匹配包含与短语完全相同的单词并且顺序相同的匹配项。例如,"test phrase"
匹配"test, phrase"
。如果短语不包含索引中的任何单词,则结果为空。例如,如果所有单词要么是停用词要么比索引单词的最小长度短,结果为空。
MySQL 的FULLTEXT
实现将任何真实单词字符序列(字母,数字和下划线)视为一个单词。该序列也可以包含撇号('
),但不能连续超过一个。这意味着aaa'bbb
被视为一个单词,但aaa''bbb
被视为两个单词。单词开头或结尾的撇号将被FULLTEXT
解析器去除;'aaa'bbb'
会被解析为aaa'bbb
。
内置的FULLTEXT
解析器通过查找特定的分隔符字符来确定单词的起始和结束位置;例如,(空格),,
(逗号)和.
(句号)。如果单词没有被分隔符(例如,中文)分隔,内置的FULLTEXT
解析器无法确定单词的起始或结束位置。为了能够将这些语言中的单词或其他索引术语添加到使用内置FULLTEXT
解析器的FULLTEXT
索引中,您必须预处理它们,以便它们被某种任意的分隔符分隔。或者,您可以使用 ngram 解析器插件(用于中文,日文或韩文)或 MeCab 解析器插件(用于日文)创建FULLTEXT
索引。
可以编写一个插件来替换内置的全文解析器。有关详细信息,请参阅 MySQL 插件 API。例如解析器插件源代码,请查看 MySQL 源代码分发的plugin/fulltext
目录。
在全文搜索中会忽略一些词:
-
任何太短的单词都会被忽略。通过全文搜索找到的单词的默认最小长度为
InnoDB
搜索索引为三个字符,或者MyISAM
为四个字符。您可以通过在创建索引之前设置配置选项来控制截断:InnoDB
搜索索引的innodb_ft_min_token_size
配置选项,或者MyISAM
的ft_min_word_len
。注意
这种行为不适用于使用 ngram 解析器的
FULLTEXT
索引。对于 ngram 解析器,标记长度由ngram_token_size
选项定义。 -
停用词列表中的单词会被忽略。停用词是一些如“the”或“some”这样常见以至于被认为没有语义价值的单词。有一个内置的停用词列表,但可以被用户定义的列表覆盖。停用词列表和相关的配置选项对
InnoDB
搜索索引和MyISAM
索引是不同的。停用词处理由配置选项innodb_ft_enable_stopword
,innodb_ft_server_stopword_table
和innodb_ft_user_stopword_table
控制InnoDB
搜索索引,以及ft_stopword_file
控制MyISAM
索引。
参见第 14.9.4 节,“全文停用词”查看默认停用词列表以及如何更改它们。默认最小单词长度可以按照第 14.9.6 节,“调整 MySQL 全文搜索”中描述的方式进行更改。
集合和查询中的每个正确单词根据其在集合或查询中的重要性进行加权。因此,出现在许多文档中的单词权重较低,因为在这个特定集合中它的语义价值较低。相反,如果单词很少见,它将获得更高的权重。单词的权重组合在一起计算行的相关性。这种技术在大型集合中效果最佳。
MyISAM 限制
对于非常小的表,单词分布不能充分反映它们的语义价值,这种模型有时可能会为MyISAM
表上的搜索索引产生奇怪的结果。例如,尽管单词“MySQL”出现在先前显示的articles
表的每一行中,但在MyISAM
搜索索引中搜索该单词却没有结果:
mysql> SELECT * FROM articles
-> WHERE MATCH (title,body)
-> AGAINST ('MySQL' IN NATURAL LANGUAGE MODE);
Empty set (0.00 sec)
由于单词“MySQL”至少出现在 50%的行中,搜索结果为空,因此实际上被视为停用词。这种过滤技术更适用于大数据集,您可能不希望结果集从 1GB 表中返回每一秒的行,而不适用于小数据集,因为这可能导致热门术语的结果不佳。
当您首次尝试全文搜索以查看其工作原理时,50%的阈值可能会让您感到惊讶,并使InnoDB
表更适合用于全文搜索的实验。如果您创建一个MyISAM
表并只插入一两行文本,那么文本中的每个单词至少在 50%的行中出现。因此,在表包含更多行之前,任何搜索都不会返回任何结果。需要绕过 50%限制的用户可以在InnoDB
表上构建搜索索引,或者使用第 14.9.2 节,“布尔全文搜索”中解释的布尔搜索模式。