站保站

服务市场
  • 网站市场
  • 单机游戏
  • 平台大厅
  • 转让市场
  • 发卡市场
  • 广告市场
  • 下载市场
  • 收录市场
  • 本站平台
    平台客服
    微信Q群



    平台微博/weibo    平台微信/公众号    平台抖音/快手   
    曝光台    保障    地图   
    上传资源 快速赚钱
    站保站    登录      |  注册  |  

    只需一步,快速开始!

     找回密码   |   协议
    热门搜索: 网站开发 App报毒 挖矿源码 代办资质

    MySQL 5.6存储过程和函数语法的简单介绍

    • 时间:2020-10-25 18:27 编辑:@夜魅 来源: 阅读:1646
    • 扫一扫,手机访问
    摘要:

    MySQL支持存储的例程(存储过程和存储函数)

    存储的例程是一组可以存储在服务器中的SQL语句。完成此操作后,客户无需继续重新发出各个语句,而是可以引用存储的例程。

    首先先进行存储的例程语法学习:

    使用create procedure和create function语句创建存储的例程。

    使用call语句调用过程,并且只能使用输出变量传回值。

    可以像其他任何函数一样从语句内部调用一个函数(即,通过调用函数名称),并且可以返回标量值。

    存储例程的主体可以使用复合语句

    可以使用drop procedure和drop function语句删除存储的例程

    可以使用alter procedure和alter function语句对其进行更改

    简单演示:

    1. -- 声明结束符,因为mysql默认使用“;”作为结束符,而在存储过程中,会使用“;”作为一段语句的结束,导致“;”使用冲突
    2. delimiter $$
    3. CREATE PROCEDURE hello_procedure()
    4. BEGIN
    5. SELECT 'hello procedure';
    6. END $$
    7. CALL hello_procedure()

    一、变量和赋值

    对于存储过程中的变量,可以类比java中的局部变量和成员变量的声明和使用;

    1、局部变量:

    用户自定义,在begin/end块中有效

    语法:

    声明变量: declare var_name type [default 'unkown'];

    举例:declare nickname varchar(32);


    set 赋值

    1. -- 声明结束符,因为mysql默认使用“;”作为结束符,而在存储过程中,会使用“;”作为一段语句的结束,导致“;”使用冲突
    2. delimiter $$
    3. create PROCEDURE sp_var01()
    4. BEGIN
    5. -- 局部变量(需要声明) 字符类型如果为char或者varchar,一定要表明单位长度,int可以不写
    6. DECLARE nickname VARCHAR(32) DEFAULT 'SF';
    7. select nickname;
    8. -- set赋值
    9. set nickname := 'UG';
    10. select nickname;
    11. END $$
    12. -- 使用call调用该函数
    13. call sp_var01()$$
    14. -- 使用drop删除该函数,若想要修改该存储函数,mysql只能drop之后重新create
    15. drop PROCEDURE sp_var01;

    into 赋值

    1. -- 首先创建一张表
    2. DROP TABLE IF EXISTS `departments`;
    3. CREATE TABLE `departments` (
    4. `id` int(11) DEFAULT NULL,
    5. `dep_name` varchar(255) DEFAULT NULL
    6. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
    7. -- ----------------------------
    8. -- Records of departments
    9. -- ----------------------------
    10. INSERT INTO `departments` VALUES ('1', '开发');
    11. INSERT INTO `departments` VALUES ('2', '测试');
    12. INSERT INTO `departments` VALUES ('3', '产品');
    13. INSERT INTO `departments` VALUES ('4', '运维');
    14. -- 创建存储函数
    15. delimiter $$
    16. create PROCEDURE sp_var01_into()
    17. BEGIN
    18. -- 声明局部变量
    19. DECLARE dept_name VARCHAR(32) DEFAULT 'unkown';
    20. DECLARE dept_no int DEFAULT 0;
    21. -- select 查询要给局部变量赋值的属性 into 直接进行赋值
    22. SELECT d.id,d.dep_name into dept_no,dept_name from departments d where d.id = 1;
    23. select dept_no,dept_name;
    24. END $$
    25. call sp_var01_into()$$
    26. drop PROCEDURE sp_var01_into;

    2、用户变量

    用户自定义,当前会话(连接)有效

    语法:

    @var_name

    不需要提前声明,使用即声明

    set 赋值

    1. delimiter $$
    2. create PROCEDURE sp_var02()
    3. BEGIN
    4. set @nick_name = 'WR';
    5. END $$
    6. CALL sp_var02 $$
    7. select @nick_name $$

    into 赋值

    1. delimiter $$
    2. create PROCEDURE sp_var_into()
    3. BEGIN
    4. select d.dep_name into @deptname from departments d where d.id = 1;
    5. END $$
    6. CALL sp_var_into $$
    7. select @deptname $$

     

    3、会话变量

    由系统提供,整个mysql服务器有效

    语法:

    @@global.var_name

    4、全局变量

    由系统提供,整个Mysql服务器有效

    语法:

    @@global.var_name

    二、入参出参

    -- 语法

    in | out | inout param_name type

    举例

    1. -- int 类型演示
    2. delimiter $$
    3. create PROCEDURE sp_param01(in age int)
    4. BEGIN
    5. set @user_age = age;
    6. end $$
    7. call sp_param01(10) $$
    8. SELECT @user_age $$
    9. delimiter $$
    10. create PROCEDURE sp_param03(in `name` VARCHAR(32))
    11. BEGIN
    12. set @user_name = `name`;
    13. end $$
    14. call sp_param03('liman') $$
    15. SELECT @user_name $$
    16. -- out 类型,只负责输出!
    17. -- 需求:输出传入的地址字符串对应的部门编号。
    18. delimiter $$
    19. create PROCEDURE sp_param02(in deptname VARCHAR(32),out dept_no int(11))
    20. BEGIN
    21. SELECT d.id into dept_no from departments d where d.dep_name = deptname;
    22. -- 此处强调,要么表起别名,要么入参名不与字段名一致
    23. end $$
    24. -- 测试
    25. delimiter ;
    26. set @dept_no = 7;
    27. call sp_param02("开发",@dept_no);
    28. select @dept_no;
    29. -- inout类型
    30. delimiter $$
    31. create PROCEDURE sp_param04(inout `name` VARCHAR(32))
    32. BEGIN
    33. set `name` = CONCAT('hello ',`name`);
    34. end $$
    35. delimiter ;
    36. set @user_name = '小明';
    37. call sp_param04(@user_name);
    38. SELECT @user_name;

    三、流程控制--判断

    if -- 语法
    IF search_condition THEN statement_list 
        [ELSEIF search_condition THEN statement_list] ...
        [ELSE statement_list]
    END IF

    举例: 

    1. DROP TABLE IF EXISTS `emp`;
    2. CREATE TABLE `emp` (
    3. `empno` int(50) NOT NULL AUTO_INCREMENT,
    4. `ename` varchar(50) COLLATE utf8_general_mysql500_ci DEFAULT NULL,
    5. `job` varchar(50) COLLATE utf8_general_mysql500_ci DEFAULT NULL,
    6. `mgr` int(50) DEFAULT NULL,
    7. `hiredate` datetime DEFAULT NULL,
    8. `sal` decimal(10,2) DEFAULT NULL,
    9. `comm` varchar(25) COLLATE utf8_general_mysql500_ci DEFAULT NULL,
    10. `deptno` int(50) NOT NULL,
    11. PRIMARY KEY (`empno`)
    12. ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_general_mysql500_ci;
    13. -- ----------------------------
    14. -- Records of emp
    15. -- ----------------------------
    16. INSERT INTO `emp` VALUES ('1', 'smith', 'clerk', '7902', '1980-12-07 12:42:26', '8000.00', null, '1');
    17. INSERT INTO `emp` VALUES ('2', 'martmin', 'saleman', '1630', '1981-10-14 12:43:24', '10000.00', null, '2');
    1. -- 前置知识点:timestampdiff(unit,exp1,exp2)取差值,单位是unit
    2. select TIMESTAMPDIFF(YEAR,e.hiredate,now()) from emp e where e.empno = '2'

    1. delimiter //
    2. CREATE PROCEDURE sp_hire ()
    3. BEGIN
    4. DECLARE result VARCHAR (32) ;
    5. DECLARE years int;
    6. select TIMESTAMPDIFF(YEAR,e.hiredate,now()) into years from emp e where e.empno = '2';
    7. IF years > 40 THEN
    8. SET result = '元老' ;
    9. ELSEIF years > 38 THEN
    10. SET result = '老员工' ;
    11. ELSE
    12. SET result = '新手' ;
    13. END IF ;
    14. SELECT result ;
    15. END//
    16. delimiter ;
    17. CALL sp_hire();

    case 语法:此语法是不仅可以用在存储过程,查询语句也可以用!

    语法一(类比java的switch)
    CASE case_value
            when when_value then statement_list
            [when when_value then statement_list] ...
            [else statement_list]
    END CASE

     语法二:
    CASE 
        when search_condition then statement_list
        [when search_condition then statement_list]
    END CASE

    举例: 

    1. -- 需求:入职年限年龄<=38 是新手 >38<=40老员工 >40元老
    2. -- 语法一:
    3. -- 1.创建函数
    4. delimiter $$
    5. create PROCEDURE sp_hire_case_in(in year INT)
    6. BEGIN
    7. DECLARE result VARCHAR(32);
    8. DECLARE message VARCHAR(64);
    9. CASE year
    10. when 40
    11. then
    12. set result = '元老';
    13. set message = '老爷爷';
    14. when 38
    15. then
    16. set result = '老员工';
    17. set message = '油腻中年人';
    18. ELSE set result = '新手';
    19. set message = '萌新';
    20. end CASE;
    21. SELECT result,message;
    22. end $$
    23. delimiter;
    24. -- 2.调用函数
    25. call sp_hire_case_in(40);
    26. -- 3.删除函数
    27. drop PROCEDURE sp_hire_case_in;
    28. -- 语法二:
    29. -- 1.创建函数
    30. delimiter $$
    31. create PROCEDURE sp_hire_case()
    32. BEGIN
    33. DECLARE result VARCHAR(32);
    34. DECLARE message VARCHAR(64);
    35. CASE
    36. when TIMESTAMPDIFF(YEAR,'2001-01-01',now()) > 40
    37. then
    38. set result = '元老';
    39. set message = '老爷爷';
    40. when TIMESTAMPDIFF(YEAR,'2001-01-01',now()) > 38
    41. then
    42. set result = '老员工';
    43. set message = '油腻中年人';
    44. ELSE set result = '新手';
    45. set message = '萌新';
    46. end CASE;
    47. SELECT result,message;
    48. end $$
    49. delimiter;
    50. -- 2.调用函数
    51. call sp_hire_case();
    52. -- 3.删除函数
    53. drop PROCEDURE sp_hire_case;

    四、 流程控制-循环

    LOOP 语法:
    [begin_label:]LOOP
            statement_list
    END LOOP [end_label]

    举例:
        需要说明,loop是死循环,需要手动退出循环,我们可以使用leave来退出
        可以把leave看成我们Java中的break;
        与之对应的,就有iterate(继续循环),类比java中的continue

    死循环处理解决方法:

    1. -- 如有死循环处理,可以通过下面的命令查看并结束
    2. show processlist;
    3. kill  id;

    实例: 

    1. -- 需求:循环打印到1到10
    2. -- leave控制循环的退出
    3. delimiter $$
    4. CREATE PROCEDURE sp_flow_loop()
    5. begin
    6. DECLARE c_index int DEFAULT 1;
    7. DECLARE result_str VARCHAR(256) default '1';
    8. cnt:LOOP
    9. if c_index >= 10
    10. then leave cnt;
    11. end if;
    12. set c_index = c_index + 1;
    13. set result_str = CONCAT(result_str,',',c_index);
    14. end loop cnt;
    15. select result_str;
    16. end $$
    17. delimiter ;
    18. call sp_flow_loop();
    19. delimiter $$
    20. create PROCEDURE sp_flow_loop02()
    21. begin
    22. DECLARE c_index int DEFAULT 1;
    23. DECLARE result_str VARCHAR(256) default '1';
    24. cnt:LOOP
    25. set c_index = c_index + 1;
    26. set result_str = CONCAT(result_str,',',c_index);
    27. if c_index < 10 then
    28. ITERATE cnt; -- 约等于java的continue
    29. end if;
    30. -- 下面这句话能否执行到?什么时候执行到
    31. leave cnt;
    32. end loop cnt;
    33. select result_str;
    34. END $$
    35. delimiter;
    36. call sp_flow_loop02();

    REPEAT语法:相当于java中的 DO...WHILE...

    [begin_label:]REPEAT
       statement_list
    until search_condition  -- 直到... 为止 才退出循环
    END REPEAT [end_label]

     

    举例:

    1. -- 需求:循环打印1到10
    2. delimiter $$
    3. create PROCEDURE sp_flow_repeat()
    4. BEGIN
    5. DECLARE c_index int DEFAULT 1;
    6. -- 收集结果字符串
    7. declare result_str VARCHAR(256) DEFAULT '1';
    8. count_lab:REPEAT
    9. SET c_index = c_index + 1;
    10. set result_str = CONCAT(result_str,',',c_index);
    11. until c_index >= 10;
    12. end REPEAT count_lab;
    13. select result_str;
    14. end $$
    15. delimiter;
    16. call sp_flow_repeat();

     while:类比Java中的while(){}

     while语法:
    [begin_label:] while search_condition DO
            statement_list
    END WHILE [end_label]

    1. -- 需求:循环打印1到10
    2. delimiter $$
    3. create PROCEDURE sp_flow_while()
    4. begin
    5. DECLARE c_index int DEFAULT 1;
    6. -- 收集结果字符串
    7. DECLARE result_str VARCHAR(256) DEFAULT '1';
    8. while c_index < 10 DO
    9. set c_index = c_index + 1;
    10. set result_str = CONCAT(result_str,',',c_index);
    11. end while;
    12. SELECT result_str;
    13. end $$
    14. delimiter ;
    15. call sp_flow_while();

    五、流程控制 -- 退出、继续循环

    leave:类比java的Break;

    1. -- 退出leave can be used within begin ... end or loop constructs(LOOP,REPEAT,WHILE).
    2. LEAVE label

    ITERATE:类比java的continue;

    1. -- 继续循环 ITERATE can appear only within LOOP,and while statements
    2. ITERATE label

    六、游标

    用游标得到某一个结果集,逐行处理数据 (不建议用,因为是一行一行进行扫描的,效率比较低)
    类比 jdbc的resultSet

    1. -- 声明语法
    2. DECLARE cursor_name CURSOR FOR select_statement
    3. -- 打开语法
    4. OPEN cursor_name
    5. -- 取值语法(当fetch 到底 报错 no datas ) 每次只能一个值
    6. FETCH cursor_name into var_name [,var_name] ...
    7. -- 关闭语法
    8. CLOSE cursor_name

    实例:

    1. -- 需求:按照部门名称查询员工,通过select查看员工的编号、姓名、薪资。(注意,此处仅仅演示游标用法)
    2. drop PROCEDURE if EXISTS sp_create_table;
    3. delimiter $$
    4. create PROCEDURE sp_create_table(in dept_name VARCHAR(32))
    5. BEGIN
    6. DECLARE emp_no int;
    7. DECLARE emp_name VARCHAR(32);
    8. DECLARE emp_sal DECIMAL(7,2);
    9. DECLARE lp_flag boolean DEFAULT true;
    10. DECLARE emp_cursor cursor FOR
    11. SELECT e.empno,e.ename,e.sal from emp e
    12. inner join departments d
    13. on e.deptno = d.id where d.dep_name = dept_name;
    14. -- handle 句柄
    15. DECLARE CONTINUE HANDLER for 1329 set lp_flag = false;
    16. OPEN emp_cursor;
    17. emp_loop:LOOP
    18. FETCH emp_cursor into emp_no,emp_name,emp_sal; -- 一个fetch每次只能取一个值
    19. if lp_flag then
    20. SELECT emp_no,emp_name,emp_sal;
    21. ELSE
    22. LEAVE emp_loop;
    23. END IF;
    24. END LOOP emp_loop;
    25. set @end_flag = 'end';
    26. CLOSE emp_cursor;
    27. END $$
    28. delimiter ;
    29. CALL sp_create_table('开发');

    特别注意:

    在语法中,变量声明、游标声明、handle声明是必须按照先后顺序书写的,否则创建存储过程出错。

    七、存储过程中的handle

    1. HANDLER 语法:
    2. DECLARE handler_action HANDLER
    3. for condition_value [,condition_value] ...
    4. statement
    5. handler_ation:{
    6. CONTINUE
    7. |EXIT
    8. |UNDO
    9. }
    10. conditon_value:{
    11. mysql_error_code
    12. |SQLSTATE [VALUE] sqlstate_value
    13. |conditon_name
    14. |SQLWARNING
    15. |NOT FOUND
    16. |SQLEXCEPTION
    17. }
    • 全部评论(0)
    • 最新

    信息加载中,请等待

    微信客服(速回)

    微信客服(慢回)



    企业微信客服二维码
    联系我们
    平台客服: 平台QQ客服

    平台电话:400电话迁移中!

    平台邮箱:28292383@qq.com

    工作时间:周一至周五:早10:00 晚:18:00

    营业执照     网站ICP备案:鲁ICP备20027607号-1     鲁公网安备:37068702000078号     增值电信业务经营许可证、在线数据与交易处理业务许可证:鲁B2-20200681      © 2016-2024 站保站  https://www.zhanbaozhan.com/ 版权所有!      平台规范:   关于我们   广告合作   隐私条款   免责声明   法律声明   服务条款   网站地图   平台工单!