背景:
要求从
balance_0x123145d67520b4h63B9D60d7C1435bffF41aFa25 这个表没有goods_id
导出数据到
balance_25 这个表多了一个 goods_id 字段,同时还要把这个goods_id 存进去(就是上面的表名后缀,也就是goods表的id)
将表名后缀取后两位,把所有后缀相同的表数据合并到一张表,而且不能确定这种表有多少个,只能选择写个过程来处理了,
这种表名后缀是由goods表的id产生的,有多少个id就有多少这种表,所以下面这条sql查出来是一个集合
SELECT `id` FROM goods WHERE `name` IS NOT NULL;
正文:
既然说到过程和函数,就要看一下它们的区别以及我为什么要选择过程来处理而不是函数;
1. 存储函数有且只有一个返回值,而存储过程不能有返回值。2. 函数只能有输入参数,而且不能带in, 而存储过程可以有多个in,out,inout参数。3. 存储过程中的语句功能更强大,存储过程可以实现很复杂的业务逻辑,而函数有很多限制,如不能在函数中使用insert,update,delete,create等语句;存储函数只完成查询的工作,可接受输入参数并返回一个结果,也就是函数实现的功能针对性比较强。4. 存储过程可以调用存储函数。但函数不能调用存储过程。5. 存储过程一般是作为一个独立的部分来执行(call调用)。而函数可以作为查询语句的一个部分来调用.
那么到了我的需求:
1. 我不需要返回值;2. 不需要传递参数;3. 我需要执行insert、select等sql
这样只能选择写一个过程(虽然很麻烦,but I like)
#以root用户创建一个名称为`PROCEDURE_BALANCE`的存储过程CREATE DEFINER=`root`@`%` PROCEDURE `PROCEDURE_BALANCE`()BEGIN #定义判断变量 DECLARE flag varchar(50); #定义名为goods_id的游标(查询goods表name不为空的所有id,赋值给goods_id) DECLARE goods_id CURSOR FOR SELECT `id` FROM goods WHERE `name` IS NOT NULL; #循环赋初始值 DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag=NULL; #打开游标 OPEN goods_id; #游标读取下一行 FETCH goods_id INTO flag; #定义循环 WHILE (flag is not null ) DO #sql拼接,替换相关变量 PS: 拼接表名这种可以用'',但是拼接WHERE条件这种,比如 id='11',就需要三个''这种单引号,这里细心想一下就可以理解 SET @string_sql = CONCAT('INSERT INTO userbalance_',RIGHT (flag, 2),'(SELECT id,''',flag,''',userAddress,amount,freezeAccount,createdAt,updatedAt,deletedAt FROM userbalance_',flag,')'); #这个是打印每条sql,可以不要 SELECT @string_sql; #创建预处理语句 PREPARE st FROM @string_sql; #执行这个sql EXECUTE st; #释放预处理语句,(如果不释放,在存储过程结束之后,该预处理语句仍然会有效,占用数据库资源) DEALLOCATE PREPARE st; #赋值下一个游标 FETCH goods_id INTO flag; END WHILE; #关闭游标, PS:用完后必须关闭,而且必须在循环外关闭 CLOSE goods_id;END#PS:游标必须在定义处理程序之前被定义,但变量必须在定义游标之前被定义,顺序就是变量定义-游标定义-处理程序.