学习了日期时间函数,接着学习条件、系统、加密和其它函数。
3,条件判断函数
条件判断函数也称为控制流程函数,根据满足的条件的不同,执行相应的流程。MySQL中进行条件判断的函数有IF、IFNULL和 CASE。
函数 | 说明 |
IF(expr,v1,v2) | 如果表达式expr是TRUE(expr > 0 and expr NULL),则IF()的返回值为v1;否则返回值为v2 |
IFNULL(v1,v2) | 假如vI不为NULL,则IFNULL()的返回值为vl;否则其返回值为v2 |
CASE | CASE expr WHEN v1 THEN rl [WHEN v2 THEN r2] [ELSE m] END |
1,IF(expr,v1,v2)函数
IF(expr, vl, v2),如果表达式expr是TRUE(expr > 0 and expr NULL),则IF()的返回值为v1;否则返回值为v2。IF()的返回值为数字值或字符串值,具体情况视其所在语境而定。
【例85】使用IF()函数进行条件判断,输入语句如下:
SELECT IF(1>2, 2, 3),
IF(1<2, 'yes' , 'no'),
IF(STRCMP('test', 'test1'), 'no', ' yes');
1>2的结果为FALSE IF(1>2, 2, 3)返回第2个表达式的值1<2的结果为TRUE
IF(1<2, 'yes', 'no')返回第一个表达式的值﹔“test ”小于“testl ”,结果为true
IF(STRCMP('test', 'test1'), 'no', 'yes')返回第一个表达式的值。
提示:如果v1或v2中只有一个明确是NULL。则IF()函数的结果类型为非NULL表达式的结果类型。
2,IFNULL(v1,v2)函数
IFNULL(v1,v2)假如vI不为NULL,则IFNULL()的返回值为vl;否则其返回值为v2。
IFNULL()的返回值是数字或是字符串,具体情况取决于其所在的语境。
【例86】使用IFNULL0函数进行条件判断,输入语句如下:
SELECT IFNULL(1,21), IFNULL(NULL,10), IFNULL(1/0, 'wrong');
IFNULL(1,2)虽然第二个值也不为空,但返回结果依然是第一一个值; IFNULL(NULL,10)第
一个值为空,因此返回10;“1/0” 的结果为空,因此IFNULL(1/0, 'wrong')返回字符串“wrong” 。
3,CASE 函数.
CASE expr WHEN v1 THEN rl [WHEN v2 THEN r2] [ELSE m] END
该函数表示,如果expr值等于某个vn,则返回对应位置THEN后面的结果。如果与所有值都不相等,则返回ELSE后面的m。
【例87】使用CASE value WHEN语句执行分支操作,输入语句如下:
SELECT CASE 2 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'more!' END;
CASE后面的值为2与第二条分支语句WHEN后面的值相等因此返回结果为“two” 。
CASE WHEN v1 THEN rl [WHEN v2 THEN r2] [ELSE m] END
该函数表示,某个vn值为TRUE时,返回对应位置THEN后面的结果,如果所有值都不
为TRUE,则返回ELSE后的m。
【例88】使用CASE WHEN语句执行分支操作,输入语句如下:
SELECT CASE WHEN 1<0 THEN 'true' ELSE 'false' END;
1<0结果为FALSE,因此函数返回值为ELSE后面的“false”。
提示:一个CASE表达式的默认返回值类型是任何返回值的相容集合类型,但具体情况视其所在语境而定。如果用在字符串语境中,则返回结果为字符串。如果用在数字语境中,则返回结果为十进制值、实数值或整数值。
4,系统信息函数
MySQL中的系统信息有,数据库的版本号、当前用户名和连接数、系统字符集、最后一个自动生成的ID值等。
函数 | 说明 |
VERSION() | 返回指示MySQL服务器版本的字符串 |
CONNECTION_ID() | 返回MySQL服务器当前连接的次数,每个连接都有各自唯一的ID |
DATABASE()、 SCHEMA() | 返回使用utf8字符集的默认(当前)数据库名 |
USER()、CURRENT_USER()、SYSTEM_USER()、 SESSION_USER() | 返回当前被MySQL服务器验证的用户名和主机名组合 |
CHARSET(str) | 返回字符串 str自变量的字符集 |
COLLATION(str) | 返回字符串str的字符排列方式 |
LAST_INSERT_ID() | 自动返回最后一个INSERT或UPDATE为AUTO_INCREMENT 列设置的第一个发生的值 |
1,获取MySQL版本号、连接数和数据库名的函数
VERSION()返回指示MySQL服务器版本的字符串。这个字符串使用utf8字符集。
【例89】查看当前MySQL版本号,输入语句如下:
SELECT VERSION();
CONNECTION_ID()返回MySQL服务器当前连接的次数,每个连接都有各自唯一的 ID。
【例90】查看当前用户的连接数,输入语句如下:
SELECT CONNECTION_ID();
在这里返回3,返回值根据登录的次数会有不同。
SHOW PROCESSLIST;
SHOW PULL PROCESSLIST;
processlist命令的输出结果显示了有哪些线程在运行,不仅可以查看当前所有的连接数,还可以查看当前的连接状态,帮助识别出有问题的查询语句等。
如果是root账号,能看到所有用户的当前连接。如果是其他普通账号,则只能看到自己占用的连接。show processlist;只列出前100条,如果想全部列出可使用show full processlist 命令。
【例91】使用SHOW PROCESSLIST命令输出当前用户的连接信息,输入语句如下:
SHOW PROCESSLIST;
各个列的含义和用途:
(1)Id列,用户登录 MySQL时,系统分配的“connection id”。
(2)User列,显示当前用户。如果不是 root,这个命令就只显示用户权限范围内的SQL语句。
(3)Host列,显示这个语句是从哪个IP的哪个端口上发出的,可以用来追踪出现问题语句的用户。
(4)db 列,显示这个进程目前连接的是哪个数据库。
(5)Command列,显示当前连接执行的命令,一般取值为休眠(Sleep),查询(Query) ,连接(Connect) 。
(6)Time列,显示这个状态持续的时间,单位是秒。
(7)State列,显示使用当前连接的SQL语句的状态,很重要的列,后续会有所有状态的描述,State 只是语句执行中的某一个状态。一个SQL语句,以查询为例,可能需要经过Copying to tmp table,Sorting result,Sending data等状态才可以完成。
(8)Info列,显示这个SQL语句,是判断问题语句的一个重要依据。
使用另一个命令行登录MySQL,此时将会有2个连接,在第2个登录的命令行下再次输入SHOW PROCESSLIST,结果如下:
SHOW PROCESSLIST;
可以看到,当前活动用户为登录的连接d为2的用户,正在执行的Command(操作命令)是Query(查询),使用的查询命令为SHOW PROCESSLIST;而连接ld为1的用户目前没有对数据进行操作,即处于Sleep操作,而且已经经过了38秒。
DATABASE()和 SCHEMA()函数返回使用utf8字符集的默认(当前)数据库名。
【例92】查看当前使用的数据库,输入语句如下:
SELECT DATABASE(), SCHEMA();
可以看到,两个函数的作用相同。
2,获取用户名的函数
USER()、CURRENT_USER()、SYSTEM_USER()和 SESSION_USER()这几个函数返回当前被MySQL服务器验证的用户名和主机名组合。这个值符合确定当前登录用户存取权限的MySQL账户。一般情况下,这几个函数的返回值是相同的。
【例93】获取当前登录用户名称,输入语句如下:
SELECT USER(), CURRENT_USER(), SYSTEM_USER();
返回结果值指示了当前账户连接服务器时的用户名及所连接的客户主机 root 为当前登录的用户名,localhost为登录的主机名。
3,获取字符串的字符集和排序方式的函数
CHARSET(str)返回字符串 str自变量的字符集。
【例94】使用CHARSET()函数返回字符串使用的字符集,输入语句如下:
SELECT CHARSET('abc'),
CHARSET(CONVERT('abc' USING latin1)),
CHARSET(VERSION());
CHARSET('abc')返回系统默认的字符集utf8;CHARSET(CONVERT(abc' USING latin1))返回的字符集为latin1;前面介绍过,VERSION()返回的字符串使用utf8字符集,因此CHARSET(VERSIONO))返回结果为utf8。
COLLATION(str)返回字符串str的字符排列方式。
【例95】使用COLLATIONO函数返回字符串排列方式,输入语句如下:
SELECT COLLATION('abc'), COLLATION(CONVERT('abc' USING utf8));
可以看到,使用不同字符集时字符串的排列方式不同,
4,获取最后一个自动生成的ID值的函数
LAST_INSERT_ID()自动返回最后一个 INSERT或UPDATE为AUTO_INCREMENT 列设置的第一个发生的值。
【例96】使用SELECT LAST_INSERT_ID查看最后一个自动生成的列值,执行过程如下:
1,一次插入一条记录
首先创建表worker,其ID字段带有AUTO_INCREMENT约束,输入语句如下:
CREATE TABLE worker(
id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
name VARCHAR(30)
);
分别单独向表worker中插入两条记录:
INSERT INTO worker VALUES (NULL, 'jimy');
INSERT INTO worker VALUES (NULL, 'Tom');
查看已经插入的数据可以发现,最后一条插入的记录的ID字段值为2,使用LAST_INSERT_ID()查看最后自动生成的ID值:
SELECT LAST_INSERT_ID();
可以看到,一次插入一条记录时,返回值为最后一条插入记录的ID值。
2,一次同时插入多条记录
接下来,向表中插入多条记录,输入语句如下:
INSERT INTO worker(NAME) VALUES
('Kevin'), ('Michal'), ('Nick');
查询已经插入的记录,
SELECT * FROM worker;
可以看到最后一条记录的ID字段值为5,使用LAST_INSERT_ID()查看最后自动生成的ID值:
SELECT LAST_INSERT_ID();
结果显示,LAST_INSERT_ID值不是5而是3,这是为什么呢?在向数据表中插入一条新记录时,LAST_INSERT_ID)返回带有 AUTO_INCREMENT约束的字段最新生成的值2;继续向表中同时添加3条记录,这是因为当使用一条INSERT语句插入多个行时,LAST_INSERT_ID()只返回插入的第一行数据时产生的值在这里为第3条记录之所以这样,是因为这使依靠其他服务器复制同样的INSERT语句变得简单。
提示:LAST_INSERT_ID 是与table无关的,如果向表a插入数据后,再向表b 插入数据,LAST_INSERT_ID返回表b中的ID值。
5,加/解密函数
加密函数主要用来对数据进行加密和界面处理,以保证某些重要数据不被别人获取。这些函数在保证数据库安全时非常有用。
函数 | 说明 |
PASSWORD(str) | 从原明文密码str计算并返回加密后的密码字符串,当参数为NULL 时,返回NULL |
MD5(str) | 为字符串算出一个 MD5 128比特校验和。该值以32位十六进制数字的二进制字符串形式返回,若参数为NULL,则会返回NULL |
ENCODE(str,pswd_str) | 使用pswd_str 作为密码,加密str |
DECODE(crypt_str,pswd_str) | 使用pswd_str作为密码,解密加密字符串crypt_str,crypt_str是由ENCODEO返回的字符串 |
1,加密函数PASSWORD(str)
PASSWORD(str)从原明文密码str计算并返回加密后的密码字符串,当参数为NULL 时,返回NULL。
【例97】使用PASSWORD函数加密密码,输入语句如下:
SELECT PASSWORD('newpwd');
MySQL将 PASSwORD函数加密后的密码保存到用户权限表中。
提示:PASSWORD()函数在MySQL服务器的鉴定系统中使用;不应将它用在个人的应用程序中。PASSWORD()加密是单向的(不可逆)。PASSWORD()执行密码加密与UNLX中密码被加密的方式不同。
2,加密函数MD5(str)
MD5(str)为字符串算出一个 MD5 128比特校验和。该值以32位十六进制数字的二进制字符串形式返回,若参数为NULL,则会返回NULL。
【例98】使用MD5函数加密字符串,输入语句如下:
SELECT MD5('mypwd');
可以看到,“mypwd”经MD5加密后的结果为318beb4be908d0da6448aOdb76908d78。
加密后大写:
SELECT UPPER(MD5('mypwd'));
3,加密函数ENCODE(str,pswd_str)
ENCODE(str,pswd_str)使用pswd_str 作为密码,加密str。使用DECODEO解密结果,是一个和str长度相同的二进制字符串。
【例99】使用ENCODE加密字符串。输入语句如下:
SELECT ENCODE('secret', 'cry'), LENGTH(ENCODE('secret', 'ery'));
可以看到。加密后的显示结果为乱码,但加密后的长度和被加密的字符串长度相同,均为6.
4,解密函数DECODE(crypt_str,pswd_str)
DECODE(crypt_str,pswd_str)使用pswd_str作为密码,解密加密字符串 crypt_str,crypt_str是由ENCODEO返回的字符串。
【例100】使用DECODE 函数解密被ENCODE 加密的字符串,输入语句如下:mysq1>
SELECT DECODE(ENCODE ('secret', 'cry'), 'cry');
可以看到,使用相同解密字符串进行解密之后的结果,正好为ENCODE函数中被加密的字符串。DECODE函数和 ENCODE函数互为反函数。
6,其他函数
有些函数不能笼统地分为哪一类,但是这些函数也非常有用,例如重复指定操作函数、改变字符集函数、IP地址与数字转换函数等。
函数 | 说明 |
FORMAT(x,n) | 将数字x格式化,并以四舍五入的方式保留小数点后n位,结果以字符串的形式返回 |
CONV(N, from_base, to_base) | 函数进行不同进制数间的转换。返回值为数值N的字符串表示 |
INET_ATON(expr) | 给出一个作为字符串的网络地址的点地址表示,返回一个代表该地址数值的整数 |
INET_NTOA(expr) | 给定一个数字网络地址(4或8bit),返回作为字符中的该地址的点地址表示 |
GET_LOCK(str,timeout) | 设法使用字符串str 给定的名字得到一个锁,持续时间timeout秒 |
RELEASE_LOCK(str) | 解开被GET_LOCK()获取的,用字符串 str所命名的锁 |
IS_FREE_LOCK(str) | 检查名为str 的锁是否可以使用 |
IS_USED_LOCK(str) | 检查名为str 的锁是否正在被使用 |
BENCHMARK(count,expr) | 函数重复count 次执行表达式expr |
CONVERT(... USING ...) | 带有USING 的CONVERT()函数被用来在不同的字符集之间转化数据 |
CAST(x , AS type)、CONVERT(x, type) | 函数将一个类型的值转换为另一个类型的值 |
1,格式化函数FORMAT(x,n)
FORMAT(x,n)将数字x格式化,并以四舍五入的方式保留小数点后n位,结果以字符串的形式返回。若n为0,则返回结果函数不含小数部分。
【例101】使用FORMAT函数格式化数字,保留小数点位数为指定值,输入语句如下:
SELECT FORMAT(12332.123456,4), FORMAT(12332,1,4), FORMAT(12332,2,0);
由结果可以看到,FORMAT(12332.123456,4)保留4位小数点值,并进行四舍五入,结果为12332.1235 FORMAT(12332.1,4)保留4位小数值位数不够的用0补齐FORMAT(12332.2,0)不保留小数位值,返回结果为整数12332.
2,不同进制的数字进行转换的函数
CONV(N, from_base , to_base)函数进行不同进制数间的转换。返回值为数值N的字符串表示。由from_base进制转化为to_basc进制。如有任意一个参数为NULL,则返回值为NULL,自变量N被理解为一个整数,但是可以被指定为一个整数或字符中。最小基数为2,而最大基数则为 36。
【例102】使用CONV函数在不同进制数值之间转换,输入语句如下。
SELECT CONV('a',16,2),
CONV(15,16,2),
CONV(15,16,8),
CONV(15,16,16);
CONV(a',16,2)将十六进制的a转换为二进制表示的数值,十六进制的a表示十进制的数值 10,二进制的数值1010正好也等于十进制的数值10CONV(15,10.2)将十进制的数值15转换为二进制值。结果为1111; CONV(15,10,8)将十进制的数值15转换为八进制值,结果为17;CONV(15,10,16)将十进制的数值15转换为十六进制值,结果为F。
进制说明:
二进制,采用0和1两个数字来表示的数。它以2为基数,逢二进一。
八进制,采用0。1,2,3,4,5,6,7八个数字,逢八进一。以数字0开头。
十进制,采用0-9。共十个数字表示,逢十进—
十六进制,它由0-9,A-F组成。与十进制的对应关系是:0-9对应0-9A-F对应10-15,以数字0x开头.
3,IP地址与数字相互转换的函数
INET_ATON(expr)给出一个作为字符串的网络地址的点地址表示,返回一个代表该地址数值的整数。地址可以是4或 8bit地址。
【例103】使用INET_ATON函数将字符串网络点地址转换为数值网络地址,输入语句如下
SELECT INET_ATON('209.207.224.40');
产生的数字按照网络字节顺序。如上面的例子,
计算方法为:209×256^3+ 207*256^2+224×256+40。
INET_NTOA(expr)给定一个数字网络地址(4或8bit),返回作为字符中的该地址的点地址表示。
【例104】使用INET_NTOA函数将数值网络地址转换为字符串网络点地址,输入语句如下:
SELECT INET_NTOA(3520061480);
可以看到,INET_NTOA和 INET_ATON互为反函数。
4,加锁函数和解锁函数
GET_LOCK(str,timeout)设法使用字符串str 给定的名字得到一个锁,持续时间timeout秒。若成功得到锁,则返回1;若操作超时,则返回0;若发生错误,则返回NULL。假如有一个用GET_LOCK()得到的锁,当执行RELEASE_LOCK()或连接断开(正常或非正常)时,这个锁就会解除。
RELEASE_LOCK(str)解开被GET_LOCK()获取的,用字符串 str所命名的锁。若锁被解开,则返回1;若该线程尚未创建锁,则返回0(此时锁没有被解开);若命名的锁不存在,则返回NULL。若该锁从未被GET_LOCK()的调用获取,或锁已经被提前解开,则该锁不存在。
IS_FREE_LOCK(str)检查名为str 的锁是否可以使用(换言之,没有被封锁)。若锁可以使用,则返回1(没有人在用这个锁);若这个锁正在被使用,则返回0;出现错误,则返回NULL(诸如不正确的参数)。
IS_USED_LOCK(str)检查名为str 的锁是否正在被使用(换言之,被封锁)。若被封锁,则返回使用该锁的客户端的连接标识符(connection ID);否则,返回NULL。
【例105】使用加锁、解锁函数,输入语句如下:
SELECT GET_LOCK('lockl',10) AS GetLock,
IS_USED_LOCK('lock1')AS ISUsedLock,
IS_FREE_LOCK('1ock1') AS ISFreeLock,
RELEASE_LOCK('lock1') AS ReleaseLock;
GET_LOCK('lock1',10)返回结果为1,说明成功得到了一个名称为‘lock1’的锁,持续时间为10秒。
IS_USED_LOCK('lock1')返回结果为当前连接ID,表示名称为‘lock1’的锁正在被使用。
IS_FREE_LOCK('lock1')返回结果为0,说明名称为‘lock1’的锁正在被使用。
RELEASE_LOCK('lock1')返回值为1,说明解锁成功。
5,重复执行指定操作的函数
BENCHMARK(count,expr)函数重复count 次执行表达式expr。它可以用于计算MySQL处理表达式的速度。结果值通常为0(0只是表示处理过程很快,并不是没有花费时间)。另一个作用是它可以在 MySQL客户端内部报告语句执行的时间。
【例106】使用BENCHMARK重复执行指定函数。首先,使用PASSWORD函数加密密码,输入语句如下:
SELECT PASSWORD("newpwd' ):
可以看到,PASSWORD执行花费时间为0.00sec,下面使用BENCHMARK函数重复执行PASSWORD操作500000次:
SELECT BENCHMARK(500000,PASSWORD('newpwd') );
由此可以看出,使用BENCHMARK执行500000次的时间为0.67sec,明显比执行一次的时间延长了。
提示:BENCHMARK报告的时间是客户端经过的时间,而不是在服务器端的CPU时间,每次执行后报告的时间并不一定是相同的。读者可以多次执行该语句,查看结果。
6,改变字符集的函数
CONVERT(... USING ...)带有USING 的CONVERT()函数被用来在不同的字符集之间转化数据。
【例107】使用CONVERTO函数改变字符串的默认字符集,输入语句如下:
SELECT CHARSET('string'), CHARSET(CONVERT('string' USING latin1));
默认为utf8字符集,通过CONVERT将字符串“string”的默认字符集改为latin1.
7,改变数据类型的函数
CAST(x , AS type)和CONVERT(x, type)函数将一个类型的值转换为另一个类型的值,可转换的type有:BINARY、CHAR(n)、DATE、TIME、DATETIME、DECIMAL、SIGNED、UNSIGNED。
【例108】使用CAST和CONVERT函数进行数据类型的转换,SQL语句如下:
SELECT CAST(100 AS CHAR(2)), CONVERT('2010-10-01 12:12:12', TIME);
可以看到,CAST(100 AS CHAR(2))将整数数据100转换为带有两个显示宽度的字符串类型,结果为‘10’;CONVERT('2010-10-01 12:12:12', TIME) 将DATETIME类型的值,转换为TIME类型值,结果为‘12:12:12’。
疑问解答
疑问1: 如何从日期时间值中获取年、月、日等部分日期或时间值?
MySQL中,日期时间值以字符串形式存储在数据表中,因此可以使用字符串函数分别截取日期时间值的不同部分,例如某个名称为dt的字段有值“2010-10-01 12:00:30”,如果只需要获得年值,可以输入LEFT(dt,4),这样就获得了字符串左边开始长度为4的子字符串,即YEAR部分的值;如果要获取月份值,可以输入MID(dt,6,2),字符串第6个字符开始,长度为2的子字符串正好为dt中的月份值。同理,读者可以根据其他日期和时间的位置,计算并获取相应的值。
疑问2∶如何改变默认的字符集?
CONVERTO函数改变指定字符串的默认字符集,在开始的章节中,向读者介绍使用GUI图形化安装配置工具进行MySQL 的安装和配置,其中的一个步骤是可以选择MySQL 的默认字符集。但是,如果只改变字符集,没有必要把配置过程重新执行一遍,在这里,一个简单的方式是修改配置文件。在 Windows中,MySQL配置文件名称为my.ini,该文件在MySQL的安装目录下面。修改配置文件中的default-character-set和 character-set-server参数值,将其改为想要的字符集名称,如 gbk、gb2312、latin1等,修改完之后重新启动MySQL服务,即可生效。读者可以在修改字符集时使用SHOW VARIABLES LIKE 'character_set_%';命令查看当前字符集,以进行对比。
总结:
条件判断语句是非常常用的,if()只适合二元判断,case when的通用性也很高,二元到多元判断。加密函数中,MD5()函数,生成不可逆密码,经常用,可以直接改代码。其它函数中FORMAT(x,n)格式化和CAST(x , AS type)会用得多一些。
上一篇: 《mysql 日期时间函数》
下一篇: 《msyql 常用函数》