14.15 信息函数
表14.20 信息函数
Name | Description |
---|---|
BENCHMARK() |
重复执行一个表达式 |
CHARSET() |
返回参数的字符集 |
COERCIBILITY() |
返回字符串参数的collation强制性值 |
COLLATION() |
返回字符串参数的collation |
CONNECTION_ID() |
返回连接ID(线程ID) |
CURRENT_ROLE() |
返回当前活动角色 |
CURRENT_USER() , CURRENT_USER |
认证用户名称和主机名称 |
DATABASE() |
返回默认(当前)数据库名称 |
FOUND_ROWS() |
对于带有LIMIT子句的SELECT语句,返回的行数将是没有LIMIT子句时的行数 |
ICU_版本() |
ICU库版本 |
LAST_INSERT_ID() |
最后一次插入操作的AUTOINCREMENT列值 |
ROLES_GRAPHML() |
返回一个表示内存角色子图的GraphML文档 |
ROW_COUNT() |
更新的行数 |
SCHEMA() |
DATABASE()的同义词 |
SESSION_USER() |
USER()的同义词 |
SYSTEM_USER() |
USER()的同义词 |
USER() |
客户端提供的用户名和主机名 |
VERSION() |
返回一个字符串,表示MySQL服务器版本 |
-
函数
BENCHMARK()
执行表达式expr
重复count
次。它可以用来测量MySQL处理表达式的速度。结果值为0
,或对于不合适的参数,如NULL
或负整数重复计数时为NULL
。预期用法是在mysql客户端中,它报告查询执行时间:
mysql> SELECT BENCHMARK(1000000,AES_ENCRYPT('hello','goodbye')); +---------------------------------------------------+ | BENCHMARK(1000000,AES_ENCRYPT('hello','goodbye')) | +---------------------------------------------------+ | 0 | +---------------------------------------------------+ 1 row in set (4.74 sec)
报告的时间是客户端的已用时间,而不是服务器端的CPU时间。建议多次执行
BENCHMARK()
,并根据服务器机器的负载情况解释结果。BENCHMARK()
旨在测量标量表达式的运行性能,这对使用它和解释结果有重要影响:-
只能使用标量表达式。虽然表达式可以是一个子查询,但它必须返回一个单独的列和最多一个行。例如,
BENCHMARK(10, (SELECT * FROM t))
如果表t
有超过一个列或超过一个行将失败。 -
执行一个
SELECT
语句expr
N
次与执行SELECT BENCHMARK(
之间存在很大的差异。前者涉及解析器、优化器、表锁定和运行时评估N
,expr
)N
次,每个组件都执行一次。后者只涉及运行时评估N
次,其他所有组件只执行一次。已经分配的内存结构将被重用,并且在聚合函数中已经评估的结果可以通过本地缓存来改变结果。因此,使用BENCHMARK()
可以衡量运行时组件的性能,使其更关注该组件,并且去除网络、解析器、优化器等引入的“噪音”。
-
-
返回字符串参数的字符集,或者如果参数为
NULL
则返回NULL
。mysql> SELECT CHARSET('abc'); -> 'utf8mb3' mysql> SELECT CHARSET(CONVERT('abc' USING latin1)); -> 'latin1' mysql> SELECT CHARSET(USER()); -> 'utf8mb3'
-
返回字符串参数的collation coercibility值。
mysql> SELECT COERCIBILITY('abc' COLLATE utf8mb4_swedish_ci); -> 0 mysql> SELECT COERCIBILITY(USER()); -> 3 mysql> SELECT COERCIBILITY('abc'); -> 4 mysql> SELECT COERCIBILITY(1000); -> 5
返回值具有以下表格所示的含义。较低的值具有更高的优先级。
Coercibility Meaning Example 0
明确的排序 带有 COLLATE
子句的值1
无排序规则 不同排序规则下的字符串连接 2
隐式排序规则 列值、存储过程参数或局部变量 3
系统常量 USER()
返回值4
可强制转换 文字字符串 5
数字 数字或时间值 6
忽略 NULL
或来自NULL
的表达式更多信息,请见第12.8.4节,“排序规则在表达式中的强制转换”。
-
返回字符串参数的排序规则。
mysql> SELECT COLLATION('abc'); -> 'utf8mb4_0900_ai_ci' mysql> SELECT COLLATION(_utf8mb4'abc'); -> 'utf8mb4_0900_ai_ci' mysql> SELECT COLLATION(_latin1'abc'); -> 'latin1_swedish_ci'
-
返回连接ID(线程ID),每个连接都有一个唯一的ID,用于当前连接的客户端集。
CONNECTION_ID()
函数返回的值与信息_schema中的PROCESSLIST
表的ID
列、SHOW PROCESSLIST
输出中的Id
列和性能_schema中的threads
表的PROCESSLIST_ID
列相同。mysql> SELECT CONNECTION_ID(); -> 23786
Warning更改会话值
pseudo_thread_id
系统变量将影响CONNECTION_ID()
函数返回的值。 -
CURRENT_ROLE()
返回一个
utf8mb3
字符串,包含当前活动会话的角色列表,逗号分隔,如果没有则返回NONE
。该值反映sql_quote_show_create
系统变量的设置。假设一个账户被授予角色如下:
GRANT 'r1', 'r2' TO 'u1'@'localhost'; SET DEFAULT ROLE ALL TO 'u1'@'localhost';
在对
u1
的会话中,初始CURRENT_ROLE()
值命名了默认账户角色。使用SET ROLE
可以更改该值:mysql> SELECT CURRENT_ROLE(); +-------------------+ | CURRENT_ROLE() | +-------------------+ | `r1`@`%`,`r2`@`%` | +-------------------+ mysql> SET ROLE 'r1'; SELECT CURRENT_ROLE(); +----------------+ | CURRENT_ROLE() | +----------------+ | `r1`@`%` | +----------------+
-
返回 MySQL 账户的用户名和主机名组合,该账户确定了当前客户端的访问权限。返回值是一个在
utf8mb3
字符集中的字符串。CURRENT_USER()
的值可能不同于USER()
的值。mysql> SELECT USER(); -> 'davida@localhost' mysql> SELECT * FROM mysql.user; ERROR 1044: Access denied for user ''@'localhost' to database 'mysql' mysql> SELECT CURRENT_USER(); -> '@localhost'
示例说明,即使客户端指定了用户名为
davida
(如USER()
函数所示),服务器仍然使用匿名用户账户来验证客户端(见CURRENT_USER()
值的空用户名部分)。这种情况可能是因为没有在授权表中列出davida
账户。在存储程序或视图中,
CURRENT_USER()
返回定义对象的用户帐户(由其DEFINER
值给出),除非使用SQL SECURITY INVOKER
特性定义对象。在后一种情况下,CURRENT_USER()
返回对象的调用者。触发器和事件没有定义
SQL SECURITY
特性的选项,因此对这些对象,CURRENT_USER()
返回定义对象的用户帐户。要返回调用者,请使用USER()
或SESSION_USER()
。以下语句支持使用
CURRENT_USER()
函数来取代受影响用户或定义者的名称(可能包括主机);在这种情况下,CURRENT_USER()
将在需要的地方展开:关于
CURRENT_USER()
扩展对复制的影响,见第19.5.1.8节,“CURRENT_USER() 复制”。该函数可以用作
VARCHAR
或TEXT
列的默认值,例如在以下CREATE TABLE
语句中:CREATE TABLE t (c VARCHAR(288) DEFAULT (CURRENT_USER()));
-
返回当前数据库名称作为一个在
utf8mb3
字符集中的字符串。如果没有默认数据库,DATABASE()
返回NULL
。在存储程序中,默认数据库是与该程序关联的数据库,这可能不同于调用上下文中的默认数据库。mysql> SELECT DATABASE(); -> 'test'
如果没有默认数据库,
DATABASE()
返回NULL
。 -
Note
查询修饰符
SQL_ CALC_FOUND_ROWS
和伴随的FOUND_ROWS()
函数已经弃用,预计将在 MySQL 的未来版本中删除。使用LIMIT
执行查询,然后第二个查询使用COUNT(*)
和不使用LIMIT
来确定是否还有更多行。例如,取代这些查询:SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE id > 100 LIMIT 10; SELECT FOUND_ROWS();
使用这些查询แทน:
SELECT * FROM tbl_name WHERE id > 100 LIMIT 10; SELECT COUNT(*) FROM tbl_name WHERE id > 100;
COUNT(*)
受某些优化的影响。SQL_ CALC_FOUND_ROWS
会禁用一些优化。SELECT 语句可能包括一个
LIMIT
子句,以限制服务器返回给客户端的行数。在某些情况下,知道语句在不使用LIMIT
时将返回多少行,但又不想重新执行语句。要获得该行数,请在SELECT
语句中包含SQL_ CALC_FOUND_ROWS
选项,然后调用FOUND_ROWS()
:mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name -> WHERE id > 100 LIMIT 10; mysql> SELECT FOUND_ROWS();
第二个
SELECT
语句返回一个数字,表示第一个SELECT
语句在没有LIMIT
子句时将返回的行数。在最近一次成功
SELECT
语句中缺少SQL_CALC_FOUND_ROWS
选项时,FOUND_ROWS()
返回该语句返回的结果集中的行数。如果语句包含LIMIT
子句,FOUND_ROWS()
返回到限制前的行数。例如,如果语句包含LIMIT 10
或LIMIT 50, 10
,则FOUND_ROWS()
返回10或60。通过
FOUND_ROWS()
可用的行数是瞬态的,不应在SELECT SQL_CALC_FOUND_ROWS语句后的语句中使用。如果您需要将其保存,以便后续使用:mysql> SELECT SQL_CALC_FOUND_ROWS * FROM ... ; mysql> SET @rows = FOUND_ROWS();
如果您使用
SELECT SQL_CALC_FOUND_ROWS
,MySQL必须计算完整结果集中的行数。然而,这比在没有LIMIT
子句时重新运行查询更快,因为结果集不需要发送到客户端。SQL_CALC_FOUND_ROWS
和FOUND_ROWS()
在某些情况下非常有用,例如,您想限制查询返回的行数,但同时也想知道完整结果集中的行数,而不需要重新运行查询。一个示例是Web脚本,它显示了分页显示,包含链接到其他搜索结果部分的页面。使用FOUND_ROWS()
可以帮助您确定需要其他页面来显示剩余结果。使用
SQL_CALC_FOUND_ROWS
和FOUND_ROWS()
对于UNION
语句比对简单的SELECT
语句更复杂,因为LIMIT
可能出现在UNION
中的多个位置。它可能应用于UNION
中的单个SELECT
语句,或者对整个UNION
结果进行全局应用。对
UNION
的SQL_ CALC_FOUND_ROWS
意图是返回没有全局LIMIT
限制时将要返回的行数。使用UNION
时SQL_ CALC_FOUND_ROWS
的条件是:-
如果使用
UNION ALL
,则FOUND_ROWS()
的值是精确的。如果使用UNION
而不使用ALL
,则会发生重复行的删除,并且FOUND_ROWS()
的值只是一致的。 -
如果
UNION
中没有LIMIT
,则SQL_ CALC_FOUND_ROWS
将被忽略,并返回处理UNION
时创建的临时表中的行数。
除此之外,
FOUND_ROWS()
的行为是未定义的(例如,在失败的SELECT
语句后其值的计算结果)。ImportantFOUND_ROWS()
使用statement-based replication不太可靠。这一函数自动使用row-based replication。 -
支持正则表达式操作的国际组件Unicode(ICU)库版本(见第14.8.2节,“Regular Expressions”)。这函数主要用于测试用例。
-
LAST_INSERT_ID()
,LAST_INSERT_ID(
expr
)无参数时,
LAST_INSERT_ID()
返回一个 64 位无符号整数值,表示最近执行的INSERT
语句中成功插入的第一个自动生成的值。该值保持不变,如果没有成功插入任何行。带参数时,
LAST_INSERT_ID()
返回一个无符号整数值或NULL
,如果参数为NULL
。例如,在插入生成自动增长值的行后,您可以使用以下方式获取该值:
mysql> SELECT LAST_INSERT_ID(); -> 195
当前执行的语句不影响
LAST_INSERT_ID()
的值。假设您使用一个语句生成一个AUTO_INCREMENT
值,然后在多行INSERT
语句中引用LAST_INSERT_ID()
,该语句将插入一个表的AUTO_INCREMENT
列。LAST_INSERT_ID()
的值在第二个语句中保持不变;对于第二个和后续行,它们的值不会受到早期插入行的影响。 (您应该注意,如果您混合使用LAST_INSERT_ID()
和LAST_INSERT_ID(
,那么结果是未定义的。)expr
)如果前一个语句返回错误,
LAST_INSERT_ID()
的值是未定义的。对于事务表,如果语句由于错误而回滚,LAST_INSERT_ID()
的值将保持未定义状态。对于手动ROLLBACK
,LAST_INSERT_ID()
的值不会恢复到事务开始前的状态;它将保持在ROLLBACK点的状态。存储程序(过程或函数)或触发器体内,
LAST_INSERT_ID()
的值将像在语句外部执行一样变化。这些对象的影响对LAST_INSERT_ID()
的值,取决于存储程序或触发器的类型:-
如果存储程序执行语句,该语句改变
LAST_INSERT_ID()
的值,后续语句将看到该变化。 -
对于存储函数和触发器,如果它们改变了
LAST_INSERT_ID()
的值,该值在函数或触发器结束时将恢复,后续语句将不见该变化。
生成的ID在服务器上以每个连接维护。这意味着,函数返回给定的客户端的是最近一次影响该客户端的AUTO_INCREMENT列的最早生成的值。这个值不能被其他客户端所影响,即使它们也生成了自己的AUTO_INCREMENT值。这一行为确保每个客户端可以无需考虑其他客户端活动和锁定或事务的情况下, Retrieves its own ID。
LAST_INSERT_ID()
的值不会被改变,如果你将行中的AUTO_INCREMENT列设置为非“magic”值(即不是NULL和0)。Important使用单个
INSERT
语句插入多行时,LAST_INSERT_ID()
只返回第一个插入行的值。这是为了使得可以轻松地在其他服务器上重复相同的INSERT
语句。例如:
mysql> USE test; mysql> CREATE TABLE t ( id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, name VARCHAR(10) NOT NULL ); mysql> INSERT INTO t VALUES (NULL, 'Bob'); mysql> SELECT * FROM t; +----+------+ | id | name | +----+------+ | 1 | Bob | +----+------+ mysql> SELECT LAST_INSERT_ID(); +------------------+ | LAST_INSERT_ID() | +------------------+ | 1 | +------------------+ mysql> INSERT INTO t VALUES (NULL, 'Mary'), (NULL, 'Jane'), (NULL, 'Lisa'); mysql> SELECT * FROM t; +----+------+ | id | name | +----+------+ | 1 | Bob | | 2 | Mary | | 3 | Jane | | 4 | Lisa | +----+------+ mysql> SELECT LAST_INSERT_ID(); +------------------+ | LAST_INSERT_ID() | +------------------+ | 2 | +------------------+
第二个
INSERT
语句将三个新行插入到t
中,但是第一个这些行的ID为2
LAST_INSERT_ ID()
在以下SELECT
语句中返回的值。如果使用
INSERT IGNORE
并且该行被忽略,LAST_INSERT_ID()
将保持不变(或在连接尚未执行成功的INSERT
语句时返回0),对于非事务表,AUTO_INCREMENT
计数器不增加。对于InnoDB
表,如果innodb_autoinc_lock_mode
设置为1
或2
,则LAST_INSERT_ID()
将增加,如下示例所示:mysql> USE test; mysql> SELECT @@innodb_autoinc_lock_mode; +----------------------------+ | @@innodb_autoinc_lock_mode | +----------------------------+ | 1 | +----------------------------+ mysql> CREATE TABLE `t` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `val` INT(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `i1` (`val`) ) ENGINE=InnoDB; # Insert two rows mysql> INSERT INTO t (val) VALUES (1),(2); # With auto_increment_offset=1, the inserted rows # result in an AUTO_INCREMENT value of 3 mysql> SHOW CREATE TABLE t\G *************************** 1. row *************************** Table: t Create Table: CREATE TABLE `t` ( `id` int(11) NOT NULL AUTO_INCREMENT, `val` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `i1` (`val`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci # LAST_INSERT_ID() returns the first automatically generated # value that is successfully inserted for the AUTO_INCREMENT column mysql> SELECT LAST_INSERT_ID(); +------------------+ | LAST_INSERT_ID() | +------------------+ | 1 | +------------------+ # The attempted insertion of duplicate rows fail but errors are ignored mysql> INSERT IGNORE INTO t (val) VALUES (1),(2); Query OK, 0 rows affected (0.00 sec) Records: 2 Duplicates: 2 Warnings: 0 # With innodb_autoinc_lock_mode=1, the AUTO_INCREMENT counter # is incremented for the ignored rows mysql> SHOW CREATE TABLE t\G *************************** 1. row *************************** Table: t Create Table: CREATE TABLE `t` ( `id` int(11) NOT NULL AUTO_INCREMENT, `val` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `i1` (`val`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci # The LAST_INSERT_ID is unchanged because the previous insert was unsuccessful mysql> SELECT LAST_INSERT_ID(); +------------------+ | LAST_INSERT_ID() | +------------------+ | 1 | +------------------+
更多信息,请见第17.6.1.6节,“InnoDB中的AUTO_INCREMENT处理”。
如果将
expr
作为参数传递给LAST_INSERT_ID()
,函数返回参数的值,并将其记忆为LAST_INSERT_ID()
下一个返回值。这样可以模拟序列:-
创建一个表来存储序列计数器,并初始化它:
mysql> CREATE TABLE sequence (id INT NOT NULL); mysql> INSERT INTO sequence VALUES (0);
-
使用表生成序列号,如下所示:
mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1); mysql> SELECT LAST_INSERT_ID();
UPDATE语句将序列计数器递增,并导致
LAST_INSERT_ID()
的下一个调用返回更新后的值。SELECT语句检索该值。可以使用mysql_insert_id()
C API函数也可以获取该值。请参阅mysql_insert_id()。
您可以在不调用
LAST_INSERT_ID()
的情况下生成序列,但是使用函数的方式有助于将ID值保存在服务器中作为最后一个自动生成的值。它是多用户安全的,因为多个客户端可以发出UPDATE
语句,并使用SELECT
语句(或mysql_insert_id()
)获取自己的序列值,而不影响或被其他客户端生成的序列值所影响。请注意
mysql_insert_id()
仅在INSERT
和UPDATE
语句执行后更新,因此您不能使用C API函数来检索LAST_INSERT_ID(
的值,例如在执行其他SQL语句,如expr
)SELECT
或SET
时。 -
-
返回一个包含 GraphML 文档表示内存角色子图的
utf8mb3
字符串。需要拥有ROLE_ADMIN
权限(或弃用的SUPER
权限)才能在<graphml>
元素中看到内容。否则,结果显示一个空元素:mysql> SELECT ROLES_GRAPHML(); +---------------------------------------------------+ | ROLES_GRAPHML() | +---------------------------------------------------+ | <?xml version="1.0" encoding="UTF-8"?><graphml /> | +---------------------------------------------------+
-
ROW_COUNT()
返回以下值:-
DDL 语句:0。这适用于语句,如
CREATE TABLE
或DROP TABLE
。 -
除
SELECT
之外的 DML 语句:影响行数。这适用于语句,如UPDATE
、INSERT
、DELETE
(之前一样),现在也适用于语句,如ALTER TABLE
和LOAD DATA
。 -
SELECT
: -1 如果语句返回结果集,否则是“affected” 中的行数。例如,对于SELECT * FROM t1
,ROW_COUNT()
返回 -1。对于SELECT * FROM t1 INTO OUTFILE '
,file_name
'ROW_COUNT()
返回写入到文件中的行数。 -
SIGNAL
语句:0。
对于
UPDATE
语句,默认的 affected-rows 值是实际更改的行数。如果您在连接到 mysqld 时指定了CLIENT_FOUND_ROWS
标志到mysql_real_connect()
,affected-rows 值是“found” 中的行数,即 WHERE 子句匹配到的行数。对于
REPLACE
语句,affected-rows 值是 2,如果新行替换了旧行,因为在这种情况下,一行被插入后删除了重复的行。对于
INSERT ... ON DUPLICATE KEY UPDATE
语句,受影响的行数值为1,如果插入的是新行,2如果更新了现有行,0如果现有行保持不变。如果您指定了CLIENT_FOUND_ROWS
标志,则受影响的行数值为1(而不是0)如果现有行保持不变。ROW_COUNT()
值类似于mysql_affected_rows()
C API 函数和mysql 客户端在执行语句后显示的行数。mysql> INSERT INTO t VALUES(1),(2),(3); Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> SELECT ROW_COUNT(); +-------------+ | ROW_COUNT() | +-------------+ | 3 | +-------------+ 1 row in set (0.00 sec) mysql> DELETE FROM t WHERE i IN(1,2); Query OK, 2 rows affected (0.00 sec) mysql> SELECT ROW_COUNT(); +-------------+ | ROW_COUNT() | +-------------+ | 2 | +-------------+ 1 row in set (0.00 sec)
ImportantROW_COUNT()
不可靠地使用语句-基于复制。该函数自动使用行-基于复制。 -
-
该函数是
DATABASE()
的同义词。 -
SESSION_USER()
是USER()
的同义词。像
USER()
一样,这个函数可以用作VARCHAR或TEXT列的默认值,例如在以下CREATE TABLE
语句中:CREATE TABLE t (c VARCHAR(288) DEFAULT (SESSION_USER()));
-
SYSTEM_USER()
是USER()
的同义词。Note函数
SYSTEM_USER()
与SYSTEM_USER
权限不同。前者返回当前MySQL账户名称,后者区分系统用户和普通用户账户类别(见第8.2.11节,“Account Categories”)。像
USER()
一样,这个函数可以用作VARCHAR或TEXT列的默认值,例如在以下CREATE TABLE
语句中:CREATE TABLE t (c VARCHAR(288) DEFAULT (SYSTEM_USER()));
-
返回当前MySQL用户名和主机名作为utf8mb3字符集的字符串。
mysql> SELECT USER(); -> 'davida@localhost'
该值表示您在连接到服务器时指定的用户名和来自您连接的客户端主机。该值可能不同于
CURRENT_USER()
的值。这个函数可以用作VARCHAR或TEXT列的默认值,例如在以下
CREATE TABLE
语句中:CREATE TABLE t (c VARCHAR(288) DEFAULT (USER()));
-
返回 MySQL 服务器版本的字符串。该字符串使用
utf8mb3
字符集。值可能包含版本号外的后缀。请参阅version
系统变量在第 7.1.8 节,“服务器系统变量”的描述。该函数对于语句基于的复制不安全。如果您在
binlog_ format
设置为STATEMENT
时使用该函数,会记录警告。mysql> SELECT VERSION(); -> '8.4.0-standard'