Mysql存储过程编写说明

1 背景

因为构造数据有点复杂,为了方便和快速的生成数据,根据业务规则,通过Mysql存储过程对数据库数据进行处理,本次记录主要说明涉及的语法格式注意事项和函数的使用。

2 脚本和说明

2.1 脚本

DELIMITER //
	DROP PROCEDURE IF EXISTS `eculist` //
	CREATE DEFINER=CURRENT_USER PROCEDURE `ecuList`(IN vininfo varchar(17),OUT result VARCHAR(1000))
		BEGIN
			DECLARE ecu_code VARCHAR(10);
			declare diagnosticPartNumber VARCHAR(10); -- 存放诊断零件号前10位
			declare diagnosticPartNumberVersion VARCHAR(2);  -- 存放诊断零件号后2位,即版本号的ASCII值
			declare softNumber VARCHAR(2); -- 软件数量,十六进制
			declare softList VARCHAR(100); -- 软件序列号列表
			DECLARE done INT DEFAULT 0;
			
			DECLARE ecu_codes CURSOR FOR 
			select t.node_address from vehicle_portrait_hardware_info t WHERE t.vin=vininfo;

			DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;  
			set result = '执行结果';

			OPEN ecu_codes;
			ecu_codes_loop: LOOP
						
				FETCH ecu_codes INTO ecu_code; #要和声明的变量对应上不能少写,done除外	
				
						IF done=1 THEN LEAVE ecu_codes_loop;	 #如果done的值为1,即遍历结束,结束循环                						
						END IF;#注意 if语句需要添加END IF结束IF
						
						-- 获取诊断零件号,前10位
						select SUBSTRING(t.diagnostic_part_number,1,10) into diagnosticPartNumber from table1 t where t.vin=vininfo and t.node_address =ecu_code;
						-- 获取诊断零件号,后2位,即版本号,获取后需转为ACSII编码
						select ASCII(SUBSTRING(t.diagnostic_part_number,11)) into diagnosticPartNumberVersion from table1 t where t.vin=vininfo and t.node_address =ecu_code;

						-- 获取软件零件号,跟硬件号有关,一个ECU一个硬件号,可以挂接多个软件号
						select LPAD(count(*),2,0) into softNumber from table2 t where t.vin=vininfo and t.node_address =ecu_code and t.hardware_part_number=partNumber and t.hardware_part_version=partVersion;
						select GROUP_CONCAT(CONCAT(t.part_number,'2020',ASCII(t.part_version)) SEPARATOR '') into softList from table2 t where t.vin=vininfo and t.node_address =ecu_code and t.hardware_part_number=partNumber and t.hardware_part_version=partVersion; --多列数据合并到一行
					
					--将结果追加到输出变量中
					select CONCAT(result,char(10),'"',ecu_code,'0E8062ED20','F1A0',diagnosticPartNumber,'2020',diagnosticPartNumberVersion,'F1AE',softNumber,softList,'",') INTO result;
		
			END LOOP ecu_codes_loop;
			CLOSE ecu_codes;

	END
	//
DELIMITER ;

调用

CALL ecuList('VINCODE1234000000',@result);
select @result;

2.2 说明

DELIMITER // 和 DELIMITER ;

MySQL默认以";“为分隔符,如果没有声明分割符,则编译器会把存储过程当成SQL语句进行处理,因此编译过程会报错,所以要事先用“DELIMITER //”声明当前段分隔符,让编译器把两个”//"之间的内容当做存储过程的代码,不会执行这些代码;“DELIMITER ;”的意为把分隔符还原

DROP PROCEDURE IF EXISTS `eculist’

因为Mysql在创建存储过程中没有Oracle数据库create or replace 语法(Mysql在创建VIEW时可以使用create or replace 语法),为了支持脚本的重复执行,可以在存储过程脚本中添加 如果存在就删除的判断

CREATE DEFINER=CURRENT_USER PROCEDURE ‘eculist’ (IN vininfo varchar(17),OUT result VARCHAR(1000))

  • DEFINER = user 选项,即指定此对象的定义者是谁,若不显式指定,则创建此对象的用户就是定义者。
  • 对于视图、函数及存储过程还可以指定 SQL SECURITY 属性,其值可以为 DEFINER(定义者) 或 INVOKER(调用者),表示在执行过程中,使用谁的权限来执行。DEFINER 表示按定义者拥有的权限来执行,INVOKER表示用调用者的权限来执行
  • 默认情况下,SQL SECURITY 属性为 DEFINER 。其值为 DEFINER 时,数据库中必须存在 DEFINER 指定的定义者用户,并且该定义者用户拥有对应的操作权限及引用的相关对象的权限,执行者只需拥有调用权限就能成功执行。当 SQL SECURITY 属性为 INVOKER 时,则需要执行者有调用权限并且有引用的相关对象的权限,才能成功执行。
  • 存储过程根据需要可能会有输入、输出、输入输出参数,如果有多个参数用","分割开。MySQL存储过程的参数用在存储过程的定义,共有三种参数类型:IN,OUT,INOUT
    IN参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值
    OUT:该值可在存储过程内部被改变,并可返回
    INOUT:调用时指定,并且可被改变和返回

BEGIN与END

过程体的开始与结束使用BEGIN与END进行标识。

DECLARE ecu_code VARCHAR(10);
DECLARE done INT DEFAULT 0;

  • 变量声明,语法:DECLARE 变量名1[,变量名2…] 数据类型 [默认值];

  • 变量赋值,语法:SET 变量名 = 变量值 [,变量名= 变量值 …]

  • Oracle提供了%TYPE定义方式,使一个变量的数据类型与另一个已经定义了的变量(尤其是表的某一列)的数据类型相一致,在Mysql中没有%TYPE定义方式

游标部分

游标声明

DECLARE ecu_codes CURSOR FOR 
			select t.node_address from vehicle_portrait_hardware_info t WHERE t.vin=vininfo;

每个游标必须使用不同的declare continue handler for not found set done=1来控制游标的结束。

declare continue handler for not found set done=1

打开游标和关闭游标

OPEN ecu_codes;
CLOSE ecu_codes;

如果游标到了末尾,结束LOOP循环,不写这句话,数据会多一条

IF done=1 THEN LEAVE ecu_codes_loop;	

ecu_codes_loop: LOOP;
END LOOP ecu_codes_loop;

开始和结束循环,ecu_codes_loop为lableName可以不写,即

LOOP;
END LOOP;

select GROUP_CONCAT(CONCAT(t.part_number,‘2020’,ASCII(t.part_version))
SEPARATOR ‘’) into softList from table2 t …;

  • GROUP_CONCAT,用通俗的话讲,就是把分组之后,没有参与分组的这一列的数据拼接起来,本来是多条数据,变成了一条
  • group_concat([distinct] 字段名 [order by 排序字段 asc/desc] [separator ‘分隔符’])

select CONCAT(result,char(10),‘"’,ecu_code,diagnosticPartNumber,‘2020’,diagnosticPartNumberVersion,softNumber,softList,‘",’)
INTO result;

  • mysql的字符串拼接,不能用‘+’号,必须用concat函数
  • char(10) 为换行
  • ‘"’ 输出引号
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值