表 14.20 信息函数
Name | Description |
---|---|
BENCHMARK() |
重复执行一个表达式 |
CHARSET() |
返回参数的字符集 |
COERCIBILITY() |
返回字符串参数的协调性值 |
COLLATION() |
返回字符串参数的排序规则 |
CONNECTION_ID() |
返回连接 ID(线程 ID) |
CURRENT_ROLE() |
返回当前活动角色 |
CURRENT_USER() , CURRENT_USER |
认证用户名称和主机名称 |
DATABASE() |
返回默认(当前)数据库名称 |
FOUND_ROWS() |
对于带有 LIMIT 子句的 SELECT,返回没有 LIMIT 子句时的行数 |
ICU_VERSION() |
ICU 库版本 |
LAST_INSERT_ID() |
最后插入的 AUTOINCREMENT 列的值 |
ROLES_GRAPHML() |
返回表示内存角色子图的 GraphML 文档 |
ROW_COUNT() |
更新的行数 |
SCHEMA() |
DATABASE() 的同义词 |
SESSION_USER() |
USER() 的同义词 |
SYSTEM_USER() |
USER() 的同义词 |
USER() |
客户端提供的用户名和主机名 |
VERSION() |
返回 MySQL 服务器版本字符串 |
-
The
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'
-
返回字符串参数的协调性值。
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()
返回的值与 Information SchemaPROCESSLIST
表的ID
列、SHOW PROCESSLIST
输出的Id
列和 Performance Schemathreads
表的PROCESSLIST_ID
列相同。mysql> SELECT CONNECTION_ID(); -> 23786
Warning更改会话值的
pseudo_thread_id
系统变量将更改CONNECTION_ID()
函数返回的值。 -
返回一个
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
,以确定是否有其他行。例如, instead of 这些查询:SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE id > 100 LIMIT 10; SELECT FOUND_ROWS();
使用这些查询 instead:
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
时将返回多少行,但不需要重新运行语句。要获取该行计数,包括SQL_CALC_FOUND_ROWS
选项在SELECT
语句中,然后调用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()
返回限制的行数。例如,FOUND_ROWS()
返回 10 或 60,分别对应语句包括LIMIT 10
或LIMIT 50, 10
。通过
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
中的多个地方。它可能应用于单个SELECT
语句中,也可以应用于整个UNION
结果。使用
SQL_CALC_FOUND_ROWS
的意图是,它应该返回没有全局LIMIT
的行计数。使用SQL_CALC_FOUND_ROWS
与UNION
的条件是:-
只有在使用
UNION ALL
时,FOUND_ROWS()
的值才是精确的。如果使用UNION
而不带ALL
,则会发生重复删除,FOUND_ROWS()
的值只是近似的。 -
如果
UNION
中没有LIMIT
,则SQL_CALC_FOUND_ROWS
将被忽略,并返回用于处理UNION
的临时表中的行数。
除了这里描述的情况外,
FOUND_ROWS()
的行为是未定义的(例如,在SELECT
语句失败时的值)。ImportantFOUND_ROWS()
不可靠地使用基于语句的复制。这函数自动使用基于行的复制。 -
用于支持正则表达式操作的 International Components for Unicode (ICU) 库的版本(见 第 14.8.2 节,“正则表达式”)。这个函数主要用于测试用例。
-
LAST_INSERT_ID()
,LAST_INSERT_ID(
expr
)不带参数时,
LAST_INSERT_ID()
返回一个BIGINT UNSIGNED
(64 位)值,表示最近执行的INSERT
语句中成功插入的第一个自动生成的值。如果没有行被成功插入,则LAST_INSERT_ID()
的值保持不变。带参数时,
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
值。这种行为确保每个客户端可以检索自己的ID,而不需要锁定或事务。如果您将
AUTO_INCREMENT
列的行设置为非“magic”值(即不是NULL也不是0),LAST_INSERT_ID()
的值将不变。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
,则AUTO_INCREMENT
计数器将递增,如下面的示例所示: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 节,“AUTO_INCREMENT 处理 in InnoDB”。
如果
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
。 -
DML 语句(除
SELECT
外):受影响的行数。这适用于语句,如UPDATE
、INSERT
或DELETE
(如前所述),现在也适用于语句,如ALTER TABLE
和LOAD DATA
。 -
SELECT
:-1 如果语句返回结果集,或者如果不返回结果集,则为受影响的行数。例如,对于SELECT * FROM t1
,ROW_COUNT()
返回 -1。对于SELECT * FROM t1 INTO OUTFILE '
,file_name
'ROW_COUNT()
返回写入文件的行数。 -
SIGNAL
语句:0。
对于
UPDATE
语句,默认情况下,受影响的行数是实际更改的行数。如果您在连接到 mysqld 时指定了CLIENT_FOUND_ROWS
标志到mysql_real_connect()
,则受影响的行数是匹配WHERE
子句的行数。对于
REPLACE
语句,受影响的行数是 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 节,“账户类别”)。像
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
字符集。该值可能还有版本号以外的后缀。见 第 7.1.8 节,“服务器系统变量” 中的version
系统变量的描述。该函数对于基于语句的复制是不安全的。如果您在
binlog_format
设置为STATEMENT
时使用该函数,将记录警告。mysql> SELECT VERSION(); -> '8.3.0-standard'