表 14.20 信息函数
名称 | 描述 |
---|---|
BENCHMARK() |
重复执行表达式 |
CHARSET() |
返回参数的字符集 |
COERCIBILITY() |
返回字符串参数的排序规则强制性值 |
COLLATION() |
返回字符串参数的排序规则 |
CONNECTION_ID() |
返回连接的连接 ID(线程 ID) |
CURRENT_ROLE() |
返回当前活动的 roles |
CURRENT_USER() , CURRENT_USER |
经过身份验证的用户名和主机名 |
DATABASE() |
返回默认(当前)数据库名称 |
FOUND_ROWS() |
对于具有 LIMIT 子句的 SELECT,如果不存在 LIMIT 子句将返回的行数 |
ICU_VERSION() |
ICU 库版本 |
LAST_INSERT_ID() |
上次 INSERT 的 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'
返回字符串参数的排序规则强制性值。
mysql> SELECT COERCIBILITY('abc' COLLATE utf8mb4_swedish_ci); -> 0 mysql> SELECT COERCIBILITY(USER()); -> 3 mysql> SELECT COERCIBILITY('abc'); -> 4 mysql> SELECT COERCIBILITY(1000); -> 5
返回值的含义如下表所示。较低的值具有较高的优先级。
强制性 含义 示例 0
显式排序规则 具有 COLLATE
子句的值1
无排序规则 具有不同排序规则的字符串的串联 2
隐式排序规则 列值、存储例程参数或局部变量 3
系统常量 USER()
返回值4
可强制性 文字字符串 5
数字 数字或时间值 6
可忽略 NULL
或从NULL
派生的表达式有关更多信息,请参见 Section 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()
返回的值与信息模式PROCESSLIST
表中的ID
列、SHOW PROCESSLIST
输出中的Id
列以及性能模式threads
表中的PROCESSLIST_ID
列显示的值相同。mysql> SELECT CONNECTION_ID(); -> 23786
警告更改
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
。-
注意
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()
可以确定结果的其余部分还需要多少其他页面。对于
UNION
语句,SQL_CALC_FOUND_ROWS
和FOUND_ROWS()
的使用比简单的SELECT
语句更复杂,因为LIMIT
可能出现在UNION
中的多个位置。它可以应用于UNION
中的各个SELECT
语句,也可以全局应用于UNION
结果。对于
UNION
,SQL_CALC_FOUND_ROWS
的目的是应该返回在没有全局LIMIT
的情况下将返回的行数。将SQL_CALC_FOUND_ROWS
与UNION
一起使用的条件如下只有使用
UNION ALL
,FOUND_ROWS()
的值才是精确的。如果使用没有ALL
的UNION
,则会发生重复删除,并且FOUND_ROWS()
的值只是一个近似值。如果
UNION
中没有LIMIT
,则会忽略SQL_CALC_FOUND_ROWS
并返回用于处理UNION
而创建的临时表中的行数。
除了这里描述的情况之外,
FOUND_ROWS()
的行为是未定义的(例如,在使用SELECT
语句失败并出现错误之后,其值是未定义的)。重要使用基于语句的复制无法可靠地复制
FOUND_ROWS()
。使用基于行的复制会自动复制此函数。 用于支持正则表达式操作的国际通用编码字符集 (ICU) 库的版本(请参阅第 14.8.2 节,“正则表达式”)。此函数主要用于测试用例。
LAST_INSERT_ID()
,LAST_INSERT_ID(
expr
)如果没有参数,
LAST_INSERT_ID()
将返回一个BIGINT UNSIGNED
(64 位)值,该值表示作为最近执行的INSERT
语句的结果,为AUTO_INCREMENT
列成功插入的第一个自动生成的值。如果未成功插入任何行,则LAST_INSERT_ID()
的值将保持不变。如果有参数,
LAST_INSERT_ID()
将返回一个无符号整数,如果参数是NULL
,则返回NULL
。例如,在插入生成
AUTO_INCREMENT
值的行之后,您可以像这样获取该值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()
值的语句,则更改后的值将被后续过程调用后的语句看到。对于更改值的存储函数和触发器,该值在函数或触发器结束时恢复,因此后面的语句不会看到更改的值。
生成的 ID 在服务器上按每个连接的方式维护。这意味着函数返回给特定客户端的值是该客户端对影响
AUTO_INCREMENT
列的最新语句生成的第一个AUTO_INCREMENT
值。即使其他客户端生成自己的AUTO_INCREMENT
值,此值也不能被其他客户端影响。这种行为确保每个客户端都可以检索自己的 ID,而无需考虑其他客户端的活动,也不需要锁或事务。如果将
AUTO_INCREMENT
列的某行设置为非“magic”值(即,不是NULL
且不是0
的值),则LAST_INSERT_ID()
的值不会更改。重要如果使用单个
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()
保持不变(或返回 0,如果连接尚未执行成功的INSERT
),并且对于非事务表,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 节,“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 值在服务器上被维护为最后一个自动生成的 value。它是多用户安全的,因为多个客户端可以发出UPDATE
语句并使用SELECT
语句(或mysql_insert_id()
)获得自己的序列值,而不会影响或被影响到生成自己的序列值的 other 客户端。请注意,
mysql_insert_id()
仅在INSERT
和UPDATE
语句之后更新,因此您不能在执行其他 SQL 语句(如SELECT
或SET
)之后使用 C API 函数来检索LAST_INSERT_ID(
的值。expr
)返回一个包含表示内存角色子图的 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;如果语句不返回结果集,则为受影响的行数。例如,对于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)
重要ROW_COUNT()
使用基于语句的复制时,不能可靠地复制。此函数使用基于行的复制时,会自动复制。此函数是
DATABASE()
的同义词。SESSION_USER()
是USER()
的同义词。与
USER()
一样,此函数可用于VARCHAR
或TEXT
列的默认值,如下面的CREATE TABLE
语句所示CREATE TABLE t (c VARCHAR(288) DEFAULT (SESSION_USER()));
SYSTEM_USER()
是USER()
的同义词。注意函数
SYSTEM_USER()
与SYSTEM_USER
权限不同。前者返回当前 MySQL 帐户名称。后者区分系统用户和普通用户帐户类别(参见 第 8.2.11 节,“帐户类别”)。与
USER()
一样,此函数可用于VARCHAR
或TEXT
列的默认值,如下面的CREATE TABLE
语句所示CREATE TABLE t (c VARCHAR(288) DEFAULT (SYSTEM_USER()));
以
utf8mb3
字符集返回当前 MySQL 用户名和主机名作为字符串。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(); -> '9.0.0-standard'