6.3.4 日期和时间函数
对于每个类型的值范围以及日期和时间值有效指定格式,请查看章节 6.2.2 Date 和 Time 类型。
这里是一个使用日期函数的例子。下面的查询选择所有 date_col 值在最后 30 天内的记录。
mysql> SELECT something FROM tbl_name WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30; DAYOFWEEK(date) 返回 date 的星期索引(1 = Sunday, 2 = Monday, ... 7 = Saturday)。索引值符合 ODBC 的标准。
mysql> SELECT DAYOFWEEK('1998-02-03'); -> 3 WEEKDAY(date) 返回 date 的星期索引(0 = Monday, 1 = Tuesday, ... 6 = Sunday):
mysql> SELECT WEEKDAY('1998-02-03 22:23:00'); -> 1 mysql> SELECT WEEKDAY('1997-11-05'); -> 2 DAYOFMONTH(date) 返回 date 是一月中的第几天,范围为 1 到 31:
mysql> SELECT DAYOFMONTH('1998-02-03'); -> 3 DAYOFYEAR(date) 返回 date 是一年中的第几天,范围为 1 到 366:
mysql> SELECT DAYOFYEAR('1998-02-03'); -> 34 MONTH(date) 返回 date 中的月份,范围为 1 到 12:
mysql> SELECT MONTH('1998-02-03'); -> 2 DAYNAME(date) 返回 date 的星期名:
mysql> SELECT DAYNAME("1998-02-05"); -> 'Thursday' MONTHNAME(date) 返回 date 的月份名:
mysql> SELECT MONTHNAME("1998-02-05"); -> 'February' QUARTER(date) 返回 date 在一年中的季度,范围为 1 到 4:
mysql> SELECT QUARTER('98-04-01'); -> 2 WEEK(date) WEEK(date,first) 对于星期日是一周中的第一天的场合,如果函数只有一个参数调用,返回 date 为一年的第几周,返回值范围为 0 到 53 (是的,可能有第 53 周的开始)。两个参数形式的 WEEK() 允许你指定一周是否以星期日或星期一开始,以及返回值为 0-53 还是 1-52。 这里的一个表显示第二个参数是如何工作的: 值 含义 0 一周以星期日开始,返回值范围为 0-53 1 一周以星期一开始,返回值范围为 0-53 2 一周以星期日开始,返回值范围为 1-53 3 一周以星期一开始,返回值范围为 1-53 (ISO 8601)
mysql> SELECT WEEK('1998-02-20'); -> 7 mysql> SELECT WEEK('1998-02-20',0); -> 7 mysql> SELECT WEEK('1998-02-20',1); -> 8 mysql> SELECT WEEK('1998-12-31',1); -> 53 注意,在版本 4.0 中,WEEK(#,0) 被更改为匹配 USA 历法。 注意,如果一周是上一年的最后一周,当你没有使用 2 或 3 做为可选参数时,MySQL 将返回 0:
mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0); -> 2000, 0 mysql> SELECT WEEK('2000-01-01',2); -> 52 你可能会争辩说,当给定的日期值实际上是 1999 年的第 52 周的一部分时,MySQL 对 WEEK() 函数应该返回 52。我们决定返回 0 ,是因为我们希望该函数返回“在指定年份中是第几周”。 当与其它的提取日期值中的月日值的函数结合使用时,这使得 WEEK() 函数的用法可靠。 如果你更希望能得到恰当的年-周值,那么你应该使用参数 2 或 3 做为可选参数,或者使用函数 YEARWEEK() :
mysql> SELECT YEARWEEK('2000-01-01'); -> 199952 mysql> SELECT MID(YEARWEEK('2000-01-01'),5,2); -> 52 YEAR(date) 返回 date 的年份,范围为 1000 到 9999:
mysql> SELECT YEAR('98-02-03'); -> 1998 YEARWEEK(date) YEARWEEK(date,first) 返回一个日期值是的哪一年的哪一周。第二个参数的形式与作用完全与 WEEK() 的第二个参数一致。注意,对于给定的日期参数是一年的第一周或最后一周的,返回的年份值可能与日期参数给出的年份不一致:
mysql> SELECT YEARWEEK('1987-01-01'); -> 198653 注意,对于可选参数 0 或 1,周值的返回值不同于 WEEK() 函数所返回值(0), WEEK() 根据给定的年语境返回周值。 HOUR(time) 返回 time 的小时值,范围为 0 到 23:
mysql> SELECT HOUR('10:05:03'); -> 10 MINUTE(time) 返回 time 的分钟值,范围为 0 到 59:
mysql> SELECT MINUTE('98-02-03 10:05:03'); -> 5 SECOND(time) 返回 time 的秒值,范围为 0 到 59:
mysql> SELECT SECOND('10:05:03'); -> 3 PERIOD_ADD(P,N) 增加 N 个月到时期 P(格式为 YYMM 或 YYYYMM)中。以 YYYYMM 格式返回值。 注意,期间参数 P 不是 一个日期值:
mysql> SELECT PERIOD_ADD(9801,2); -> 199803 PERIOD_DIFF(P1,P2) 返回时期 P1 和 P2 之间的月数。P1 和 P2 应该以 YYMM 或 YYYYMM 指定。 注意,时期参数 P1 和 P2 不是 日期值:
mysql> SELECT PERIOD_DIFF(9802,199703); -> 11 DATE_ADD(date,INTERVAL expr type) DATE_SUB(date,INTERVAL expr type) ADDDATE(date,INTERVAL expr type) SUBDATE(date,INTERVAL expr type) 这些函数执行日期的算术运算。ADDDATE() 和 SUBDATE() 分别是 DATE_ADD() 和 DATE_SUB() 的同义词。 在 MySQL 3.23 中,如果表达式的右边是一个日期值或一个日期时间型字段,你可以使用 + 和 - 代替 DATE_ADD() 和 DATE_SUB()(示例如下)。 参数 date 是一个 DATETIME 或 DATE 值,指定一个日期的开始。expr 是一个表达式,指定从开始日期上增加还是减去间隔值。expr 是一个字符串;它可以以一个 “-” 领头表示一个负的间隔值。type 是一个关键词,它标志着表达式以何格式被解释。 下表显示 type 和 expr 参数是如何关联的: type 值 expr 期望的格式 SECOND SECONDS MINUTE MINUTES HOUR HOURS DAY DAYS MONTH MONTHS YEAR YEARS MINUTE_SECOND "MINUTES:SECONDS" HOUR_MINUTE "HOURS:MINUTES" DAY_HOUR "DAYS HOURS" YEAR_MONTH "YEARS-MONTHS" HOUR_SECOND "HOURS:MINUTES:SECONDS" DAY_MINUTE "DAYS HOURS:MINUTES" DAY_SECOND "DAYS HOURS:MINUTES:SECONDS" 在 expr 的格式中,MySQL 允许任何字符作为定界符。表中所显示的是建议的定界字符。如果 date 参数是一个 DATE 值,并且计算的间隔仅仅有 YEAR、MONTH 和 DAY 部分(没有时间部分),那么返回值也是一个 DATE 值。否则返回值是一个 DATETIME 值:
mysql> SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND; -> 1998-01-01 00:00:00 mysql> SELECT INTERVAL 1 DAY + "1997-12-31"; -> 1998-01-01 mysql> SELECT "1998-01-01" - INTERVAL 1 SECOND; -> 1997-12-31 23:59:59 mysql> SELECT DATE_ADD("1997-12-31 23:59:59", -> INTERVAL 1 SECOND); -> 1998-01-01 00:00:00 mysql> SELECT DATE_ADD("1997-12-31 23:59:59", -> INTERVAL 1 DAY); -> 1998-01-01 23:59:59 mysql> SELECT DATE_ADD("1997-12-31 23:59:59", -> INTERVAL "1:1" MINUTE_SECOND); -> 1998-01-01 00:01:00 mysql> SELECT DATE_SUB("1998-01-01 00:00:00", -> INTERVAL "1 1:1:1" DAY_SECOND); -> 1997-12-30 22:58:59 mysql> SELECT DATE_ADD("1998-01-01 00:00:00", -> INTERVAL "-1 10" DAY_HOUR); -> 1997-12-30 14:00:00 mysql> SELECT DATE_SUB("1998-01-02", INTERVAL 31 DAY); -> 1997-12-02 如果你指定了一个太短的间隔值(没有包括 type 关键词所期望的所有间隔部分),MySQL 假设你遗漏了间隔值的最左边部分。例如,如果指定一个 type 为 DAY_SECOND,那么 expr 值被期望包含天、小时、分钟和秒部分。如果你象 "1:10" 样指定一个值,MySQL 假设天和小时部分被遗漏了,指定的值代表分钟和秒。换句话说,"1:10" DAY_SECOND 被解释为等价于 "1:10" MINUTE_SECOND。这类似于 MySQL 解释 TIME 值为经过的时间而不是一天的时刻。 注意,如果依着包含一个时间部分的间隔增加或减少一个日期值,该日期值将被自动地转换到一个日期时间值:
mysql> SELECT DATE_ADD("1999-01-01", INTERVAL 1 DAY); -> 1999-01-02 mysql> SELECT DATE_ADD("1999-01-01", INTERVAL 1 HOUR); -> 1999-01-01 01:00:00 如果你使用了确定不正确的日期,返回结果将是 NULL。如果你增加 MONTH、YEAR_MONTH 或 YEAR,并且结果日期的天比新月份的最大天数还大,那么它将被调整到新月份的最大天数:
mysql> SELECT DATE_ADD('1998-01-30', INTERVAL 1 MONTH); -> 1998-02-28 注意,上面的例子中,单词 INTERVAL 和关键词 type 是不区分字母大小写的。
EXTRACT(type FROM date) EXTRACT() 函数使用与 DATE_ADD() 或 DATE_SUB() 一致的间隔类型,但是它用于指定从日期中提取的部分,而不是进行日期算术运算。mysql> SELECT EXTRACT(YEAR FROM "1999-07-02"); -> 1999 mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03"); -> 199907 mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03"); -> 20102 TO_DAYS(date) 给出一个日期 date,返回一个天数(从 0 年开始的天数):
mysql> SELECT TO_DAYS(950501); -> 728779 mysql> SELECT TO_DAYS('1997-10-07'); -> 729669 TO_DAYS() 无意于使用先于格里高里历法(即现行的阳历)(1582)出现的值,因为它不考虑当历法改变时所遗失的天数。
FROM_DAYS(N) 给出一个天数 N,返回一个 DATE 值:mysql> SELECT FROM_DAYS(729669); -> '1997-10-07' FROM_DAYS() 无意于使用先于格里高里历法(1582)出现的值,因为它不考虑当历法改变时所遗失的天数。
DATE_FORMAT(date,format) 依照 format 字符串格式化 date 值。下面的修饰符可被用于 format 字符串中: 修饰符 含义 %M 月的名字 (January..December) %W 星期的名字 (Sunday..Saturday) %D 有英文后缀的某月的第几天 (0th, 1st, 2nd, 3rd, etc.) %Y 年份,数字的,4 位 %y 年份,数字的,2 位 %X 周值的年份,星期日是一个星期的第一天,数字的,4 位,与 '%V' 一同使用 %x 周值的年份,星期一是一个星期的第一天,数字的,4 位,与 '%v' 一同使用 %a 缩写的星期名 (Sun..Sat) %d 月份中的天数,数字的 (00..31) %e 月份中的天数,数字的 (0..31) %m 月,数字的 (00..12) %c 月,数字的 (0..12) %b 缩写的月份名 (Jan..Dec) %j 一年中的天数 (001..366) %H 小时 (00..23) %k 小时 (0..23) %h 小时 (01..12) %I 小时 (01..12) %l 小时 (1..12) %i 分钟,数字的 (00..59) %r 时间,12 小时 (hh:mm:ss [AP]M) %T 时间,24 小时 (hh:mm:ss) %S 秒 (00..59) %s 秒 (00..59) %p AM 或 PM %w 一周中的天数 (0=Sunday..6=Saturday) %U 星期 (00..53),星期日是一个星期的第一天 %u 星期 (00..53),星期一是一个星期的第一天 %V 星期 (01..53),星期日是一个星期的第一天。与 '%X' 一起使用 %v 星期 (01..53),星期一是一个星期的第一天。与 '%x' 一起使用 %% 一个字母 “%” 所有其它的字符不经过解释,直接复制到结果中:mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y'); -> 'Saturday October 1997' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s'); -> '22:23:00' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%D %y %a %d %m %b %j'); -> '4th 97 Sat 04 10 Oct 277' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H %k %I %r %T %S %w'); -> '22 22 10 10:23:00 PM 22:23:00 00 6' mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V'); -> '1998 52' 在 MySQL 3.23 中,在格式修饰符前需要字符 `%'。在更早的 MySQL 版本中,`%' 是可选的。 月份与天修饰符的范围从零开始的原因是,在 MySQL 3.23 中,它允许存储不完善的日期值(例如 '2004-00-00')。
TIME_FORMAT(time,format) 它的使用方法与上面的 DATE_FORMAT() 函数相似,但是 format 字符串只包含处理小时、分和秒的那些格式修饰符。使用其它的修饰符会产生一个 NULL 值或 0。 CURDATE() CURRENT_DATE 以 'YYYY-MM-DD' 或 YYYYMMDD 格式返回当前的日期值,返回的格式取决于该函数是用于字符串还是数字语境中:mysql> SELECT CURDATE(); -> '1997-12-15' mysql> SELECT CURDATE() + 0; -> 19971215 CURTIME() CURRENT_TIME 以 'HH:MM:SS' 或 HHMMSS 格式返回当前的时间值,返回的格式取决于该函数是用于字符串还是数字语境中:
mysql> SELECT CURTIME(); -> '23:50:26' mysql> SELECT CURTIME() + 0; -> 235026 NOW() SYSDATE() CURRENT_TIMESTAMP 以 'YYYY-MM-DD HH:MM:SS' 或 YYYYMMDDHHMMSS 格式返回当前的日期时间值,返回的格式取决于该函数是用于字符串还是数字语境中:
mysql> SELECT NOW(); -> '1997-12-15 23:50:26' mysql> SELECT NOW() + 0; -> 19971215235026 注意,函数 NOW() 在每个查询中只计算一次,也就是在查询开始执行时。这就是说,如果在一个单独的查询中多次引用了 NOW(),它只会给出值都是一个相同的时间。
UNIX_TIMESTAMP() UNIX_TIMESTAMP(date) 如果调用时没有参数,以无符号的整数形式返回一个 Unix 时间戳(从 '1970-01-01 00:00:00' GMT 开始的秒数)。如果以一个参数 date 调用 UNIX_TIMESTAMP(),它将返回该参数值从 '1970-01-01 00:00:00' GMT 开始经过的秒数值。date 可以是一个 DATE 字符串,一个 DATETIME 字符串,一个 TIMESTAMP,或者以一个 YYMMDD 或 YYYYMMDD 显示的本地时间:mysql> SELECT UNIX_TIMESTAMP(); -> 882226357 mysql> SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00'); -> 875996580 当 UNIX_TIMESTAMP 被用于一个 TIMESTAMP 列时,函数直接返回一个内部的时间戳值,而不进行一个隐含地 “string-to-unix-timestamp” 转换。 如果你传递一个超出范围的日期参数给 UNIX_TIMESTAMP() ,它将返回 0,但是请注意,MySQL 对其仅仅进行基本的检验(年范围 1970-2037,月份 01-12,日期 01-31)。 如果你希望减去 UNIX_TIMESTAMP() 列,你应该需要将结果强制转换为一有符号整数。查看章节 6.3.5 Cast 函数。
FROM_UNIXTIME(unix_timestamp [,format]) 以 'YYYY-MM-DD HH:MM:SS' 或 YYYYMMDDHHMMSS 格式返回一个 unix_timestamp 参数值,返回值的形式取决于该函数使用于字符串还是数字语境。 如果 format 给出,返回值依 format 字符串被格式。format 可以包含与 DATE_FORMAT() 函数同样的修饰符。mysql> SELECT FROM_UNIXTIME(875996580); -> '1997-10-04 22:23:00' mysql> SELECT FROM_UNIXTIME(875996580) + 0; -> 19971004222300 mysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(), '%Y %D %M %h:%i:%s %x'); -> '1997 23rd December 03:43:30 1997' SEC_TO_TIME(seconds) 以 'HH:MM:SS' 或 HHMMSS 格式返回参数 seconds 被转换到时分秒后的值,返回值的形式取决于该函数使用于字符串还是数字语境:
mysql> SELECT SEC_TO_TIME(2378); -> '00:39:38' mysql> SELECT SEC_TO_TIME(2378) + 0; -> 3938 TIME_TO_SEC(time) 将参数 time 转换为秒数后返回:
mysql> SELECT TIME_TO_SEC('22:23:00'); -> 80580 mysql> SELECT TIME_TO_SEC('00:39:38'); -> 2378 6.3.5 Cast 函数
CAST 函数的句法如下:
CAST(expression AS type) 或 CONVERT(expression,type)
type 可以是下面的任一个: BINARY CHAR (4.0.6 中新加入) DATE DATETIME SIGNED {INTEGER} TIME UNSIGNED {INTEGER}
CAST() 是 ANSI SQL99 的句法,CONVERT() 是 ODBC 的句法。
CAST 函数主要用于以特殊的 CREATE ... SELECT 形式建立一个列时:
CREATE TABLE new_table SELECT CAST('2000-01-01' AS DATE);
CAST(string AS BINARY 与 BINARY string 是相同的。 CAST(expr AS CHAR 表示一个使用当前默认字符集的字符串。
为了将一个字符串转换成一个数字值,通常不需要做任何事情;只要将字符串值当做一个数字即可:
mysql> SELECT 1+'1'; -> 2
如果在一个字符串语境中使用一个数字,该数字会被自动地转换为一个 BINARY 字符串。
mysql> SELECT CONCAT("hello you ",2); -> "hello you 2"
MySQL 支持两方是有符号的和无符号的 64 位值的算术运算。如果你使用一个数字操作符(比如 +),并且其中的一个操作数是 unsigned integer,那么结果将是无符号的。为了不考虑这些问题,你可以使用 SIGNED 和 UNSIGNED CAST 操作符来,它会分别地强制运算到一个有符号的或一个无符号的 64 位整数。
mysql> SELECT CAST(1-2 AS UNSIGNED) -> 18446744073709551615 mysql> SELECT CAST(CAST(1-2 AS UNSIGNED) AS SIGNED); -> -1
注意,如果任一个操作数是一个浮点值(在这种语境下,DECIMAL() 被当作是一个浮点数值),结果也将是一个浮点数值,并且结果不受上面的规则影响。
mysql> SELECT CAST(1 AS UNSIGNED) -2.0 -> -1.0
如果在一个算术运算中使用一个字符串,它将被转换为一个浮点数字。
函数 CAST() 和 CONVERT() 在 MySQL 4.0.2 中被加入。
为了完全支持 BIGINT,在 MySQL 4.0 中对无符号值的处理发生了改变。如果希望你的代码在 MySQL 4.0 和 3.23 中均能够正常运行(在这种情况下,你或许不能够使用 CAST 函数),当进行两个无符号整数列的减法时,你可以使用下面的技巧得到一个有符号的结果:
SELECT (unsigned_column_1+0.0)-(unsigned_column_2+0.0);
这个做法是在进行减法之前,先将无符号列转换为一个浮点数。
如果你将旧的 MySQL 应用程序移植到 MySQL 4.0 时,在 UNSIGNED 列上出现了问题,你可以在启动 mysqld 时使用 --sql-mode=NO_UNSIGNED_SUBTRACTION 选项。注意,只要你使用了这个选项,你将不能直接地使用 UNSIGNED BIGINT 列类型。
6.3.6 其它函数 6.3.6.1 位函数
MySQL 使用 BIGINT (64 位) 算法进行位运算,因而这些操作符有一个 64 位的最大范围。
| 位或mysql> SELECT 29 | 15; -> 31 返回值是一个 64 位的无符号整数。
& 位与mysql> SELECT 29 & 15; -> 13 返回值是一个 64 位的无符号整数。
^ 位异或mysql> SELECT 1 ^ 1; -> 0 mysql> SELECT 1 ^ 0; -> 1 mysql> SELECT 11 ^ 3; -> 8 返回值是一个 64 位的无符号整数。 XOR 在 MySQL 4.0.2 中被加入。
<< 左移一个长长的数字(BIGINT):mysql> SELECT 1 << 2; -> 4 返回值是一个 64 位的无符号整数。
>> 右移一个长长的数字(BIGINT):mysql> SELECT 4 >> 2; -> 1 返回值是一个 64 位的无符号整数。
~ 置反所有位:mysql> SELECT 5 & ~1; -> 4 返回值是一个 64 位的无符号整数。
BIT_COUNT(N) 返回在参数 N 中嵌入的比特位数量:mysql> SELECT BIT_COUNT(29); -> 4 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();
本文地址:http://com.8s8s.com/it/it21255.htm