这里主要介绍mysql丰富的内置函数。
数学函数
数学函数相对比较简单,就是涉及一些数值的计算,这里列出数学函数的功能,仅个别给出实例。
函数 | 作 用 |
ABX(x) | 返回x的绝对值 |
CEIL(X),CEILING(x) | 返回大于或等于x的最小整数 |
FLOOR(X) | 返回小于或等于x的最大整数 |
RAND() | 返回0~1的随机数 |
RAND(X) | 返回0~1的随机数,x值相同时,返回的随机数相同 |
SIGN(x) | 返回x的符号,负数,0,正数对应的符号分为-1,0,1 |
PI() | 返回圆周率 |
TRUNCATE(x,y) | 返回数值x保留到小数点后y位的值 |
ROUND(x) | 返回离x最近的整数 |
ROUND(x,y) | 保留x小数点后y位的值,但截断时要进行四舍五入 |
POW(x,y),POWER(x,y) | 返回x的y次方 |
SQRT(x) | 返回x的平方根 |
EXP(x) | 返回e的x次方 |
MOD(x,y) | 返回x除以y以后的余数 |
LOG(x) | 返回自然对数(以e为底的对数) |
LOG10(x) | 返回以10为底的对数 |
RADLANS(x) | 将角度转换为弧度 |
DEGREES(x) | 将弧度转换为角度 |
SIN(x) | 求正弦值 |
ASIN(x) | 求反正弦值 |
COS(x) | 求余弦值 |
aCOS(x) | 求反余弦值 |
TAN(x) | 求正切值 |
ATAN(x),ATAN2(x,y) | 求反正切值 |
COT(x) | 求余切值 |
root@testdb 09:55:30>select rand(); #返回随机值 +--------------------+ | rand() | +--------------------+ | 0.0276665883396441 | +--------------------+ 1 row in set (0.00 sec) root@testdb 10:10:26>select rand(); +--------------------+ | rand() | +--------------------+ | 0.9018256607482449 | +--------------------+ 1 row in set (0.00 sec) root@testdb 10:10:27>select rand(1); #x值相同,则返回相同的随机值 +---------------------+ | rand(1) | +---------------------+ | 0.40540353712197724 | +---------------------+ 1 row in set (0.00 sec) root@testdb 10:10:29>select rand(1); +---------------------+ | rand(1) | +---------------------+ | 0.40540353712197724 | +---------------------+ 1 row in set (0.00 sec) root@testdb 10:10:30>
ROUND(X)函数返回离x最近的整数,也就是对x进行四舍五入处理;ROUND(x,y)函数返回x保留到小数点后y位的值,截断时需要进行四舍五入处理,TRUNCATE(x,y)函数返回x保留到小数点后y位的值。
root@testdb 10:14:50>select pi(), round(pi()), round(pi(), 3), truncate(pi(),3); +----------+-------------+----------------+------------------+ | pi() | round(pi()) | round(pi(), 3) | truncate(pi(),3) | +----------+-------------+----------------+------------------+ | 3.141593 | 3 | 3.142 | 3.141 | +----------+-------------+----------------+------------------+ 1 row in set (0.00 sec) root@testdb 10:15:21>
mysql中内置的数学函数大致就如上面所列的,相对比较简单,在截断浮点数的时候,注意是否是采用来四舍五入的算法。
字符串函数
字符串函数是mysql中最常用的一类函数。字符串函数主要用于处理表中的字符串。字符串函数包括求字符串长度,合并字符串,在字符串中插入子串和大小写字母之间的切换等函数。主要有如下函数。
函数 | 作用 |
CHAR_LENGTH(S) | 返回字符串s的字符数 |
LENGTH(S) | 返回字符串s的长度 |
CONCAT(s1,s2,...) | 将多个字符串合并为一个字符串 |
CONCAT_WS(x,S1,S2,...) | 将多个字符串合并为一个字符串,但是每个字符串之间要加上x |
INSERT(s1,x, len, s2) | 将字符串s1中x位置开始长度为len的字符串用s2替换 |
UPPER(s),UCASE(s) | 将字符串s的所有字母都变成大写字母 |
LOWER(s),LCASE(s) | 将字符串s的所有字母都变为小写字母 |
LEFT(s,n) | 返回字符串s的左边n个字符 |
RIGHT(s,n) | 返回字符串s右边的n个字符 |
LPAD(s1, len, s2) | 字符串s2来填充s1的开始处,使字符串长度达到len |
RPAD(s1,len,s2) | 字符串s2来填充s1的结尾处,使字符串长度达到len |
LTRIM(s) | 去掉字符串s开始处的空格 |
RTRIM(s) | 去掉字符串s结尾处的空格 |
TRIM(s) | 去掉字符串s开始和结尾处的空格 |
TRIM(s1 FROM s2) | 函数去掉字符s中开始处和结尾处的字符串s1 |
REPEAT(s,n) | 将字符串s重复n次 |
SPACE(n) | 返回n个空格 |
REPLACE(s,s1,s2) | 用字符串s2替换字符串s中字符串s1 |
STRCMP(s1,s2) | 比较字符串s1和s2,这里是比较字符对应的ASCII码的大小 |
SUBSTRING(s,n,len) | 获取字符串s中第n个位置开始长度为len的字符 |
MID(s,n,len) | 同上 |
LOCATE(s1,S),POSITION(S1 IN S) | 从字符串s中获取字符串s1的开始位置 |
INSTR(S,S1) | 同上 |
REVERSE(S) | 将字符串s的顺序反过来 |
ELT(N,S1,S2..) | 返回第n个字符串 |
EXPORT_SET | 看下面的说明 |
FIELD(s,s1,s2...) | 返回第一个与字符串s匹配的字符串位置 |
FIND_IN_SET(S1,S2) | 返回在字符串s2中与s1匹配的字符串的位置 |
MAKE_SET(X,S1,S2...) | 按x的二进制数从s1,s2,...sn中选取字符串 |
比较返回的字符数与字符长度
这两个函数用英文字母不太好区别,我们使用汉语字符串如下:
root@testdb 10:15:21>select "北京", char_length("北京"),length("北京"); #在utf8编码中,每一个汉字占3个字符长度。两个字符,6个字符长度。 +--------+-----------------------+------------------+ | 北京 | char_length("北京") | length("北京") | +--------+-----------------------+------------------+ | 北京 | 2 | 6 | +--------+-----------------------+------------------+
合并字符串:
通过一个实例来说明两者之间的差别
root@employees 10:41:31>select concat(first_name,last_name) from employees limit 1; #这样合成的全名中间直接连接 +------------------------------+ | concat(first_name,last_name) | +------------------------------+ | GeorgiFacello | +------------------------------+ 1 row in set (0.01 sec) root@employees 10:45:02>select concat_ws("-",first_name,last_name) from employees limit 1; #这样合成的全名,中间会有一个短横线连接 +-------------------------------------+ | concat_ws("-",first_name,last_name) | +-------------------------------------+ | Georgi-Facello | +-------------------------------------+ 1 row in set (0.00 sec) root@employees 10:45:16>
替换字符串
root@employees 10:50:39>select insert("beijing",4,4,"fang"); #将“beijing”中第四个位置开始,长度为4的字符串替换为fang。 +------------------------------+ | insert("beijing",4,4,"fang") | +------------------------------+ | beifang | +------------------------------+ 1 row in set (0.00 sec) root@employees 10:51:32>
需要说明的是,替换的字符串长度可以和原字符中要替换的长度不相等:
root@employees 10:52:53>select insert("abcdefg",2,3,"hhhhhhhh"); +----------------------------------+ | insert("abcdefg",2,3,"hhhhhhhh") | +----------------------------------+ | ahhhhhhhhefg | +----------------------------------+ 1 row in set (0.00 sec) root@employees 10:54:25>select insert("abcdefg",2,3,"h"); +---------------------------+ | insert("abcdefg",2,3,"h") | +---------------------------+ | ahefg | +---------------------------+ 1 row in set (0.00 sec) root@employees 10:54:31>
获取指定长度的字符串函数
root@employees 10:54:31>select left("abcdef",3); #从左边弹出指定长度字符串 +------------------+ | left("abcdef",3) | +------------------+ | abc | +------------------+ 1 row in set (0.00 sec) root@employees 10:56:05>select right("abcdef",3); #从右边弹出指定长度字符串 +-------------------+ | right("abcdef",3) | +-------------------+ | def | +-------------------+ 1 row in set (0.00 sec)
填充字符串函数
root@employees 11:00:23>select "abc", lpad("abc", 6, "defgh"), rpad("abc", 6, "defgh"); #填充的长度超过要求的长度则截断 +-----+-------------------------+-------------------------+ | abc | lpad("abc", 6, "defgh") | rpad("abc", 6, "defgh") | +-----+-------------------------+-------------------------+ | abc | defabc | abcdef | +-----+-------------------------+-------------------------+ 1 row in set (0.00 sec) root@employees 11:00:45>select "abc", lpad("abc", 6, "d"), rpad("abc", 6, "d"); #填充的长度不足要求的长度则重复补充 +-----+---------------------+---------------------+ | abc | lpad("abc", 6, "d") | rpad("abc", 6, "d") | +-----+---------------------+---------------------+ | abc | dddabc | abcddd | +-----+---------------------+---------------------+ 1 row in set (0.00 sec) root@employees 11:00:57>
删除指定字符串函数
trim(s1 from s)函数去掉字符s中开始处和结尾处的字符串s1.
root@employees 11:00:57>select trim("aa" from "aabcdefaaghiaaa"); #中间的满足的字符并不会被删除, +-----------------------------------+ | trim("aa" from "aabcdefaaghiaaa") | +-----------------------------------+ | bcdefaaghia | +-----------------------------------+ 1 row in set (0.00 sec) root@employees 11:04:47>select trim("a" from "aabcdefaaghiaaa"); +----------------------------------+ | trim("a" from "aabcdefaaghiaaa") | +----------------------------------+ | bcdefaaghi | +----------------------------------+ 1 row in set (0.00 sec) root@employees 11:04:54>
重复和替换字符
root@employees 11:04:54>select repeat("a","5"); #字符“a”重复5次 +-----------------+ | repeat("a","5") | +-----------------+ | aaaaa | +-----------------+ 1 row in set (0.00 sec) root@employees 11:06:49>select replace("shenyang","yang","zhen"); #“yang”替换为“zhen” +-----------------------------------+ | replace("shenyang","yang","zhen") | +-----------------------------------+ | shenzhen | +-----------------------------------+ 1 row in set (0.00 sec) root@employees 11:07:33>
MAKE_SET函数
make-set(x,s1,s2,...)函数按x的二进制数从s1,s2,....,sn中选取字符串。例如x值为12,二进制数为1100,这个二进制数从右到左的第三位和第四位是1,所有选取s3和s4.
root@employees 11:21:33>select make_set(11,"a","b","c","d"), make_set(3,"a","b","c","d"); +------------------------------+-----------------------------+ | make_set(11,"a","b","c","d") | make_set(3,"a","b","c","d") | +------------------------------+-----------------------------+ | a,b,d | a,b | +------------------------------+-----------------------------+ 1 row in set (0.00 sec)
#在计数时注意二进制数从低位到高位,字符串则按正常顺序。
EXPORT_SET函数
语法结构如下:
EXPORT_SET(bits,on,off[,separator[,number_of_bits]]) number_of_bits:默认数值是64,可以指定。 on的字符串对应1,off的字符串对应0.
通过一个实例来说明这个函数的用法:
root@employees 11:33:06>select export_set("11","a","b", "-", 6); +----------------------------------+ | export_set("11","a","b", "-", 6) | +----------------------------------+ | a-a-b-a-b-b | +----------------------------------+ 1 row in set (0.00 sec) root@employees 11:33:43> #数字11的二进制数为1011,把这个二进制数补全到number_of_bits位,这里是补全到6位即:001011,默认是64位。 然后数字1对应on位置的字符串即为a,数字0对应off位置的字符串即为b,然后按照二进制数的从低位到高位组成字符串即: aababb.最后把组成的字符串使用"-"连接即为:a-a-b-a-b-b
日期函数
日期函数也是用的比较多的函数,下面会详细介绍mysql中日期函数的用法。
获取当前日期和时间的函数
CURDATE()和CURRENT_DATE()函数获取当前日期;CURTIME()和CURRENT_TIME()获取当前时间。
root@employees 11:40:16>select curdate(),current_date(),curtime(),current_time(); +------------+----------------+-----------+----------------+ | curdate() | current_date() | curtime() | current_time() | +------------+----------------+-----------+----------------+ | 2019-04-28 | 2019-04-28 | 23:42:31 | 23:42:31 | +------------+----------------+-----------+----------------+ 1 row in set (0.00 sec)
NOW(),CURRENT_TIMESTAMP(),LOCALTIME()和SYSDATE()等4个函数都用来获取当前的日期和时间。这四个函数标识相同的含义。
root@employees 11:42:31>select now(),current_timestamp(),localtime(),sysdate(); +---------------------+---------------------+---------------------+---------------------+ | now() | current_timestamp() | localtime() | sysdate() | +---------------------+---------------------+---------------------+---------------------+ | 2019-04-28 23:45:11 | 2019-04-28 23:45:11 | 2019-04-28 23:45:11 | 2019-04-28 23:45:11 | +---------------------+---------------------+---------------------+---------------------+ 1 row in set (0.00 sec)
一个如下实例:
root@employees 11:47:23>select now(),current_timestamp(),localtime(),sysdate(), sleep(2), now(),current_timestamp(),localtime(),sysdate(); +---------------------+---------------------+---------------------+---------------------+----------+---------------------+---------------------+---------------------+---------------------+ | now() | current_timestamp() | localtime() | sysdate() | sleep(2) | now() | current_timestamp() | localtime() | sysdate() | +---------------------+---------------------+---------------------+---------------------+----------+---------------------+---------------------+---------------------+---------------------+ | 2019-04-28 23:47:50 | 2019-04-28 23:47:50 | 2019-04-28 23:47:50 | 2019-04-28 23:47:50 | 0 | 2019-04-28 23:47:50 | 2019-04-28 23:47:50 | 2019-04-28 23:47:50 | 2019-04-28 23:47:52 | +---------------------+---------------------+---------------------+---------------------+----------+---------------------+---------------------+---------------------+---------------------+ 1 row in set (2.00 sec) root@employees 11:47:52>
可以看到最后一个sysdate返回的时间比其余的函数返回的时间差了2秒,其余函数返回的是语句执行时候的时间,而sysdate返回的则是语句执行到这个点的时间。
时间戳函数
有返回时间戳的函数,自然有转换时间戳的函数。UNIX_TIMESTAMP函数以时间戳的形式返回当前时间;unix_timestamp(d)函数将时间d以unxi时间戳的形式返回;from_unixtime(d)函数把时间戳转换为普通格式的时间。
root@employees 11:56:56>select now(),unix_timestamp(), unix_timestamp(now()), from_unixtime(unix_timestamp()); +---------------------+------------------+-----------------------+---------------------------------+ | now() | unix_timestamp() | unix_timestamp(now()) | from_unixtime(unix_timestamp()) | +---------------------+------------------+-----------------------+---------------------------------+ | 2019-04-28 23:57:42 | 1556510262 | 1556510262 | 2019-04-28 23:57:42 | +---------------------+------------------+-----------------------+---------------------------------+ 1 row in set (0.00 sec)
#unix_timestamp默认返回当前时间点的时间戳,也可以给一个时间参数,返回对应时间的时间戳。from_unixtime则把时间戳转换为对应的可读的时间。
返回UTC时间
UTC_DATE()函数返回UTC日期;UTC_TIME()函数返回UTC时间。UTC也就是国际日期协调时间。会有时区的差别的。
root@employees 11:57:42>select curdate(),utc_date(),curtime(),utc_time(); +------------+------------+-----------+------------+ | curdate() | utc_date() | curtime() | utc_time() | +------------+------------+-----------+------------+ | 2019-04-29 | 2019-04-29 | 00:00:50 | 04:00:50 | +------------+------------+-----------+------------+ 1 row in set (0.00 sec)
与年月日和周相关的几个函数
MONTH(d)函数返回日期d中的月份,其取值范围是1~12;monthname(d)函数返回日期d中的月份的英文名称。
root@employees 12:01:11>select now(),month(now()),monthname(now()); +---------------------+--------------+------------------+ | now() | month(now()) | monthname(now()) | +---------------------+--------------+------------------+ | 2019-04-29 01:48:29 | 4 | April | +---------------------+--------------+------------------+ 1 row in set (0.00 sec) root@employees 01:48:29>
dayname(d)函数返回日期d是星期几,显示英文名。dayofweek函数一周中的第几天,1表示第一天,2表示第二天(周日算第一天)。weekday返回日期是星期几,0表示星期一,1表示星期二。
root@employees 01:48:29>select dayname(now()),dayofweek(now()),weekday(now()); #星期一,一周中的第2天。 +----------------+------------------+----------------+ | dayname(now()) | dayofweek(now()) | weekday(now()) | +----------------+------------------+----------------+ | Monday | 2 | 0 | +----------------+------------------+----------------+ 1 row in set (0.00 sec) root@employees 01:51:45>
获取周的函数week,以及一年中的第几周的函数。 #这两个值不一样,有点不理解?
root@employees 01:51:45>select week(now()),weekofyear(now()); +-------------+-------------------+ | week(now()) | weekofyear(now()) | +-------------+-------------------+ | 17 | 18 | +-------------+-------------------+ 1 row in set (0.00 sec)
获取天数的函数
root@employees 01:57:32>select dayofyear(now()),dayofmonth(now()),now(); +------------------+-------------------+---------------------+ | dayofyear(now()) | dayofmonth(now()) | now() | +------------------+-------------------+---------------------+ | 119 | 29 | 2019-04-29 01:57:45 | +------------------+-------------------+---------------------+ 1 row in set (0.00 sec) root@employees 01:57:45>
获取年份,季度,小时,分钟和秒钟的函数。
root@employees 01:57:45>select now(),year(now()),quarter(now()),minute(now()),second(now()); +---------------------+-------------+----------------+---------------+---------------+ | now() | year(now()) | quarter(now()) | minute(now()) | second(now()) | +---------------------+-------------+----------------+---------------+---------------+ | 2019-04-29 01:59:25 | 2019 | 2 | 59 | 25 | +---------------------+-------------+----------------+---------------+---------------+ 1 row in set (0.00 sec)
获取日期的指定函数值
extract(type from d)函数从日期d中获取指定的值。这个值是什么由type的值决定。type的值可以是year,month,day,hour,minute和second。
root@(none) 03:08:14>select now(), extract(year from now()); +---------------------+--------------------------+ | now() | extract(year from now()) | +---------------------+--------------------------+ | 2019-04-29 03:08:24 | 2019 | +---------------------+--------------------------+ 1 row in set (0.00 sec) root@(none) 03:08:24>
时间和秒钟的转换函数
time_to_sec(t)函数将时间t转换为以秒为单位的时间;sec_to_time(s)函数将以秒为单位的时间转换为时分秒的格式。
root@(none) 03:12:11>select curtime(),time_to_sec(curtime()),sec_to_time(11531); +-----------+------------------------+--------------------+ | curtime() | time_to_sec(curtime()) | sec_to_time(11531) | +-----------+------------------------+--------------------+ | 03:12:35 | 11555 | 03:12:11 | +-----------+------------------------+--------------------+ 1 row in set (0.00 sec)
计算日期和时间的函数
1:TO_DAYS(d),FROM_DAYS(N),DATEDIFF(d1,d2)函数。to_days函数计算日期d与0000年1月1日的天数;FROM_DAYS函数计算从0000年1月1日开始n天后的日期;DATEDIFF(d1,d2)函数计算两个日期的相隔天数。
root@(none) 03:12:35>select curdate(),to_days(curdate()); +------------+--------------------+ | curdate() | to_days(curdate()) | +------------+--------------------+ | 2019-04-29 | 737543 | +------------+--------------------+ 1 row in set (0.00 sec) root@(none) 03:16:47>select from_days(737543); +-------------------+ | from_days(737543) | +-------------------+ | 2019-04-29 | +-------------------+ 1 row in set (0.00 sec) root@(none) 03:17:33>select datediff(curdate(), "2019-04-20"); +-----------------------------------+ | datediff(curdate(), "2019-04-20") | +-----------------------------------+ | 9 | +-----------------------------------+ 1 row in set (0.00 sec)
2:adddate在指定的日期上加上n天,subdate在指定的日期上减去n天;addtime在指定的日期上加上n秒,subtime在指定的日期上减去n秒。
root@testdb 03:30:58>select curdate(),adddate(curdate(),3),subdate(curdate(),3); +------------+----------------------+----------------------+ | curdate() | adddate(curdate(),3) | subdate(curdate(),3) | +------------+----------------------+----------------------+ | 2019-04-29 | 2019-05-02 | 2019-04-26 | +------------+----------------------+----------------------+ 1 row in set (0.00 sec) root@testdb 03:31:07>
adddate的进阶用法:
ADDDATE(date,INTERVAL expr unit)函数和DATE_ADD(date,INTERVAL expr unit)函数,给日期的某一部分加上expr的时间。
root@testdb 04:04:30>select curdate(), adddate(curdate(),interval '1' year); #给当前日期的年份加上1 +------------+--------------------------------------+ | curdate() | adddate(curdate(),interval '1' year) | +------------+--------------------------------------+ | 2019-04-29 | 2020-04-29 | +------------+--------------------------------------+ 1 row in set (0.00 sec) root@testdb 04:04:45>
root@testdb 04:05:53>select curdate(), date_add(curdate(),interval '1 2' year_month); #给年份和月份分别加上1和2
+------------+-----------------------------------------------+
| curdate() | date_add(curdate(),interval '1 2' year_month) |
+------------+-----------------------------------------------+
| 2019-04-29 | 2020-06-29 |
+------------+-----------------------------------------------+
1 row in set (0.00 sec)
root@testdb 04:06:11
unit的间隔类型可以取值如下:
year, month, day, hour,minute, second, year_month, day_hour, day_minute, day_second, hour_minute, hour_second, minute_second
有加自然有减,对应的subdate的用法和上面一样。
将日期和时间格式化的函数
DATE_FORMAT(d,f)函数安装表达式f的要求显示日期d。表达式f指定来显示的格式。
root@testdb 04:06:11>select curdate(),date_format(curdate(),"%b %D %Y"); +------------+-----------------------------------+ | curdate() | date_format(curdate(),"%b %D %Y") | +------------+-----------------------------------+ | 2019-04-29 | Apr 29th 2019 | +------------+-----------------------------------+ 1 row in set (0.00 sec)
time_formate(d,f)按照响应的格式显示时间。
格式化的时候不同的简写代表不同格式,具体内容可以参考官方文档:https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format
其他函数
格式化函数
format(x,n)函数可以将数字x进行格式化,将x保留到小数点后n位,这个过程需要四舍五入。
root@testdb 04:20:18>select format(3.14159, 3); +--------------------+ | format(3.14159, 3) | +--------------------+ | 3.142 | +--------------------+ 1 row in set (0.00 sec)
ip地址与数字相互转换
inet_aton(ip)函数可以将ip地址转换为数字表示;inet_ntoa(n)函数可以将数字转换为ip形式。
root@testdb 04:20:20>select inet_aton("10.0.68.42"); +-------------------------+ | inet_aton("10.0.68.42") | +-------------------------+ | 167789610 | +-------------------------+ 1 row in set (0.00 sec) root@testdb 04:22:33>select inet_ntoa(167789610); +----------------------+ | inet_ntoa(167789610) | +----------------------+ | 10.0.68.42 | +----------------------+ 1 row in set (0.00 sec) root@testdb 04:22:49>
重复执行操作的函数
benchmark(count,expr)函数将表达式expr重复执行count次,然后返回执行时间。
root@testdb 04:26:33>select benchmark(10000,now()); #这说明执行时间短,为0 +------------------------+ | benchmark(10000,now()) | +------------------------+ | 0 | +------------------------+ 1 row in set (0.00 sec) root@testdb 04:26:56> root@testdb 04:25:59>select benchmark(2,sleep(2)); #这个4秒的时间,不知道为啥也是0 +-----------------------+ | benchmark(2,sleep(2)) | +-----------------------+ | 0 | +-----------------------+ 1 row in set (4.00 sec)
改变字段数据类型的函数
cast(x as type)和convert(x, type)这两个函数将x变成type类型,这两个函数只对binary,char,date,datetime,time,int这些类型起作用。只改变来输出值的数据类型,不改变表中字段的类型。
root@testdb 04:26:56>select now(), cast(now() as date),convert(now(),time); +---------------------+---------------------+---------------------+ | now() | cast(now() as date) | convert(now(),time) | +---------------------+---------------------+---------------------+ | 2019-04-29 04:31:26 | 2019-04-29 | 04:31:26 | +---------------------+---------------------+---------------------+ 1 row in set (0.00 sec)