存储过程和函数
- 存储函数和存储过程统称为存储例程(stored routine)。存储过程和函数是在数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句。
优点
- 存储过程和函数可以避免开发人员重复的编写相同是SQL语句,可减少数据库开发人员的工作量。
- 存储过程和函数是在MySQL服务器中存储和执行的,可以减少客户端和服务器段的数据传输。
- 存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般 SQL 语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
- 安全性高,可设定只有某此用户才具有对指定存储过程的使用权。
注意
- 当对数据库进行复杂操作时,可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。这些操作,如果用程序来完成,就变成了一条条的 SQL 语句,可能要多次连接数据库。而换成存储,只需要连接一次数据库就可以了。
- 在数据库服务器上进行大量的复杂运算也会占用服务器的 CPU, 造成数据库服务器的压力, 所以不要在存储过程和函数中进行大量的复杂运算,应尽量将这些运算操作分摊到应用服务器上执行。
- 如果执行比较简单的数据库操作,例如简单的增删改查就没有必要使用存储过程了。维护起来也是比较麻烦的事情,而且效率也不会提高太多。
- 当客户端和数据库服务器都是在同一台机器的时候,使用存储过程的意义不大,除非做的是很复杂的数据库操作。
存储过程与函数的对比
- 两者的定义语法很相似,但却是不同的内容。存储函数限制比较多,比如不能用临时表,只能用表变量。还有一些函数都不可用等等。而存储过程的限制相对就比较少。
- 一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。存储过程一般是作为一个独立的部分来执行,而函数可以作为查询语句的一个部分来调用,由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面。
- 存储过程可以接受参数、输出参数、返回单个或多个结果集以及返回值,可以向程序返回错误原因。但函数只能返回一个特定类型的值或者表对象。存储过程中的CRUD的操作会影响数据库状态,但函数却不能。
功能 | 存储过程 | 函数 | 创建 create procedure <过程名>(<参数列表,无参时忽略>) create function <函数名>(<参数列表,无参时忽略>) 返回值 不一定有返回值 函数必须有返回值 参数 有三种、IN、OUT、INOUT 类似于IN参数 调用 call select
MySQL数据库提供的函数
数学函数
函数 | 作用 | 例子 | 运行结果 | ABS(x) 返回x的绝对值 SELECT ABS(-100) 100 BIN(x) 返回x的二进制(OCT返回八进制,HEX返回十六进制) SELECT BIN(5) 101 CEILING(x) 返回大于x的最小整数值 SELECT CEILING(5.1) 6 EXP(x) 返回值e(自然对数的底)的x次方 SELECT EXP(-1) 0.36787944117144233 FLOOR(x) 返回小于x的最大整数值 SELECT FLOOR(365.76) 365 GREATEST(x1,x2,…,xn) 返回集合中最大的值 SELECT GREATEST(50,46,89,98,1,56,47,5,0) 98 LEAST(x1,x2,…,xn) 返回集合中最小的值 SELECT LEAST(50,46,89,98,1,56,47,5,0) 0 LN(x) 返回x的自然对数 SELECT LN(2.71828) 0.999999327347282 LOG(x,y) 返回x的以y为底的对数 SELECT LOG(10,10) 1 MOD(x,y) 返回x/y的模(余数) SELECT MOD(30,7) 2 PI() 返回pi的值(圆周率) SELECT PI() 3.141593 RAND() 返回0到1内的随机值,可以通过提供一个参数(种子)使RAND()随机数生成器生成一个指定的值 SELECT RAND() 结果是随机的 ROUND(x,y) 返回参数x的四舍五入的有y位小数的值 SELECT ROUND(123.16789,3) 123.168 SIGN(x) 返回代表数字x的符号的值,负数返回-1,0返回0,正数返回1 SELECT SIGN(-100) -1聚合函数(常用于GROUP BY从句的SELECT查询中)
函数 | 作用 | 例子 | GROUP_CONCAT(col) 返回该列值连接组合而成的结果(字符串) SELECT GROUP_CONCAT(col) FROM table_name MIN(col) 返回指定列的最小值 SELECT MIN(col) FROM table_name MAX(col) 返回指定列的最大值 SELECT MAX(col) FROM table_name COUNT(col) 返回指定列中非NULL值的个数 SELECT COUNT(col) FROM table_name SUM(col) 返回指定列的所有值之和 SELECT SUM(col) FROM table_name AVG(col) 返回指定列的平均值 SELECT AVG(col) FROM table_name字符串函数
函数 | 作用 | 例子 | ASCII(char) 返回字符的ASCII码值 SELECT ASCII(‘a’) BIT_LENGTH(str) 返回字符串的比特长度 SELECT BIT_LENGTH(“hello world”) CONCAT(s1,s2…,sn) 将s1,s2…,sn连接成字符串 SELECT CONCAT(“hello”,” “, “world”) CONCAT_WS(sep,s1,s2…,sn) 将s1,s2…,sn连接成字符串,并用sep字符间隔 SELECT CONCAT_WS(“*”,”a”,”b”,”c”) 将s1,s2…,sn连接成字符串,并用sep字符间隔 SELECT CONCAT_WS(“*”,”a”,”b”,”c”) INSERT(str,x,y,instr) 将字符串str从第x位置开始,y个字符长的子串替换为字符串instr,返回结果 FIND_IN_SET(str,list) 分析逗号分隔的list列表,如果发现str,返回str在list中的位置 LCASE(str)或LOWER(str) 返回将字符串str中所有字符改变为小写后的结果 LEFT(str,x) 返回字符串str中最左边的x个字符 LENGTH(s) 返回字符串str中的字符数 LTRIM(str) 从字符串str中切掉开头的空格 POSITION(substr,str) 返回子串substr在字符串str中第一次出现的位置 QUOTE(str) 用反斜杠转义str中的单引号 REPEAT(str,srchstr,rplcstr) 返回字符串str重复x次的结果 REVERSE(str) 返回颠倒字符串str的结果 RIGHT(str,x) 返回字符串str中最右边的x个字符 RTRIM(str) 返回字符串str尾部的空格 STRCMP(s1,s2) 比较字符串s1和s2 TRIM(str) 去除字符串首部和尾部的所有空格 UCASE(str)或UPPER(str) 返回将字符串str中所有字符转变为大写后的结果 日期和时间函数
函数 | 作用 | 例子 | CURDATE()或CURRENT_DATE() 返回当前的日期 CURTIME()或CURRENT_TIME() 返回当前的时间 DATE_ADD(date,INTERVAL int keyword) 返回日期date加上间隔时间int的结果(int必须按照关键字进行格式化) DATE_FORMAT(date,fmt) 依照指定的fmt格式格式化日期date值 DATE_SUB(date,INTERVAL int keyword) 返回日期date加上间隔时间int的结果(int必须按照关键字进行格式化) DAYOFWEEK(date) 返回date所代表的一星期中的第几天(1~7) DAYOFMONTH(date) 返回date是一个月的第几天(1~31) DAYOFYEAR(date) 返回date是一年的第几天(1~366) DAYNAME(date) 返回date的星期名 FROM_UNIXTIME(ts,fmt) 根据指定的fmt格式,格式化UNIX时间戳ts HOUR(time) 返回time的小时值(0~23) MINUTE(time) 返回time的分钟值(0~59) MONTH(date) 返回date的月份值(1~12) MONTHNAME(date) 返回date的月份名 NOW() 返回当前的日期和时间 QUARTER(date) 返回date在一年中的季度(1~4) WEEK(date) 返回日期date为一年中第几周(0~53) YEAR(date) 返回日期date的年份(1000~9999) 一些示例:
获取当前系统时间:SELECT FROM_UNIXTIME(UNIX_TIMESTAMP());
SELECT EXTRACT(YEAR_MONTH FROM CURRENT_DATE);
SELECT EXTRACT(DAY_SECOND FROM CURRENT_DATE);
SELECT EXTRACT(HOUR_MINUTE FROM CURRENT_DATE);
返回两个日期值之间的差值(月数):SELECT PERIOD_DIFF(200302,199802);
在Mysql中计算年龄:
SELECT DATE_FORMAT(FROM_DAYS(TO_DAYS(NOW())-TO_DAYS(birthday)),’%Y’)+0 AS age FROM employee;
这样,如果Brithday是未来的年月日的话,计算结果为0。
下面的SQL语句计算员工的绝对年龄,即当Birthday是未来的日期时,将得到负值。
SELECT DATE_FORMAT(NOW(), ‘%Y’) - DATE_FORMAT(birthday, ‘%Y’) -(DATE_FORMAT(NOW(), ‘00-%m-%d’)