6.3.6.2 辅助功能函数
DATABASE()
返回当前数据库名:
mysql> SELECT DATABASE();
-> 'test'
如果没有当前数据库,DATABASE() 返回一个空字符串。
USER()
SYSTEM_USER()
SESSION_USER()
返回当前 MySQL 用户名:
mysql> SELECT USER();
-> 'davida@localhost'
在 MySQL 3.22.11 或更新的版本中,返回值包含用户名和客户机的主机名。你可以象下面所示的仅取出用户名部分(无论值是否包含一个主机名部分,它均能正常工作):
mysql> SELECT SUBSTRING_INDEX(USER(),"@",1);
-> 'davida'
CURRENT_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'
PASSWORD(str)
OLD_PASSWORD(str)
从纯文本口令 str 计算一个口令字符串。这个函数用于对存储到授权表 user 的Password 列中的 MySQL 口令进行加密。
mysql> SELECT PASSWORD('badpwd');
-> '7f84554057dd964b'
PASSWORD() 加密是不可逆的。 PASSWORD() 不以与 Unix 口令加密相同的方式进行口令加密。参见 ENCRYPT()。 注意, PASSWORD() 函数是用于在 MySQL 服务中验证系统的,你不应该 在你的应用程序中使用它。你可以使用 MD5() 或 SHA1() 代替使用它。同样查看 RFC-2195 可获得有关应用程序的口令处理与安全验证的更多信息。
ENCRYPT(str[,salt])
Encrypt使用 Unix crypt() 系统调用加密 str 。参数 salt 应该是一个有两个字符的字符串,(在 MySQL 3.22.16 中,salt 可以超过两个字符。):
mysql> SELECT ENCRYPT("hello");
-> 'VxuFAJXVARROc'
如果 crypt() 在你的系统上不可用,ENCRYPT() 总是返回 NULL。 ENCRYPT() 只保留 str 中前 8 个字符,而忽略其它所有的,至少在某些系统上是这样的。这取决于底层 crypt() 系统调用的行为。
ENCODE(str,pass_str)
使用 pass_str 做为密钥加密 str。使用 DECODE() 解密结果。结果是一个与 string 一样长的二进制字符。如果希望将它保存到一个列中,请使用 BLOB 列类型。
DECODE(crypt_str,pass_str)
使用 pass_str 作为密钥解密加密后的字符串 crypt_str。crypt_str 应该是一个由 ENCODE() 返回的字符串。
MD5(string)
计算一个字符串的 MD5 128 位校验和。值作为一个 32 位的十六进制数字返回,例如,被用于一个哈希(hash)键:
mysql> SELECT MD5("testing");
-> 'ae2b1fca515949e5d54fb22b8ed95575'
这是 "RSA 数据安全公司的 MD5 消息-摘要算法"。
SHA1(string)
SHA(string)
计算一个字符串的 SHA1 160 位校验和(在 RFC 3174 (Secure Hash Algorithm) 中被描述)。返回值是一个 40 位的十六进制数字,或在输入参数为 NULL 的情况下,返回值为 NULL。一个使用这个函数的可能就是用于一个哈希键。你也可以使用它作为存储密码时的密码安全函数。
mysql> SELECT SHA1("abc");
-> 'a9993e364706816aba3e25717850c26c9cd0d89d'
SHA1() 在MySQL 4.0.2 中被加入,并可被当做比 MD5() 加密更安全的等价物。SHA() 是 SHA1() 的同义词。
AES_ENCRYPT(string,key_string)
AES_DECRYPT(string,key_string)
这些函数允许使用官方的 AES(Advanced Encryption Standardadvanced 先进的密码技术标准) 算法加密/解密数据。加密时使用 128 位长的密钥,但是你可以通过修改源码将其扩展到 256 位。我们选择 128 位是因为它更快一点并且已足够安全了。 输入的参数可以是任意长度的。如果任何一个参数是 NULL,这个函数返回值也将是 NULL。 因为 AES 是一个块级的算法,加密不同长度的字符串时会对其进行填充,因而结果字符串的长度也可以通过 16*(trunc(string_length/16)+1) 计算出。 如果 AES_DECRYPT() 发现数据无效或错误的填料,它将返回 NULL。可是,如果输入的数据或密钥是无效的,函数仍然可能返回一个非 NULL 值 (可能是无用的信息)。 通过修改你的 SQL 语句,你可以使用 AES 函数以一个加密的形式存储数据:
INSERT INTO t VALUES (1,AES_ENCRYPT("text","password"));
尽量避免在一个连接上的每个查询中传递密钥,这样可以得到更高的安全性,上述方式可以通过连接时在服务器端存储密钥来完成:
SELECT @password:="my password";
INSERT INTO t VALUES (1,AES_ENCRYPT("text",@password));
AES_ENCRYPT() 和 AES_DECRYPT() 在 MySQL 4.0.2 中被加入,可以被考虑为当前 MySQL 中可用的加解密函数中最密码安全的。
DES_ENCRYPT(string_to_encrypt [, (key_number | key_string) ] )
使用 Triple-DES 算法以给定的密钥对字符串加密。 注意,只有配置了 MySQL 对 SSL 的支持,这个函数才能正常工作。查看章节 4.3.9 使用安全地连接。 编码密钥以下列各项方法选择: 参数 含义
只有一个参数 des-key-file 中的第一个密钥被使用。
key number des-key-file 中给定的密钥 (0-9) 被使用。
string 给定的 key_string 将被用于加密 string_to_encrypt。
返回字符串是一个二进制字符串,并且第一个字符是 CHAR(128 | key_number)。 128 被加入是为了更加容易地识别一个加密密钥。如果你使用一个字符串密钥,key_number 将是 127。 当发生错误时,这个函数返回 NULL。 返回字符串的长度将为:new_length= org_length + (8-(org_length % 8))+1。 des-key-file 的格式如下:
key_number des_key_string
key_number des_key_string
每个 key_number 必须是一个在 0 到 9 范围之内的数字。文件中的行可以是任何次序的。des_key_string 是用于加密消息的字符串。在数字与密钥之间至少要有一个空格。如果你没在 DES_ENCRYPT() 指定任何密钥参数,那么文件中的第一个密钥将被缺省使用。 以 FLUSH DES_KEY_FILE 命令,你可以告诉 MySQL 从密钥文件中读取新的密钥值。这个操作需要你有 Reload_priv 权限。 有一套默认密钥的一个好处就是,它给应用程序一个检查存在的加密列值的方法,而不需要给最终用户解密这些值的权限。
mysql> SELECT customer_address FROM customer_table WHERE
crypted_credit_card = DES_ENCRYPT("credit_card_number");
DES_DECRYPT(string_to_decrypt [, key_string])
解密 DES_ENCRYPT() 加密后的字符串。 注意,只有配置了 MySQL 对 SSL 的支持,这个函数才能正常工作。查看章节 4.3.9 使用安全地连接。 如果 key_string 参数没有给出,DES_DECRYPT() 检查加密字符串的第一个字节,以确定用于加密原始字符串的 DES 密钥数字,然后从 des-key-file 读取密钥用于解密消息。为了能这样工作,该用户必须有 SUPER 权限。 如果将一个 key_string 参数传递给该函数,这个字符串将被作为解密消息的密钥。 如果 string_to_decrypt 看上去不像是一个加密字符串,MySQL 将返回给定的 string_to_decrypt。 当发生错误时,该函数返回 NULL。
LAST_INSERT_ID([expr])
返回被插入到一个 AUTO_INCREMENT 列中的最后一个自动产生的值。查看章节 8.1.3.130 mysql_insert_id()。
mysql> SELECT LAST_INSERT_ID();
-> 195
最后产生的 ID 是以每个连接为基础在服务器端被维护的。它不可能被其它的客户端连接改变。如果你以一个非特殊值(即一个非 NULL 和非 0 的值)更新其它的 AUTO_INCREMENT,它甚至也不会改变。 如果你在同一时间内以一个插入语句插入了许多记录行,LAST_INSERT_ID() 将返回第一个被插入行的值。这样做的原因是因为,这可能列容易地在其它服务器上再现同一条 INSERT 语句。 如果 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);
你也可以不调用 LAST_INSERT_ID() 产生序列,但是以这种方式使用这个函数的作用就是,ID 值是在服务器端叙谈最后的自动产生值被维护的(是多用户安全的)。你可以检索这的新的 ID 值,就好像读取 MySQL 中任何正常的 AUTO_INCREMENT 值一样。举例来说,LAST_INSERT_ID()(无任何参数) 将返回一个新的 ID。C API 函数 mysql_insert_id() 也可以用来得到这个值。 注意,由于 mysql_insert_id() 仅仅只能用于在 INSERT 和 UPDATE 语句的更新之后,所以在执行了其它的 SQL 语句(比如 SELECT 或 SET)之后,你不能够使用 C API 函数检索到 LAST_INSERT_ID(expr) 的值。
FORMAT(X,D)
将数字 X 格式化为一个 '#,###,###.##' 的形式,四舍五入到 D 位小数。如果 D 为 0,返回的结果将没有小数点和小数部分:
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'
VERSION()
以一个字符串形式返回 MySQL 服务器的版本:
mysql> SELECT VERSION();
-> '3.23.13-log'
注意,如果你的版本以 -log 结果,那就意味着日志是被设为可用的。
CONNECTION_ID()
返回当前连接的连接 ID(thread_id)。每个连接均有一个自己唯一的 id:
mysql> SELECT CONNECTION_ID();
-> 1
GET_LOCK(str,timeout)
尝试获得一个由字符串 str 给定名字的锁定与一个 timeout 秒的超时。如果锁定被获得成功,返回 1,如果尝试超时,返回 0,或者一个错误发生(比如内存溢出或线程被 mysqladmin kill 杀死),返回NULL。当你执行 RELEASE_LOCK()、执行一个新的 GET_LOCK(),或线程终止时,一个锁定被释放。这个函数可以被用于执行应用程序锁定或模拟记录锁定。它会阻塞其它的客户端用同样的名字的锁定请求;遵从一个给定锁定字符串名的客户端可以使用这个字符串来执行子协作建议的锁定:
mysql> SELECT GET_LOCK("lock1",10);
-> 1
mysql> SELECT IS_FREE_LOCK("lock2");
-> 1
mysql> SELECT GET_LOCK("lock2",10);
-> 1
mysql> SELECT RELEASE_LOCK("lock2");
-> 1
mysql> SELECT RELEASE_LOCK("lock1");
-> NULL
注意,第二个 RELEASE_LOCK() 调用返回 NULL 是因为 "lock1" 锁定被第二个 GET_LOCK() 调用自动地释放了。
RELEASE_LOCK(str)
释放由字符串 str 命名的通过 GET_LOCK() 获得的锁定。如果锁定被释放,返回 1;如果锁定并没有被当前线程锁定(在这种情况下,锁定不会被释放),返回 0;如果命名的锁定不存在,返回 NULL。如果锁定从来就没有通过调用一个 GET_LOCK() 获得,或已被释放了,那么该锁定将不存在。 DO 语句通常与 RELEASE_LOCK() 一起使用。查看章节 6.4.10 DO 句法。
IS_FREE_LOCK(str)
检查以 str 命名的锁定是否可以自由使用(也就是说,还未锁定)。如果锁定被释放了(没有一个人使用这个锁定),返回 1;如果这个锁定处于使用中,返回 0;如果发生一个错(例如错误的参数),返回 NULL。
BENCHMARK(count,expr)
BENCHMARK() 函数用于将表达式 expr 重复运行 count 次。它可以被用于计时 MySQL 处理表达式有多快。结果通常为 0。在 mysql 客户端有意使用它时,它将返回查询执行所需的时间:
mysql> SELECT BENCHMARK(1000000,ENCODE("hello","goodbye"));
+----------------------------------------------+
| BENCHMARK(1000000,ENCODE("hello","goodbye")) |
+----------------------------------------------+
| 0 |
+----------------------------------------------+
1 row in set (4.74 sec)
报告的时间是客户端经过的时间,不是服务器端的 CPU 时间。执行 BENCHMARK() 多次可能是明智的,并注意服务器的负载来解释结果。
INET_NTOA(expr)
给定一个数字的网络地址 (4 或 8 字节),以一个字符串的形式返回点组表示的地址:
mysql> SELECT INET_NTOA(3520061480);
-> "209.207.224.40"
INET_ATON(expr)
以字符串的形式给定一个点组表示的网络地址,返回一个地址的数字值表示的整数。地址可以是 4 或 8 个字节的地址:
mysql> SELECT INET_ATON("209.207.224.40");
-> 3520061480
产生的数字通常是以网络地址字节的顺序;例如,上面的数字是以 209*256^3 + 207*256^2 + 224*256 +40 被计算出来的。
MASTER_POS_WAIT(log_name, log_pos)
阻塞,只到从服务器到达(也就是说,已读取并应用了所有更新,一直到)主服务器上的日志中指定的位置。如果主服务器上的信息没有初始化,或如果参数错误,返回 NULL。如果从服务器没有运行,将阻塞并造作,只到它启动并到达或超过指定的位置。如果从服务器已超过指定的位置,立即返回。 如果 timeout (在 4.0.10 中新加入) 被指定,当等待 timeout 秒经过后,将放弃。timeout 必须大于 0;一个零或一个负值 timeout 意味着超时。返回值是到达日志指定位置所必须等待的日志事件的数量,或者在出错的情况下为 NULL,或者超过超时时间返回 -1。 这个命令有益于控制主从服务器的同步,但是最初是为了复制测试的方便而写的。
FOUND_ROWS()
返回最后一个 SELECT SQL_CALC_FOUND_ROWS ... 命令如果没有以 LIMIT 进行限制结果时将返回记录行数。
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 ...,MySQL 不得不计算所有的记录行到结果集中。然而,这与你不使用 LIMIT 相比是更快一点的,因为结果集不需要发送到客户端。 SQL_CALC_FOUND_ROWS 从 MySQL 4.0.0 开始可以被使用。
6.3.7 用于 GROUP BY 子句的函数
如果在一个没有包含 GROUP BY 子句的一个语句中使用聚合函数,它将等价于将所有的记录行分为一组。
COUNT(expr)
返回由一个 SELECT 语句检索出来的记录行中非 NULL 值的记录总数目:
mysql> SELECT student.student_name,COUNT(*)
-> FROM student,course
-> WHERE student.student_id=course.student_id
-> GROUP BY student_name;
COUNT(*) 在它返回检索出的记录行的数目上稍微有点不同,它不管记录行中是否包括 NULL 值。 如果 SELECT 语句从一个表中进行检索,没有检索其它的列,并且没有 WHERE 子句,那么 COUNT(*) 将被优化以便更快地返回值。示例如下:
mysql> SELECT COUNT(*) FROM student;
COUNT(DISTINCT expr,[expr...])
返回一个互不相同的非 NULL 的值的总数目:
mysql> SELECT COUNT(DISTINCT results) FROM student;
在 MySQL 中,通过给出一个表达式列表,可以得到不包含 NULL 的不同的表达式组合的数目。在 ANSI SQL 中,你可能不得不在 COUNT(DISTINCT ...) 中拼接所有的表达式。
AVG(expr)
返回 expr 的平均值:
mysql> SELECT student_name, AVG(test_score)
-> FROM student
-> GROUP BY student_name;
MIN(expr)
MAX(expr)
返回 expr 的最小或最大值。MIN() 和 MAX() 可以接受一个字符串参数;在这种情况下,它们将返回最小或最大的字符串传下。查看章节 5.4.3 MySQL 如何使用索引。
mysql> SELECT student_name, MIN(test_score), MAX(test_score)
-> FROM student
-> GROUP BY student_name;
在 MIN()、MAX() 和其它的合计函数中,MySQL 通常列的字符串值比较 ENUM 和 SET 列,而不是字符串在集合中相对应的位置。这将会被修正。
SUM(expr)
返回 expr 的总和。注意,如果返回集中没有从我任何记录行,它将返回 NULL !
GROUP_CONCAT(expr)
完整句法如下:
GROUP_CONCAT([DISTINCT] expr [,expr ...]
[ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC] [,col ...]]
[SEPARATOR str_val])
这个函数在 MySQL 4.1 中被加入。函数返回一个字符串结果,该结果由分组中的值连接组合而成:
mysql> SELECT student_name,
-> GROUP_CONCAT(test_score)
-> FROM student
-> GROUP BY student_name;
or
mysql> SELECT student_name,
-> GROUP_CONCAT(DISTINCT test_score
-> ORDER BY test_score DESC SEPARATOR " ")
-> FROM student
-> GROUP BY student_name;
在 MySQL 中,你可以得到表达式结合体的连结值。通过使用 DISTINCT 可以排除重复值。如果希望对结果中的值进行排序,可以使用 ORDER BY 子句。为了以倒序排序,可以在 ORDER BY 子句中用于排序的列名后添加一个 DESC (递减 descending) 关键词。缺省为升序;这也可以通过使用 ASC 关键词明确指定。 SEPARATOR 是一个字符串值,它被用于插入到结果值中。缺省为一个逗号 (",")。你可以通过指定 SEPARATOR "" 完全地移除这个分隔符。 在你的配置中,通过变量 group_concat_max_len 要以设置一个最大的长度。在运行时执行的句法如下:
SET [SESSION | GLOBAL] group_concat_max_len = unsigned_integer;
如果最大长度被设置,结果值被剪切到这个最大长度。 GROUP_CONCAT() 函数是一个增强的 Sybase SQL Anywhere 支持的基本 LIST() 函数。如果只有一个列,并且没有其它选项被指定,GROUP_CONCAT() 是向后兼容有极大限制的 LIST() 函数。 LIST() 有一个缺省的排序次序。
示例(译者注):
mysql> CREATE TABLE `ta` (
-> `id` smallint(5) unsigned NOT NULL default '0',
-> `name` char(60) NOT NULL default '',
-> KEY `id` (`id`)
-> ) TYPE=MyISAM;
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO `ta` VALUES("1", "a"),("1", "b"),
-> ("1", "c"),("1", "d"),("2", "a"),
-> ("2", "b"),("2", "c"),("3", "d");
Query OK, 8 rows affected (0.03 sec)
Records: 8 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM `ta`;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 1 | b |
| 1 | c |
| 1 | d |
| 2 | a |
| 2 | b |
| 2 | c |
| 3 | d |
+----+------+
8 rows in set (0.00 sec)
mysql> SELECT `id`,
-> GROUP_CONCAT(`name`)
-> FROM `ta`
-> GROUP BY `id`;
+----+----------------------+
| id | GROUP_CONCAT(`name`) |
+----+----------------------+
| 1 | a c b d |
| 2 | a c b |
| 3 | d |
+----+----------------------+
3 rows in set (0.03 sec)
# SEPARATOR 缺省是一个空格而不是一个逗号
mysql> SELECT `id`,
-> GROUP_CONCAT(DISTINCT `name`
-> ORDER BY `name` DESC SEPARATOR ",") AS Result
-> FROM `ta`
-> GROUP BY `id`;
+----+---------+
| id | Result |
+----+---------+
| 1 | d,c,b,a |
| 2 | c,b,a |
| 3 | d |
+----+---------+
3 rows in set (0.00 sec)
* 以上结果在 MySQL 4.1 中测试
示例结束(译者注)
VARIANCE(expr)
返回 expr 的标准方差(standard variance)。这是对 ANSI SQL 的扩展(只有在 4.1 或更新的版本中可用)。
STD(expr)
STDDEV(expr)
返回 expr 的标准偏差(standard deviation)。这是对 ANSI SQL 的扩展。这个函数的 STDDEV() 格式是为了 Oracle 兼容而提供的。
BIT_OR(expr)
返回 expr 中所有比特位的位 OR。计算以 64 位 (BIGINT) 精度执行。
BIT_AND(expr)
返回 expr 中所有比特位的位 AND。计算以 64 位 (BIGINT) 精度执行。
示例(译者注):
mysql> CREATE TABLE `ta` (
-> `id` smallint(5) unsigned NOT NULL default '0',
-> KEY `id` (`id`)
-> ) TYPE=MyISAM;
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO `ta` VALUES("1"),("2"),("3"),("4");
Query OK, 8 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> SELECT BIT_OR(id) from ta;
+------------+
| BIT_OR(id) |
+------------+
| 7 |
+------------+
1 row in set (0.00 sec)
# ..0001
# ..0010
# ..0011
# ..0100
# OR ..0000
# ---------
# ..0111
mysql> SELECT BIT_AND(id) from ta;
+-------------+
| BIT_AND(id) |
+-------------+
| 0 |
+-------------+
1 row in set (0.00 sec)
# ..0001
# ..0010
# ..0011
# ..0100
# AND ..1111
# ----------
# ..0000
* 以上结果在 MySQL 4.1 中测试
示例结束(译者注)
MySQL 扩展了 GROUP BY 的用法。在 SELECT 表达式中,你可以使用或计算没有出现在 GROUP BY 部分中的列。这代表 这个组的任何可能的值。你可以使用它避免在不必要的分类项目上进行排序和分组,这样会得到更好的性能。举例来说,在下面的例子中,你不必要以 customer.name 进行分组:
mysql> SELECT order.custid,customer.name,MAX(payments)
-> FROM order,customer
-> WHERE order.custid = customer.custid
-> GROUP BY order.custid;
在 ANSI SQL 中,必须将customer.name 添加到 GROUP BY 子句。而在 MySQL 中,如果没有以 ANSI 模式运行,该名是多余的。
如果你在 GROUP BY 部分省略的列在分组中不是唯一的,请不要使用这个特征!否则将得到不可预知的结果。
在某些情况下,可以使用 MIN() 和 MAX() 获得一个特定的列值,即使它不是唯一的。下面的示例取出包含了 sort 列中最小值的记录行中的 column 的值:
SUBSTR(MIN(CONCAT(RPAD(sort,6,' '),column)),7)
查看章节 3.5.4 拥有某个字段的组间最大值的记录行。
注意,如果你所使用的是 MySQL 3.22 (或更早的版本),或者你正试图遵从 ANSI SQL,你不能在 GROUP BY 或 ORDER BY 子句中使用表达式。你可以使用表达式的别名来应付这个限制:
mysql> SELECT id,FLOOR(value/100) AS val FROM tbl_name
-> GROUP BY id,val ORDER BY val;
在 MySQL 3.23 中,你可以这样做:
mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();
DATABASE()
返回当前数据库名:
mysql> SELECT DATABASE();
-> 'test'
如果没有当前数据库,DATABASE() 返回一个空字符串。
USER()
SYSTEM_USER()
SESSION_USER()
返回当前 MySQL 用户名:
mysql> SELECT USER();
-> 'davida@localhost'
在 MySQL 3.22.11 或更新的版本中,返回值包含用户名和客户机的主机名。你可以象下面所示的仅取出用户名部分(无论值是否包含一个主机名部分,它均能正常工作):
mysql> SELECT SUBSTRING_INDEX(USER(),"@",1);
-> 'davida'
CURRENT_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'
PASSWORD(str)
OLD_PASSWORD(str)
从纯文本口令 str 计算一个口令字符串。这个函数用于对存储到授权表 user 的Password 列中的 MySQL 口令进行加密。
mysql> SELECT PASSWORD('badpwd');
-> '7f84554057dd964b'
PASSWORD() 加密是不可逆的。 PASSWORD() 不以与 Unix 口令加密相同的方式进行口令加密。参见 ENCRYPT()。 注意, PASSWORD() 函数是用于在 MySQL 服务中验证系统的,你不应该 在你的应用程序中使用它。你可以使用 MD5() 或 SHA1() 代替使用它。同样查看 RFC-2195 可获得有关应用程序的口令处理与安全验证的更多信息。
ENCRYPT(str[,salt])
Encrypt使用 Unix crypt() 系统调用加密 str 。参数 salt 应该是一个有两个字符的字符串,(在 MySQL 3.22.16 中,salt 可以超过两个字符。):
mysql> SELECT ENCRYPT("hello");
-> 'VxuFAJXVARROc'
如果 crypt() 在你的系统上不可用,ENCRYPT() 总是返回 NULL。 ENCRYPT() 只保留 str 中前 8 个字符,而忽略其它所有的,至少在某些系统上是这样的。这取决于底层 crypt() 系统调用的行为。
ENCODE(str,pass_str)
使用 pass_str 做为密钥加密 str。使用 DECODE() 解密结果。结果是一个与 string 一样长的二进制字符。如果希望将它保存到一个列中,请使用 BLOB 列类型。
DECODE(crypt_str,pass_str)
使用 pass_str 作为密钥解密加密后的字符串 crypt_str。crypt_str 应该是一个由 ENCODE() 返回的字符串。
MD5(string)
计算一个字符串的 MD5 128 位校验和。值作为一个 32 位的十六进制数字返回,例如,被用于一个哈希(hash)键:
mysql> SELECT MD5("testing");
-> 'ae2b1fca515949e5d54fb22b8ed95575'
这是 "RSA 数据安全公司的 MD5 消息-摘要算法"。
SHA1(string)
SHA(string)
计算一个字符串的 SHA1 160 位校验和(在 RFC 3174 (Secure Hash Algorithm) 中被描述)。返回值是一个 40 位的十六进制数字,或在输入参数为 NULL 的情况下,返回值为 NULL。一个使用这个函数的可能就是用于一个哈希键。你也可以使用它作为存储密码时的密码安全函数。
mysql> SELECT SHA1("abc");
-> 'a9993e364706816aba3e25717850c26c9cd0d89d'
SHA1() 在MySQL 4.0.2 中被加入,并可被当做比 MD5() 加密更安全的等价物。SHA() 是 SHA1() 的同义词。
AES_ENCRYPT(string,key_string)
AES_DECRYPT(string,key_string)
这些函数允许使用官方的 AES(Advanced Encryption Standardadvanced 先进的密码技术标准) 算法加密/解密数据。加密时使用 128 位长的密钥,但是你可以通过修改源码将其扩展到 256 位。我们选择 128 位是因为它更快一点并且已足够安全了。 输入的参数可以是任意长度的。如果任何一个参数是 NULL,这个函数返回值也将是 NULL。 因为 AES 是一个块级的算法,加密不同长度的字符串时会对其进行填充,因而结果字符串的长度也可以通过 16*(trunc(string_length/16)+1) 计算出。 如果 AES_DECRYPT() 发现数据无效或错误的填料,它将返回 NULL。可是,如果输入的数据或密钥是无效的,函数仍然可能返回一个非 NULL 值 (可能是无用的信息)。 通过修改你的 SQL 语句,你可以使用 AES 函数以一个加密的形式存储数据:
INSERT INTO t VALUES (1,AES_ENCRYPT("text","password"));
尽量避免在一个连接上的每个查询中传递密钥,这样可以得到更高的安全性,上述方式可以通过连接时在服务器端存储密钥来完成:
SELECT @password:="my password";
INSERT INTO t VALUES (1,AES_ENCRYPT("text",@password));
AES_ENCRYPT() 和 AES_DECRYPT() 在 MySQL 4.0.2 中被加入,可以被考虑为当前 MySQL 中可用的加解密函数中最密码安全的。
DES_ENCRYPT(string_to_encrypt [, (key_number | key_string) ] )
使用 Triple-DES 算法以给定的密钥对字符串加密。 注意,只有配置了 MySQL 对 SSL 的支持,这个函数才能正常工作。查看章节 4.3.9 使用安全地连接。 编码密钥以下列各项方法选择: 参数 含义
只有一个参数 des-key-file 中的第一个密钥被使用。
key number des-key-file 中给定的密钥 (0-9) 被使用。
string 给定的 key_string 将被用于加密 string_to_encrypt。
返回字符串是一个二进制字符串,并且第一个字符是 CHAR(128 | key_number)。 128 被加入是为了更加容易地识别一个加密密钥。如果你使用一个字符串密钥,key_number 将是 127。 当发生错误时,这个函数返回 NULL。 返回字符串的长度将为:new_length= org_length + (8-(org_length % 8))+1。 des-key-file 的格式如下:
key_number des_key_string
key_number des_key_string
每个 key_number 必须是一个在 0 到 9 范围之内的数字。文件中的行可以是任何次序的。des_key_string 是用于加密消息的字符串。在数字与密钥之间至少要有一个空格。如果你没在 DES_ENCRYPT() 指定任何密钥参数,那么文件中的第一个密钥将被缺省使用。 以 FLUSH DES_KEY_FILE 命令,你可以告诉 MySQL 从密钥文件中读取新的密钥值。这个操作需要你有 Reload_priv 权限。 有一套默认密钥的一个好处就是,它给应用程序一个检查存在的加密列值的方法,而不需要给最终用户解密这些值的权限。
mysql> SELECT customer_address FROM customer_table WHERE
crypted_credit_card = DES_ENCRYPT("credit_card_number");
DES_DECRYPT(string_to_decrypt [, key_string])
解密 DES_ENCRYPT() 加密后的字符串。 注意,只有配置了 MySQL 对 SSL 的支持,这个函数才能正常工作。查看章节 4.3.9 使用安全地连接。 如果 key_string 参数没有给出,DES_DECRYPT() 检查加密字符串的第一个字节,以确定用于加密原始字符串的 DES 密钥数字,然后从 des-key-file 读取密钥用于解密消息。为了能这样工作,该用户必须有 SUPER 权限。 如果将一个 key_string 参数传递给该函数,这个字符串将被作为解密消息的密钥。 如果 string_to_decrypt 看上去不像是一个加密字符串,MySQL 将返回给定的 string_to_decrypt。 当发生错误时,该函数返回 NULL。
LAST_INSERT_ID([expr])
返回被插入到一个 AUTO_INCREMENT 列中的最后一个自动产生的值。查看章节 8.1.3.130 mysql_insert_id()。
mysql> SELECT LAST_INSERT_ID();
-> 195
最后产生的 ID 是以每个连接为基础在服务器端被维护的。它不可能被其它的客户端连接改变。如果你以一个非特殊值(即一个非 NULL 和非 0 的值)更新其它的 AUTO_INCREMENT,它甚至也不会改变。 如果你在同一时间内以一个插入语句插入了许多记录行,LAST_INSERT_ID() 将返回第一个被插入行的值。这样做的原因是因为,这可能列容易地在其它服务器上再现同一条 INSERT 语句。 如果 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);
你也可以不调用 LAST_INSERT_ID() 产生序列,但是以这种方式使用这个函数的作用就是,ID 值是在服务器端叙谈最后的自动产生值被维护的(是多用户安全的)。你可以检索这的新的 ID 值,就好像读取 MySQL 中任何正常的 AUTO_INCREMENT 值一样。举例来说,LAST_INSERT_ID()(无任何参数) 将返回一个新的 ID。C API 函数 mysql_insert_id() 也可以用来得到这个值。 注意,由于 mysql_insert_id() 仅仅只能用于在 INSERT 和 UPDATE 语句的更新之后,所以在执行了其它的 SQL 语句(比如 SELECT 或 SET)之后,你不能够使用 C API 函数检索到 LAST_INSERT_ID(expr) 的值。
FORMAT(X,D)
将数字 X 格式化为一个 '#,###,###.##' 的形式,四舍五入到 D 位小数。如果 D 为 0,返回的结果将没有小数点和小数部分:
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'
VERSION()
以一个字符串形式返回 MySQL 服务器的版本:
mysql> SELECT VERSION();
-> '3.23.13-log'
注意,如果你的版本以 -log 结果,那就意味着日志是被设为可用的。
CONNECTION_ID()
返回当前连接的连接 ID(thread_id)。每个连接均有一个自己唯一的 id:
mysql> SELECT CONNECTION_ID();
-> 1
GET_LOCK(str,timeout)
尝试获得一个由字符串 str 给定名字的锁定与一个 timeout 秒的超时。如果锁定被获得成功,返回 1,如果尝试超时,返回 0,或者一个错误发生(比如内存溢出或线程被 mysqladmin kill 杀死),返回NULL。当你执行 RELEASE_LOCK()、执行一个新的 GET_LOCK(),或线程终止时,一个锁定被释放。这个函数可以被用于执行应用程序锁定或模拟记录锁定。它会阻塞其它的客户端用同样的名字的锁定请求;遵从一个给定锁定字符串名的客户端可以使用这个字符串来执行子协作建议的锁定:
mysql> SELECT GET_LOCK("lock1",10);
-> 1
mysql> SELECT IS_FREE_LOCK("lock2");
-> 1
mysql> SELECT GET_LOCK("lock2",10);
-> 1
mysql> SELECT RELEASE_LOCK("lock2");
-> 1
mysql> SELECT RELEASE_LOCK("lock1");
-> NULL
注意,第二个 RELEASE_LOCK() 调用返回 NULL 是因为 "lock1" 锁定被第二个 GET_LOCK() 调用自动地释放了。
RELEASE_LOCK(str)
释放由字符串 str 命名的通过 GET_LOCK() 获得的锁定。如果锁定被释放,返回 1;如果锁定并没有被当前线程锁定(在这种情况下,锁定不会被释放),返回 0;如果命名的锁定不存在,返回 NULL。如果锁定从来就没有通过调用一个 GET_LOCK() 获得,或已被释放了,那么该锁定将不存在。 DO 语句通常与 RELEASE_LOCK() 一起使用。查看章节 6.4.10 DO 句法。
IS_FREE_LOCK(str)
检查以 str 命名的锁定是否可以自由使用(也就是说,还未锁定)。如果锁定被释放了(没有一个人使用这个锁定),返回 1;如果这个锁定处于使用中,返回 0;如果发生一个错(例如错误的参数),返回 NULL。
BENCHMARK(count,expr)
BENCHMARK() 函数用于将表达式 expr 重复运行 count 次。它可以被用于计时 MySQL 处理表达式有多快。结果通常为 0。在 mysql 客户端有意使用它时,它将返回查询执行所需的时间:
mysql> SELECT BENCHMARK(1000000,ENCODE("hello","goodbye"));
+----------------------------------------------+
| BENCHMARK(1000000,ENCODE("hello","goodbye")) |
+----------------------------------------------+
| 0 |
+----------------------------------------------+
1 row in set (4.74 sec)
报告的时间是客户端经过的时间,不是服务器端的 CPU 时间。执行 BENCHMARK() 多次可能是明智的,并注意服务器的负载来解释结果。
INET_NTOA(expr)
给定一个数字的网络地址 (4 或 8 字节),以一个字符串的形式返回点组表示的地址:
mysql> SELECT INET_NTOA(3520061480);
-> "209.207.224.40"
INET_ATON(expr)
以字符串的形式给定一个点组表示的网络地址,返回一个地址的数字值表示的整数。地址可以是 4 或 8 个字节的地址:
mysql> SELECT INET_ATON("209.207.224.40");
-> 3520061480
产生的数字通常是以网络地址字节的顺序;例如,上面的数字是以 209*256^3 + 207*256^2 + 224*256 +40 被计算出来的。
MASTER_POS_WAIT(log_name, log_pos)
阻塞,只到从服务器到达(也就是说,已读取并应用了所有更新,一直到)主服务器上的日志中指定的位置。如果主服务器上的信息没有初始化,或如果参数错误,返回 NULL。如果从服务器没有运行,将阻塞并造作,只到它启动并到达或超过指定的位置。如果从服务器已超过指定的位置,立即返回。 如果 timeout (在 4.0.10 中新加入) 被指定,当等待 timeout 秒经过后,将放弃。timeout 必须大于 0;一个零或一个负值 timeout 意味着超时。返回值是到达日志指定位置所必须等待的日志事件的数量,或者在出错的情况下为 NULL,或者超过超时时间返回 -1。 这个命令有益于控制主从服务器的同步,但是最初是为了复制测试的方便而写的。
FOUND_ROWS()
返回最后一个 SELECT SQL_CALC_FOUND_ROWS ... 命令如果没有以 LIMIT 进行限制结果时将返回记录行数。
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 ...,MySQL 不得不计算所有的记录行到结果集中。然而,这与你不使用 LIMIT 相比是更快一点的,因为结果集不需要发送到客户端。 SQL_CALC_FOUND_ROWS 从 MySQL 4.0.0 开始可以被使用。
6.3.7 用于 GROUP BY 子句的函数
如果在一个没有包含 GROUP BY 子句的一个语句中使用聚合函数,它将等价于将所有的记录行分为一组。
COUNT(expr)
返回由一个 SELECT 语句检索出来的记录行中非 NULL 值的记录总数目:
mysql> SELECT student.student_name,COUNT(*)
-> FROM student,course
-> WHERE student.student_id=course.student_id
-> GROUP BY student_name;
COUNT(*) 在它返回检索出的记录行的数目上稍微有点不同,它不管记录行中是否包括 NULL 值。 如果 SELECT 语句从一个表中进行检索,没有检索其它的列,并且没有 WHERE 子句,那么 COUNT(*) 将被优化以便更快地返回值。示例如下:
mysql> SELECT COUNT(*) FROM student;
COUNT(DISTINCT expr,[expr...])
返回一个互不相同的非 NULL 的值的总数目:
mysql> SELECT COUNT(DISTINCT results) FROM student;
在 MySQL 中,通过给出一个表达式列表,可以得到不包含 NULL 的不同的表达式组合的数目。在 ANSI SQL 中,你可能不得不在 COUNT(DISTINCT ...) 中拼接所有的表达式。
AVG(expr)
返回 expr 的平均值:
mysql> SELECT student_name, AVG(test_score)
-> FROM student
-> GROUP BY student_name;
MIN(expr)
MAX(expr)
返回 expr 的最小或最大值。MIN() 和 MAX() 可以接受一个字符串参数;在这种情况下,它们将返回最小或最大的字符串传下。查看章节 5.4.3 MySQL 如何使用索引。
mysql> SELECT student_name, MIN(test_score), MAX(test_score)
-> FROM student
-> GROUP BY student_name;
在 MIN()、MAX() 和其它的合计函数中,MySQL 通常列的字符串值比较 ENUM 和 SET 列,而不是字符串在集合中相对应的位置。这将会被修正。
SUM(expr)
返回 expr 的总和。注意,如果返回集中没有从我任何记录行,它将返回 NULL !
GROUP_CONCAT(expr)
完整句法如下:
GROUP_CONCAT([DISTINCT] expr [,expr ...]
[ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC] [,col ...]]
[SEPARATOR str_val])
这个函数在 MySQL 4.1 中被加入。函数返回一个字符串结果,该结果由分组中的值连接组合而成:
mysql> SELECT student_name,
-> GROUP_CONCAT(test_score)
-> FROM student
-> GROUP BY student_name;
or
mysql> SELECT student_name,
-> GROUP_CONCAT(DISTINCT test_score
-> ORDER BY test_score DESC SEPARATOR " ")
-> FROM student
-> GROUP BY student_name;
在 MySQL 中,你可以得到表达式结合体的连结值。通过使用 DISTINCT 可以排除重复值。如果希望对结果中的值进行排序,可以使用 ORDER BY 子句。为了以倒序排序,可以在 ORDER BY 子句中用于排序的列名后添加一个 DESC (递减 descending) 关键词。缺省为升序;这也可以通过使用 ASC 关键词明确指定。 SEPARATOR 是一个字符串值,它被用于插入到结果值中。缺省为一个逗号 (",")。你可以通过指定 SEPARATOR "" 完全地移除这个分隔符。 在你的配置中,通过变量 group_concat_max_len 要以设置一个最大的长度。在运行时执行的句法如下:
SET [SESSION | GLOBAL] group_concat_max_len = unsigned_integer;
如果最大长度被设置,结果值被剪切到这个最大长度。 GROUP_CONCAT() 函数是一个增强的 Sybase SQL Anywhere 支持的基本 LIST() 函数。如果只有一个列,并且没有其它选项被指定,GROUP_CONCAT() 是向后兼容有极大限制的 LIST() 函数。 LIST() 有一个缺省的排序次序。
示例(译者注):
mysql> CREATE TABLE `ta` (
-> `id` smallint(5) unsigned NOT NULL default '0',
-> `name` char(60) NOT NULL default '',
-> KEY `id` (`id`)
-> ) TYPE=MyISAM;
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO `ta` VALUES("1", "a"),("1", "b"),
-> ("1", "c"),("1", "d"),("2", "a"),
-> ("2", "b"),("2", "c"),("3", "d");
Query OK, 8 rows affected (0.03 sec)
Records: 8 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM `ta`;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 1 | b |
| 1 | c |
| 1 | d |
| 2 | a |
| 2 | b |
| 2 | c |
| 3 | d |
+----+------+
8 rows in set (0.00 sec)
mysql> SELECT `id`,
-> GROUP_CONCAT(`name`)
-> FROM `ta`
-> GROUP BY `id`;
+----+----------------------+
| id | GROUP_CONCAT(`name`) |
+----+----------------------+
| 1 | a c b d |
| 2 | a c b |
| 3 | d |
+----+----------------------+
3 rows in set (0.03 sec)
# SEPARATOR 缺省是一个空格而不是一个逗号
mysql> SELECT `id`,
-> GROUP_CONCAT(DISTINCT `name`
-> ORDER BY `name` DESC SEPARATOR ",") AS Result
-> FROM `ta`
-> GROUP BY `id`;
+----+---------+
| id | Result |
+----+---------+
| 1 | d,c,b,a |
| 2 | c,b,a |
| 3 | d |
+----+---------+
3 rows in set (0.00 sec)
* 以上结果在 MySQL 4.1 中测试
示例结束(译者注)
VARIANCE(expr)
返回 expr 的标准方差(standard variance)。这是对 ANSI SQL 的扩展(只有在 4.1 或更新的版本中可用)。
STD(expr)
STDDEV(expr)
返回 expr 的标准偏差(standard deviation)。这是对 ANSI SQL 的扩展。这个函数的 STDDEV() 格式是为了 Oracle 兼容而提供的。
BIT_OR(expr)
返回 expr 中所有比特位的位 OR。计算以 64 位 (BIGINT) 精度执行。
BIT_AND(expr)
返回 expr 中所有比特位的位 AND。计算以 64 位 (BIGINT) 精度执行。
示例(译者注):
mysql> CREATE TABLE `ta` (
-> `id` smallint(5) unsigned NOT NULL default '0',
-> KEY `id` (`id`)
-> ) TYPE=MyISAM;
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO `ta` VALUES("1"),("2"),("3"),("4");
Query OK, 8 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> SELECT BIT_OR(id) from ta;
+------------+
| BIT_OR(id) |
+------------+
| 7 |
+------------+
1 row in set (0.00 sec)
# ..0001
# ..0010
# ..0011
# ..0100
# OR ..0000
# ---------
# ..0111
mysql> SELECT BIT_AND(id) from ta;
+-------------+
| BIT_AND(id) |
+-------------+
| 0 |
+-------------+
1 row in set (0.00 sec)
# ..0001
# ..0010
# ..0011
# ..0100
# AND ..1111
# ----------
# ..0000
* 以上结果在 MySQL 4.1 中测试
示例结束(译者注)
MySQL 扩展了 GROUP BY 的用法。在 SELECT 表达式中,你可以使用或计算没有出现在 GROUP BY 部分中的列。这代表 这个组的任何可能的值。你可以使用它避免在不必要的分类项目上进行排序和分组,这样会得到更好的性能。举例来说,在下面的例子中,你不必要以 customer.name 进行分组:
mysql> SELECT order.custid,customer.name,MAX(payments)
-> FROM order,customer
-> WHERE order.custid = customer.custid
-> GROUP BY order.custid;
在 ANSI SQL 中,必须将customer.name 添加到 GROUP BY 子句。而在 MySQL 中,如果没有以 ANSI 模式运行,该名是多余的。
如果你在 GROUP BY 部分省略的列在分组中不是唯一的,请不要使用这个特征!否则将得到不可预知的结果。
在某些情况下,可以使用 MIN() 和 MAX() 获得一个特定的列值,即使它不是唯一的。下面的示例取出包含了 sort 列中最小值的记录行中的 column 的值:
SUBSTR(MIN(CONCAT(RPAD(sort,6,' '),column)),7)
查看章节 3.5.4 拥有某个字段的组间最大值的记录行。
注意,如果你所使用的是 MySQL 3.22 (或更早的版本),或者你正试图遵从 ANSI SQL,你不能在 GROUP BY 或 ORDER BY 子句中使用表达式。你可以使用表达式的别名来应付这个限制:
mysql> SELECT id,FLOOR(value/100) AS val FROM tbl_name
-> GROUP BY id,val ORDER BY val;
在 MySQL 3.23 中,你可以这样做:
mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();