MySQL存储过程语法
MySQL存储过程语法
- 1、语法结构
- 2、变量及赋值
- 2.1、局部变量
- 2.2、用户变量
- 2.3、全局变量:
- 3、出参和入参
- 4、流程控制
- 4.1、判断
- 4.1.1、IF
- 4.1.2、CASE
- 4.2、循环
- 4.2.1、LOOP
- 4.2.2、REPEAT
- 4.2.3、WHILE
- 4.3、游标和HANDLER
- 5、应用
- 5.1、临时表
- 5.2、可以在select语句中写case
- 5.3、执行sql字符串
1、语法结构
– 官方参考网址
https://dev.mysql.com/doc/refman/5.6/en/sql-statements.html
https://dev.mysql.com/doc/refman/5.6/en/sql-compound-statements.html
CREATE[DEFINER = user]PROCEDURE sp_name ([proc_parameter[,...]])[characteristic ...] routine_body-- proc_parameter参数部分,可以如下书写:[ IN | OUT | INOUT ] param_name type-- type类型可以是MySQL支持的所有类型-- routine_body(程序体)部分,可以书写合法的SQL语句 BEGIN ... END
例如:
-- 声明结束符。因为MySQL默认使用‘;’作为结束符,而在存储过程中,会使用‘;’作为一段语句的结束,导致‘;’使用冲突
DELIMITER $$CREATE-- test为库明PROCEDURE test.`hello_procedure`()BEGINSELECT 'hello_procedure';END$$DELIMITER ;CALL hello_procedure();
2、变量及赋值
2.1、局部变量
用户自定义,在begin/end块中有效
语法:
声明变量 declare var_name type [default var_value];
举例:declare nickname varchar(32);
-- set赋值
DELIMITER $$
CREATE PROCEDURE test.sp_var01()
BEGINDECLARE nickname VARCHAR(32) DEFAULT 'unkown';SET nickname = 'ZS';SELECT nickname;
END$$
DELIMITER ;
-- into赋值
DELIMITER $$
CREATE PROCEDURE test.sp_var_into()
BEGINDECLARE emp_name VARCHAR(32) DEFAULT 'unkown' ;DECLARE emp_no INT DEFAULT 0;SELECT emp_no INTO emp_name ;SELECT emp_no,emp_name;
END$$
DELIMITER ;
CALL sp_var_into();
2.2、用户变量
用户自定义,当前会话(连接)有效。
语法:
@var_name
不需要提前声明,使用即声明
DELIMITER $$
CREATE PROCEDURE test.sp_var02()
BEGINSET @nickname = 'zk';
END$$
DELIMITER ;
CALL sp_var02() ;
SELECT @nickname;
2.3、全局变量:
由系统提供,整个mysql服务器有效
语法:
@@global.var_name
举例
– 查看全局变量中变量名有char的记录
show global variables like '%char%';
– 查看全局变量character_set_client的值
select @@global.character_set_client;
3、出参和入参
– 语法 参数如果是varchar 要写大小
in | out | inout param_name type
举例
DROP PROCEDURE IF EXISTS `sp_param01`;DELIMITER $$
CREATE PROCEDURE sp_param01(IN age INT)
BEGINSET @user_age = age;
END$$
DELIMITER ;
CALL sp_param01(10);
SELECT @user_age;
-- OUT类型,只负责输出!
-- 如果查询的是表,且表中列明和参数名相同,那么就换参数或者给列起别名
DELIMITER $$CREATE PROCEDURE sp_param02(OUT dept_no INT(11))
BEGINSET dept_no = 10;
END$$
DELIMITER ;-- 测试
SET @dept_no = 100;
CALL sp_param02(@dept_no);
SELECT @dept_no;
-- INOUT类型
DELIMITER $$
CREATE PROCEDURE sp_param03(INOUT user_name VARCHAR(64))
BEGINSET user_name = CONCAT('hello' ,user_name);
END$$
DELIMITER ;SET @user_name = '小明';
CALL sp_param03(@user_name);
SELECT @user_name;
4、流程控制
官网说明
https://dev.mysql.com/doc/refman/5.6/en/flow-control-statements.html
4.1、判断
4.1.1、IF
– 语法
IF search_condition THEN statement_list[ELSEIF search_condition THEN statement_list] ...[ELSE statement_list]
END IF
例子
DELIMITER $$
CREATE PROCEDURE sp_hire_if()
BEGINDECLARE result1 VARCHAR(32);DECLARE result2 VARCHAR(32);IF EXISTS(SELECT 1) -- 是否存在THEN SET result1 = 'EXISTS';END IF;IF result2 <> '' -- 判断相等THEN SET result2 = 'cond1';ELSE SET result2 = 'cond2';END IF;SELECT result1;SELECT result2;
END$$
DELIMITER ;CALL sp_hire_if();
4.1.2、CASE
此语法是不仅可以用在存储过程,查询语句也可以用!
– 语法一(类比java的switch):
CASE case_valueWHEN when_value THEN statement_list[WHEN when_value THEN statement_list] ...[ELSE statement_list]
END CASE
– 语法二:
CASEWHEN search_condition THEN statement_list[WHEN search_condition THEN statement_list] ...[ELSE statement_list]
END CASE
例子
– 需求:入职年限年龄<=38是新手 >38并 <=40老员工 >40元老
DELIMITER $$
CREATE PROCEDURE sp_hire_case()
BEGINDECLARE result VARCHAR(32);DECLARE message VARCHAR(64);CASEWHEN TIMESTAMPDIFF(YEAR,'2001-01-01',NOW()) > 40 THEN SET result = '元老';SET message = '老爷爷';WHEN TIMESTAMPDIFF(YEAR,'2001-01-01',NOW()) > 38THEN SET result = '老员工';SET message = '油腻中年人';ELSE SET result = '新手';SET message = '萌新';END CASE;SELECT result;
END$$
DELIMITER ;
CALL sp_hire_case();
4.2、循环
4.2.1、LOOP
需要说明,loop是死循环,需要手动退出循环,我们可以使用leave来退出。
可以把leave看成我们java中的break;与之对应的,就有iterate(继续循环)——类比java的continue
– 语法
[begin_label:] LOOPstatement_list
END LOOP [end_label]
例子
-- 循环打印1到10
-- leave控制循环的退出
DELIMITER $$
CREATEPROCEDURE sp_flow_loop01()BEGINDECLARE c_index INT DEFAULT 1;DECLARE result_Str VARCHAR(256) DEFAULT '1';cnt:LOOPIF c_index >=10THEN LEAVE cnt; -- 退出END IF;SET c_index = c_index+1;SET result_str = CONCAT(result_str,',',c_index);END LOOP cnt;SELECT result_str;END$$
DELIMITER ;CALL sp_flow_loop();
-- iterate + leave控制循环
DELIMITER $$
CREATE PROCEDURE sp_flow_loop02()
BEGINDECLARE c_index INT DEFAULT 1;DECLARE result_str VARCHAR(256) DEFAULT '1';cnt:LOOPSET c_index = c_index + 1;SET result_str = CONCAT(result_str,',',c_index);IF c_index < 10 THEN ITERATE cnt; END IF;-- 当c_index < 10为false时执行LEAVE cnt;END LOOP cnt;SELECT result_str;END$$CALL sp_flow_loop02();
4.2.2、REPEAT
语法
[begin_label:] REPEATstatement_list
UNTIL search_condition -- 直到…为止,才退出循环
END REPEAT [end_label]
例子
– 循环打印1到10
DELIMITER $$
CREATE PROCEDURE sp_flow_repeat()
BEGINDECLARE c_index INT DEFAULT 1;-- 收集结果字符串DECLARE result_str VARCHAR(256) DEFAULT '1';count_lab:REPEATSET c_index = c_index + 1;SET result_str = CONCAT(result_str,',',c_index);UNTIL c_index >= 10END REPEAT count_lab;SELECT result_str;
END$$CALL sp_flow_repeat();
4.2.3、WHILE
类比java的while(){}
语法
[begin_label:] WHILE search_condition DOstatement_list
END WHILE [end_label]
-- 循环打印1到10
DELIMITER $$
CREATE PROCEDURE sp_flow_while()
BEGINDECLARE c_index INT DEFAULT 1;-- 收集结果字符串DECLARE result_str VARCHAR(256) DEFAULT '1';WHILE c_index < 10 DOSET c_index = c_index + 1;SET result_str = CONCAT(result_str,',',c_index);END WHILE;SELECT result_str;
END$$
CALL sp_flow_while();
4.3、游标和HANDLER
用游标得到某一个结果集,逐行处理数据。
类比jdbc的ResultSet
特别注意:
在语法中,变量声明、游标声明、handler声明是必须按照先后顺序书写的,否则创建存储过程出错。
-- 声明语法
DECLARE cursor_name CURSOR FOR select_statement
-- 打开语法
OPEN cursor_name
-- 取值语法
FETCH cursor_name INTO var_name [, var_name] ...
-- 关闭语法
CLOSE cursor_name
例子
CREATE TABLE `dept` (`deptno` INT(11) NOT NULL COMMENT '部门编号',`dname` VARCHAR(32) NULL COMMENT '部门名称' COLLATE 'utf8_general_ci',`loc` VARCHAR(64) NULL COMMENT '部门地址' COLLATE 'utf8_general_ci',PRIMARY KEY (`deptno`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
CREATE TABLE `emp` (`empno` INT(11) NOT NULL COMMENT '员工编号',`ename` VARCHAR(32) NULL COMMENT '员工姓名' COLLATE 'utf8_general_ci',`job` VARCHAR(10) NULL COMMENT '职位' COLLATE 'utf8_general_ci',`mgr` INT(11) NULL COMMENT '上级编号',`hiredate` DATE NOT NULL COMMENT '入职时间',`sal` DECIMAL(7,2) NOT NULL DEFAULT '0.00' COMMENT '薪资',`comm` DECIMAL(7,2) NULL COMMENT '年终奖金',`deptno` INT(11) NOT NULL COMMENT '部门编号',PRIMARY KEY (`empno`) USING BTREE,INDEX `FK_emp_dept` (`deptno`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
-- 按照部门名称查询员工,通过select查看员工的编号、姓名、薪资。(注意,此处仅仅演示游标用法)
DELIMITER $$
CREATE PROCEDURE sp_cursor01(IN dept_name VARCHAR(32))
BEGINDECLARE e_no INT;DECLARE e_name VARCHAR(32);DECLARE e_sal DECIMAL(7,2);DECLARE lp_flag BOOLEAN DEFAULT TRUE;DECLARE emp_cursor CURSOR FOR SELECT e.empno,e.ename,e.salFROM emp e,dept dWHERE e.deptno = d.deptno AND d.dname = dept_name;-- handler 处理游标到最后时的行为DECLARE CONTINUE HANDLER FOR NOT FOUND SET lp_flag = FALSE;OPEN emp_cursor;emp_loop:LOOPFETCH emp_cursor INTO e_no,e_name,e_sal;IF lp_flag THENSELECT e_no,e_name,e_sal;ELSELEAVE emp_loop;END IF;END LOOP emp_loop;SET @end_falg = 'exit_flag';CLOSE emp_cursor;
END$$CALL sp_cursor01('RESEARCH');
5、应用
5.1、临时表
DELIMITER $$
CREATE PROCEDURE sp_create_table02(IN dept_name VARCHAR(32))
BEGINDECLARE emp_no INT;DECLARE emp_name VARCHAR(32);DECLARE emp_sal DECIMAL(7,2);DECLARE exit_flag INT DEFAULT 0;DECLARE emp_cursor CURSOR FORSELECT e.empno,e.ename,e.salFROM emp e INNER JOIN dept d ON e.deptno = d.deptno WHERE d.dname = dept_name;DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_flag = 1;-- 创建临时表收集数据CREATE TEMPORARY TABLE `temp_table_emp` (`empno` INT(11) NOT NULL COMMENT '员工编号',`ename` VARCHAR(32) NULL COMMENT '员工姓名' COLLATE 'utf8_general_ci',`sal` DECIMAL(7,2) NOT NULL DEFAULT '0.00' COMMENT '薪资',PRIMARY KEY (`empno`) USING BTREE)COLLATE='utf8_general_ci'ENGINE=INNODB; OPEN emp_cursor;c_loop:LOOPFETCH emp_cursor INTO emp_no,emp_name,emp_sal;IF exit_flag != 1 THENINSERT INTO temp_table_emp VALUES(emp_no,emp_name,emp_sal); ELSELEAVE c_loop;END IF;END LOOP c_loop;SELECT * FROM temp_table_emp;SELECT @sex_res; -- 仅仅是看一下会不会执行到CLOSE emp_cursor;END$$CALL sp_create_table02('RESEARCH');
5.2、可以在select语句中写case
https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html
SELECT CASE WHEN 1>0 THEN 'true' ELSE 'false' END;
5.3、执行sql字符串
https://dev.mysql.com/doc/refman/5.7/en/sql-prepared-statements.html
语法
PREPARE sql_stmt FROM var_sql_str;
EXECUTE sql_stmt;
DEALLOCATE PREPARE sql_stmt;
例子
DELIMITER $$CREATEPROCEDURE sp_prepare()BEGINSET @var_sql_str = 'select 1 into @result'; -- 用户变量直接使用不需要声明PREPARE sql_stmt FROM @var_sql_str;EXECUTE sql_stmt;DEALLOCATE PREPARE sql_stmt;END$$DELIMITER ;CALL sp_prepare();
SELECT @result;
MySQL存储过程语法相关推荐
- mysql的存储过程正负数的变化_《转》mysql存储过程语法及范例
<转>mysql存储过程语法及实例 存储过程如同一门程序设计语言,同样包含了数据类型.流程控制.输入和输出和它自己的函数库. --------------------基本语法------- ...
- mysql存储过程语法及实例
存储过程如同一门程序设计语言,同样包含了数据类型.流程控制.输入和输出和它自己的函数库. --------------------基本语法-------------------- 一.创建存储过程 c ...
- mysql存储过程语法 if_mysql存储过程语法 if
MySql存储过程 MySQL 存储过程是从 MySQL 5.0 开始增加的新功能.存储过程的优点有一箩筐.不过最主要的还是执行效率和SQL 代码封装.特别是 SQL 代码封装功能,如果没有存储过程, ...
- Mysql存储过程语法讲解,以及如何用Java调用!
存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的-种数据库对象. 存储过程是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中,用户可通过指定存储过 ...
- mysql存储过程语法错误1064_mysql,dos下执行SQL语句创建存储过程出错ERROR 1064 (42000):...
update1.sql的内容为 DROP PROCEDURE IF EXISTS pcName; CREATE PROCEDURE pcName() BEGIN select 'a'; END; do ...
- mysql存储过程语法大全
http://dev.mysql.com/doc/refman/5.1/zh/stored-procedures.html#flow-control-constructs 第20章:存储程序和函数 目 ...
- mysql存储过程语法和游标的语法_MySQL游标存储过程-语法点滴
CREATE PROCEDURE my_proc() BEGIN -- 需要定义接收游标数据的变量 DECLARE sname VARCHAR(100); DECLARE cattype VARCHA ...
- mysql 存储过程 is_Mysql存储过程语法问题...
小弟对Mysql存储过程语法不太熟悉,以下存储过程在调整过后执行仍不成功,求各位大侠指点指点.. create procedure prc_AddChannel ( id int, iname var ...
- mysql中leave和_MySQL数据库之Mysql存储过程使用LEAVE实现MSSQL存储过程中return语法
本文主要向大家介绍了MySQL数据库之Mysql存储过程使用LEAVE实现MSSQL存储过程中return语法 ,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助. DELIMITER ...
最新文章
- 要学会Python爬虫都需要什么基础呢?
- 定制kali linux
- 5-(基础入门篇)学会刷Wi-Fi模块固件(刷LUA版本固件)
- 网站服务器怎么用手机登录不了怎么办,怎么打不开服务器列表了?
- 50个linux初学者必须掌握的命令
- C++中的string
- (HDU)1157 -- Who's in the Middle(哪个居中)
- ProxyToken:微软 Exchange 服务器中的认证绕过新漏洞,可窃取用户邮件
- Linux ALSA音频子系统二
- js限制input输入
- CentOS更改主机名
- SpringBoot中的定时任务和异步任务
- python图像风格迁移教程_【人工智能】python图像风格迁移,来欣赏梵高风格的石原里美吧!...
- FPGA模拟PS/2键盘
- 数据分析思维:分析方法和业务知识
- python均线斜率_一根20日均线闯天下? ——量化回测“压箱底指标”
- 多多情报通:拼多多推广哪个效果好?有什么推广技巧?
- php ic卡,IC卡的数据结构认识
- (不打广告)推荐这款永久免费内网穿透软件-神卓互联
- 学校学生学籍的计算机管理属于什么领域,浅谈计算机管理学生学籍信息系统的重要性...
热门文章
- deepin efi 启动u盘_【2017.12.16】启动U盘简单手动制作BIOS+UEFI的syslinux/grub/boomgr/grub2互转...
- 2019数据安装勾选_停机前未勾选完的发票,升完级后这样操作!后附常见问题解答...
- 易语言保存txt记录至c盘,易语言超级列表框导入TXT文本后修改保存和新增记录...
- macOS Catalina 10.15.7(19H2)原版CDR镜像
- Origin如何进行单段和多段的线性拟合
- Android 12.0 Launcher3 去掉Hotseat功能
- 将一个文本打乱顺序的简单方法
- 逻辑回归原理以及推导
- 无盘服务器内存回写速度,解决无盘回写压力方法杂谈!
- linux 面试答题