-- 存储过程
-- 1.存储过程,其实就是带逻辑的(多个)sql语句。
-- 也就是sql编程。
-- 2.存储过程的特点。
-- 1)存储过程保存到数据库服务器端,通过数据库客户端工具调用存储。
-- 2)存储过程的效率会非常高,因为存储过程是在服务器端执行的。
-- 3)缺点:存储过程的移植性是非常差的。
-- 如果数据库迁移,如果从mysql到Oracle的时候存储过程的语法差异是很大的。 就完全不能用了
-- 每种数据库客户端工具的存储过程的语法差异是很大的。
-- 存储过程在Stored Procs中
-- 查看全局变量
SHOW VARIABLES;
SHOW VARIABLES LIKE 'c%';
-- 但是关于全局变量:我们只能修改来设置
-- 不能添加全局变量,全局变量一共有300多个,都是有意义的
-- 只能添加和修改会话变量和局部变量
-- 1.0 使用现有的oracleDemo来测试我的存储过程
-- mysql中创建存储过程
-- 先要定义一个结束的符号
-- 符号是任意定义的
-- 一般是$
DELIMITER $ -- delimiter:分隔符(delimiter $ 定义$为分割符)
CREATE PROCEDURE test() -- 可以不写参数
BEGIN
SELECT * FROM emp;
END $ -- 在end的地方使用此分隔符进行结束说明
-- 调用存储过程
CALL test();
-- delimiter 结束符号
-- create procedure 存储过程名称(参数, 参数... )
-- begin
-- 多个sql语句
-- end 结束符号
-- 调用存储过程
-- call 存储过程名称(实际参数列表)
-- 参数类型
-- in 输入参数,可以携带数据到存储过程中
-- out 输出参数,可以携带数据到存储过程外面
-- inout 输入输出参数
-- 1.1 输入参数:查询指定id 的对应的员工
DELIMITER $
CREATE PROCEDURE pro_testByIn(IN id INT)
BEGIN
SELECT * FROM emp WHERE emp.`EMPNO` = id;
END $
-- 没有大小写的区别
CALL pro_testByIN(7566);
-- 调用:如何来接受存储过程的输出参数
-- 定义一个变量去接收输出参数。
-- mysql数据库中的三种变量:
-- 1)全局变量:mysql内置的变量,mysql程序关闭时,全局变量才会消失
-- show variables; 可以查看全部变量
-- show variables like 'character%'; 模糊匹配前面带有character的
-- character_set_client:mysql接收的客户端的数据编码
-- character_set_results:mysql输出给客户端的数据编码
-- 查看某个全局变量:select @@变量名
-- select @@character_set_client;
-- 修改全局变量:set @@变量名=值
-- set @@character_set_client=gbk;
-- 2)会话变量。变量只在某次登录的会话中有效!
-- 退出连接,会话变量数据失效!
-- 查看某个会话变量:select @变量名
-- 不同的客户端登录的,会话变量不能访问
-- 修改/定义 会话变量:set @变量名=值
-- set @name = 'eric';
-- 如果该会话变量不存在的话,修改就相当于创建
-- 3)局部变量:在存储过程中定义的变量
-- 存储过程结束,局部变量失效。
-- 查看某个会话变量:select 变量名
-- 修改局部变量:set 变量名=值
-- set name = 'eric';
-- 定义某个局部变量:
-- declare 变量名 数据类型;
-- 1.3 带有输出参数的存储过程
DELIMITER $
CREATE PROCEDURE pro_testByOut(OUT n VARCHAR(20))
BEGIN
SET n='输出参数';
END $
-- 带出输出参数,一般使用会话变量
-- 如果需要初始化参数的话 可以先set @n = '100'
-- 但是如果不需要的话,可以直接这样传,就可以使用了
CALL pro_testByOut(@n);
SELECT @n;
-- 1.4 带有输入输出参数的存储过程
DELIMITER $
CREATE PROCEDURE pro_testByInOut(INOUT n VARCHAR(20))
BEGIN
-- n被传入之后,就是此存储过程中的局部变量了
-- 查看变量
SELECT n;
-- 修改n变量
SET n = '500';
END $
SET @n = '100';
CALL pro_testByInOut(@n);
SELECT @n;
-- 1.5 带有判断条件的存储过程
-- 传入一个num整数,num=1 输出周一,num=2 输出周二,num=3 输出周三,否则不输出!
SET @num=1
DELIMITER $
CREATE PROCEDURE test_if(IN num INT, OUT str VARCHAR(20))
BEGIN
IF num=1 THEN
SET str='周一:day01'; -- 因为我们这个数据库在创建的时候忘记设置utf8,所以用英文
ELSEIF num=2 THEN
SET str='周二:day02';
ELSEIF num=3 THEN
SET str='周三:day03';
ELSE
SET str='错误参数:error';
END IF;
END $
CALL test_if(@num, @str);
SELECT @str;
-- 1.6 带有循环条件的存储过程
-- 需求:输入一个num,计算从1到num的总和。
DELIMITER $
CREATE PROCEDURE pro_testByWhile(IN num INT, OUT score INT)
BEGIN
-- 会话变量的修改和定义都是set
-- 局部变量的修改是set定义是DECLARE
DECLARE i INT DEFAULT 1;
DECLARE result INT DEFAULT 0;
WHILE i<=num DO
SET result = result + i;
SET i = i + 1;
END WHILE;
SET score = result;
END $
-- set @num = 100;
-- call pro_testByWhile(@num, @score);
-- select @score;
-- 形参和实参也遵循高级语言规则,可以不同
CALL pro_testByWhile(100, @score01);
SELECT @score01;
-- 1.7 携带数据库的数据给输出参数
-- 需求:传入员工id,查询对应的员工,输出员工姓名
DELIMITER $
CREATE PROCEDURE pro_testData(IN id INT, OUT ename VARCHAR(20))
BEGIN
-- 注意:这里不能直接写ename into ename
-- 虽然不会报错,但是mysql识别不出来,
-- 这样有歧义的话,不管id是多少查出来都是null
SELECT emp.ename INTO ename FROM emp WHERE emp.`EMPNO` = id;
END $
CALL pro_testData(7369, @ename);
SELECT @ename;
-- 1.8 进行一个对员工工资进行筛选的存储过程
DELIMITER $
CREATE PROCEDURE get_salGrade(IN sal DOUBLE(7, 2), OUT result VARCHAR(20))
BEGIN
IF sal BETWEEN 800 AND 1000 THEN
SET result = '很少';
ELSEIF sal BETWEEN 1001 AND 2000 THEN
SET result = '还好';
ELSEIF sal BETWEEN 2001 AND 4000 THEN
SET result = '不错';
ELSE
SET result ='XXX';
END IF;
END $
CALL get_salGrade(2000, @res);
SELECT @res;
DROP PROCEDURE get_salGrade; -- drop的话,直接写名字就可以