函数
MySQL函数(自定义函数),MySQL存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合,函数一般用于计算和返回一个值,通常用来进行一些计算。
创建自定义函数
CREATE FUNCTION 函数名(参数1 参数类型, 参数2 参数类型)
RETURNS 返回值类型
BEGIN
DECLARE 变量 变量类型;
SET 变量 = 变量值;
SELECT...INTO 变量;
RETURN 表达式/结果/查询;
END
如果一次输入的语句较多,并且语句中间有分号,这时需要新指定一个特殊的分隔符。
这个时候就需要用到DELIMITER
告诉mysql解释器,该段命令是否已经结束了,mysql是否可以执行了。
默认情况下,delimiter是;
DELIMITER $$
CREATE FUNCTION 函数名(参数1 参数类型, 参数2 参数类型)
RETURNS 返回值类型
BEGIN
DECLARE 变量 变量类型;
SET 变量 = 变量值;
SELECT...INTO 变量;
RETURN 表达式/结果/查询;
END$$
DELIMITER ;
删除函数
DROP FUNCTION 函数名
调用自定义函数
SELECT 函数名
案例
生成指定范围的随机整数
CREATE FUNCTION random_int_num(low INT,high INT)
RETURNS INT
BEGIN
RETURN ROUND(RAND()*(high-low)+low,0);
END;
如上通过输入范围的最小值和最大值进行返回范围内的随机整数。
如果希望函数进行根据大小自动判断范围,并返回范围内的随机整数。
DELIMITER $$
CREATE FUNCTION random_int_num(i INT,j INT)
RETURNS INT
BEGIN
DECLARE result INT;
IF(i>j)
THEN
SET result=ROUND(RAND()*(i-j)+j,0);
ELSE
SET result=ROUND(RAND()*(j-i)+i,0);
END IF;
RETURN result;
END
$$
储存过程
就是一组经过预先编译的 SQL 语句的封装,需要执行的时候就可以把预先存储好的这一系列 SQL 语句全部执行
创建存储过程
DELIMITER //
CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,...)
[characteristics ...]
BEGIN
存储过程体
END;
DELIMITER ;
删除存储过程
DROP PROCEDURE 存储过程名
调用存储过程
CALL 存储过程名(实参列表)
#如果你用的是其他数据库中的存储过程,哪就需要指定数据库名
CALL 库名.存储过程名(实参列表)
参数
MySQL存储过程的参数共有三种:IN \ OUT \ INOUT
- IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量)
- OUT 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)
- INOUT 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)
案例
向dept部门表批量插入随机数据
dept表结构
CREATE TABLE dept(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
dname VARCHAR(20) NOT NULL DEFAULT "",
loc VARCHAR(13) NOT NULL DEFAULT ""
) ENGINE=INNODB DEFAULT CHARSET=UTF8 ;
随机产生字符串函数
DELIMITER $$
CREATE FUNCTION random_str(n INT)
RETURNS VARCHAR(255)
BEGIN
DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ0123456789';
DECLARE return_str VARCHAR(255) DEFAULT '';
DECLARE i INT default 0;
WHILE i < n DO
SET return_str =CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*62),1));
##concat 连接函数 ,substring(a,index,length) 从index处开始截取
SET i = i + 1;
END WHILE;
RETURN return_str;
END $$
插入部门数据的存储过程
DELIMITER $$
CREATE PROCEDURE insert_dept (in deptno_prefix int,in max_num int(10))
BEGIN
DECLARE i INT DEFAULT 0;
set autocommit = 0;
REPEAT
SET i= i+1;
INSERT INTO dept(deptno,dname,loc) value (deptno_prefix+i,random_str(10),random_str(8));
UNTIL i = max_num
END REPEAT;
COMMIT;
END $$
优缺点
优点
- 存储过程可以一次编译多次使用。 存储过程只在创建时进行编译,之后的使用都不需要重新编译,这就提升了 SQL 的执行效率。
- 可以减少开发工作量。将代码封装成模块,实际上是编程的核心思想之一,这样可以把复杂的问题拆解成不同的模块,然后模块之间可以重复使用,在减少开发工作量的同时,还能保证代码的结构清晰。
- 存储过程的安全性强。我们在设定存储过程的时候可以设置对用户的使用权限,这样就和视图一样具有较强的安全性。
- 可以减少网络传输量。因为代码封装到存储过程中,每次使用只需要调用存储过程即可,这样就减少了网络传输量。
- 良好的封装性。在进行相对复杂的数据库操作时,原本需要使用一条一条的 SQL 语句,可能要连接多次数据库才能完成的操作,现在变成了一次存储过程,只需要连接一次即可。
缺点
- 可移植性差。存储过程不能跨数据库移植,比如在 MySQL、Oracle 和 SQL Server 里编写的存储过程,在换成其他数据库时都需要重新编写。
- 调试困难。只有少数 DBMS 支持存储过程的调试。对于复杂的存储过程来说,开发和维护都不容易。虽然也有一些第三方工具可以对存储过程进行调试,但要收费。
- 存储过程的版本管理很困难。比如数据表索引发生变化了,可能会导致存储过程失效。我们在开发软件的时候往往需要进行版本管理,但是存储过程本身没有版本控制,版本迭代更新的时候很麻烦。
- 它不适合高并发的场景。
存储过程和函数的区别
- 存储过程的用户在数据库中完成特定的操作或者任务(例如插入、删除等),而函数则用于返回特定的数据;
- 存储过程的声明使用procedure关键字,而函数的声明则使用function关键字;
- 存储过程不需要返回类型,而函数则必须要返回类型;
- 存储过程可以作为独立的PL-SQL执行,而函数则不能作为独立的PL-SQL执行,必须作为表达式的一部分;
- 存储过程只能通过out和in/out来返回值,而函数除了可以使用out和in/out以外,还可以使用return来返回值,而且函数中必须要有return子句;
- SQL语句(DML或者SELECT)中不可用调用存储过程,而函数可以;
- 执行方式略有不同,存储过程的执行方式有两种(使用execute,使用begin和end),函数除了存储过程的两种方式外,还可以作为表达式使用(例如放在select中)