MySQL 函数和运算符:信息函数

来自Wikioe
跳到导航 跳到搜索


信息函数:

Name Description
BENCHMARK() 重复执行一个表达式

“BENCHMARK(count,expr)”:重复执行“expr”“count”次。它可以用来计时 MySQL 处理表达式的速度。对于不适当的参数(例如NULL或负重复计数),结果值是 0 或 NULL。

预期用途来自mysqlClient 端,该 Client 端报告查询执行时间:

mysql> SELECT BENCHMARK(1000000,AES_ENCRYPT('hello','goodbye'));
+---------------------------------------------------+
| BENCHMARK(1000000,AES_ENCRYPT('hello','goodbye')) |
+---------------------------------------------------+
|                                                 0 |
+---------------------------------------------------+
1 row in set (4.74 sec)
  • 报告的时间是 Client 端的经过时间,而不是服务器端的 CPU 时间。建议执行BENCHMARK()次,并解释有关服务器计算机负载的结果。


BENCHMARK() 用于测量标量表达式的运行时性能,这对使用它和解释结果的方式有一些重要影响:

  1. 只能使用标量表达式。尽管表达式可以是子查询,但它必须返回单列和最多单行。例如,如果表t具有多于一列或多于一行,则“BENCHMARK(10,(SELECT * FROM t))”将失败。
  2. 在涉及的开销方面,执行“SELECT expr”语句 N 次的时间与执行“SELECT BENCHMARK(N, expr)”的时间不同。两者的执行配置文件非常不同,您不应期望它们花费相同的时间:
    1. 前者涉及解析器,优化器,表锁定和运行时评估 N 每次。
    2. 后者仅涉及运行时评估 N 次,而所有其他组件仅评估一次。已经分配的内存结构将被重用,并且运行时优化(例如已针对聚合函数评估的结果的本地缓存)可能会更改结果。

BENCHMARK()的使用因此通过赋予该组件更多的权重并消除网络,解析器,优化器等引入的影响来衡量该组件的性能。

CHARSET() 返回参数的字符集

“CHARSET(str)”:返回字符串参数的字符集。

mysql> SELECT CHARSET('abc');
        -> 'latin1'
mysql> SELECT CHARSET(CONVERT('abc' USING utf8));
        -> 'utf8'
mysql> SELECT CHARSET(USER());
        -> 'utf8'
COERCIBILITY() 返回字符串参数的排序规则强制性值

“COERCIBILITY(str)”:返回字符串参数的排序规则强制性值。【较低的值具有较高的优先级

mysql> SELECT COERCIBILITY('abc' COLLATE latin1_swedish_ci);
        -> 0
mysql> SELECT COERCIBILITY(USER());
        -> 3
mysql> SELECT COERCIBILITY('abc');
        -> 4
mysql> SELECT COERCIBILITY(1000);
        -> 5

返回值的含义如下:

Coercibility Meaning Example
0 Explicit collation 带有COLLATE子句的值
1 No collation 具有不同排序规则的字符串的串联
2 Implicit collation 列值,存储的例程参数或局部变量
3 System constant USER()返回值
4 Coercible Literal string
5 Numeric 数值或时间值
5 Ignorable NULL或源自NULL的表达式
COLLATION() 返回字符串参数的排序规则

“COLLATION(str)”:返回字符串参数的排序规则。

mysql> SELECT COLLATION('abc');
        -> 'latin1_swedish_ci'
mysql> SELECT COLLATION(_utf8'abc');
        -> 'utf8_general_ci'
CONNECTION_ID() 返回连接的连接 ID(线程 ID)
  • 每个连接都有一个在当前连接的 Client 端集中唯一的 ID。
  • “CONNECTION_ID()”返回的值与“INFORMATION_SCHEMA.PROCESSLIST”表的ID列,“SHOW PROCESSLIST”输出的“Id”列和“Performance Schema threads”表的“PROCESSLIST_ID”列中显示的值类型相同。
mysql> SELECT CONNECTION_ID();
        -> 23786
CURRENT_USER(), CURRENT_USER 经过身份验证的用户名和主机名
  • 返回的是服务器用来认证当前 Client 端的 MySQL 帐户的用户名和主机名组合。该帐户确定您的访问权限。
  • 返回值是utf8字符集中的字符串。
  • “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'
    
    如上:尽管 Client 端指定了 davida 的用户名(如USER()函数的值所示),但服务器仍使用匿名用户帐户对 Client 端进行了身份验证(如CURRENT_USER()值的空用户名部分所示)。发生这种情况的一种方法是,在davida的授予表中没有列出帐户。


在存储的程序或视图中,“CURRENT_USER()”返回定义对象的用户的帐户(由其“DEFINER”值给出),除非使用“SQL SECURITY INVOKER”特性定义。在后一种情况下,“CURRENT_USER()”返回对象的调用者。

触发器和事件没有定义“SQL SECURITY”特性的选项,因此对于这些对象,“CURRENT_USER()”返回定义该对象的用户的帐户。要返回调用者,请使用“USER()”或“SESSION_USER()”。

DATABASE() 返回默认(当前)数据库名称
  • 以 utf8 字符集的字符串形式返回默认(当前)数据库名称。
  • 如果没有默认数据库,则DATABASE()返回NULL。
  • 在存储的例程中,默认数据库是与该例程关联的数据库,它不一定与调用上下文中的默认数据库相同。
mysql> SELECT DATABASE();
        -> 'test'
FOUND_ROWS() 对于带有 LIMIT 子句的 SELECT,如果没有 LIMIT 子句,则将返回的行数【???】

“SELECT”语句可以包含“LIMIT”子句以限制服务器返回给 Client 端的行数。在某些情况下,希望知道该语句在没有“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返回一个数字,该数字指示如果不使用LIMIT子句写入第一个SELECT将会返回多少行。


在最近成功执行的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();


“UNION”语句的使用 SQL_CALC_FOUND_ROWS 和 FOUND_ROWS() 比简单SELECT语句的使用更为复杂,因为LIMIT可能出现在UNION的多个位置。它可以应用于UNION中的单个SELECT语句,也可以应用于整个UNION结果。

SQL_CALC_FOUND_ROWS对于UNION的意图是,它应返回没有全局LIMIT时将返回的行数。【???】

将SQL_CALC_FOUND_ROWS与UNION一起使用的条件是:

  1. SQL_CALC_FOUND_ROWS关键字必须出现在UNION的前SELECT中。
  2. 仅当使用UNION ALL时,FOUND_ROWS()的值才是正确的。如果使用UNION而不使用ALL,则会发生重复删除,并且FOUND_ROWS()的值仅是近似值。
  3. 如果UNION中不存在LIMIT,则SQL_CALC_FOUND_ROWS将被忽略并返回在临时表中创建的用于处理UNION的行数。

除了此处描述的情况外,FOUND_ROWS()的行为是不确定的(例如,在SELECT语句后由于错误而失败的值)。

LAST_INSERT_ID() 最后一个 INSERT 的 AUTOINCREMENT 列的值
  1. “LAST_INSERT_ID()”:不带任何参数的LAST_INSERT_ID()返回BIGINT UNSIGNED(64 位)值,该值表示由于最近执行的“INSERT”语句而成功为“AUTO_INCREMENT”列成功插入的第一个自动生成的值。如果没有成功插入行,则LAST_INSERT_ID()的值保持不变。
  2. “LAST_INSERT_ID(expr)”:带有一个参数的LAST_INSERT_ID()返回无符号整数
mysql> SELECT LAST_INSERT_ID();
        -> 195


  • 如果将行的 AUTO_INCREMENT 列设置为非“magic”值(即,不是NULL也不是0的值),则LAST_INSERT_ID()的值不会更改。
  • 如果前一条语句返回错误,则LAST_INSERT_ID()的值不确定。
  • 对于事务表,如果由于错误而回滚该语句,则LAST_INSERT_ID()的值将保持未定义状态。
    对于手动ROLLBACK,LAST_INSERT_ID()的值不会恢复为 Transaction 之前的值;它保持在ROLLBACK的位置。


  • 如果使用单个 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 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 DEFAULT CHARSET=latin1;

# 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=latin1

# 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=latin1

# The LAST_INSERT_ID is unchanged because the previous insert was unsuccessful

mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                1 |
+------------------+
【???】


如果将“expr”作为LAST_INSERT_ID()的参数给出,则该参数的值由函数返回,并记为LAST_INSERT_ID()返回的下一个值。这可以用来模拟序列:

  1. 创建一个表来保存序列计数器并对其进行初始化:
    mysql> CREATE TABLE sequence (id INT NOT NULL);
    mysql> INSERT INTO sequence VALUES (0);
    
  2. 使用该表生成如下的序列号:
    mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);
    mysql> SELECT LAST_INSERT_ID();
    


【????????????????????????????????】

ROW_COUNT() 更新的行数

ROW_COUNT()返回的值如下:

  1. DDL 语句:0。【这适用于诸如“CREATE TABLE”或“DROP TABLE”的语句】
  2. SELECT以外的 DML 语句:受影响的行数。【这适用于诸如“UPDATE”,“INSERT”或“DELETE”之类的语句(如前所述),但现在也适用于诸如“ALTER TABLE”和“LOAD DATA”之类的语句】
  3. SELECT:如果语句返回结果集,则为-1,否则返回“受影响”的行数。
    例如,对于SELECT * FROM t1,ROW_COUNT()返回-1.对于SELECT * FROM t1 INTO OUTFILE 'file_name',ROW_COUNT()返回写入文件的行数。
  4. SIGNAL 语句:0
  • 对于 UPDATE 语句,默认情况下受影响的行值为实际更改的行数。如果在连接到mysqld时将“CLIENT_FOUND_ROWS”标志指定为“mysql_real_connect()”,则受影响的行值为“找到”的行数;否则,为 0。也就是说,与WHERE子句匹配。【???】
  • 对于 REPLACE 语句,如果新行替换了旧行,则受影响的行值为 2,因为在这种情况下,删除重复项后将插入一行。
  • 对于“INSERT ... ON DUPLICATE KEY UPDATE”语句【???】,如果将行作为新行插入,则每行的受影响行值为 1;如果更新了现有行,则为 2;如果将现有行设置为其当前值,则为 0。如果指定“CLIENT_FOUND_ROWS”标志,则将现有行设置为其当前值时,受影响的行值为 1(而不是 0)。
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)
SCHEMA() DATABASE()的同义词
SESSION_USER() USER()的同义词
SYSTEM_USER() USER()的同义词
USER() Client 端提供的用户名和主机名
  • 该值指示您在连接到服务器时指定的用户名,以及从中连接的 Client 端主机。该值可以与“CURRENT_USER()”的值不同。
  • 以utf8字符集的字符串形式返回当前 MySQL 用户名和主机名。
mysql> SELECT USER();
        -> 'davida@localhost'
VERSION() 返回指示 MySQL 服务器版本的字符串
  • 该字符串使用utf8字符集。该值除版本号外还可以带有后缀。
  • 此功能对于基于语句的复制不安全。如果在“binlog_format”设置为“STATEMENT”时使用此功能,则会记录一条警告。【???】
mysql> SELECT VERSION();
        -> '5.7.32-standard'