MYSQL存储过程:批量更新、插入数据、游标 - Go语言中文社区

MYSQL存储过程:批量更新、插入数据、游标



地区等级的信息储存在jsjh_district表。

要更新jsjh_goods_district表的district_level地区信息

通过jsjh_goods_district表中district_idjsjh_district表的id字段关联,查询出所有符合条件的记录指定字段放入游标,

然后打开游标遍历查询的记录的对应字段分别放入定义的变量中,然后将jsjh_district表的地区等级更新到jsjh_goods_district表中


复制代码
DELIMITER $$ 
DROP PROCEDURE IF EXISTS update_district_level $$
CREATE PROCEDURE update_district_level()
BEGIN
DECLARE row_id INT;#定义变量ID
DECLARE row_district_id INT;#定义变量地区ID
DECLARE row_level INT;#定义变量地区等级
DECLARE done INT;
-- 定义游标
DECLARE rs_cursor CURSOR FOR
SELECT main.id,main.district_id,d.`level` FROM jsjh_goods_district main LEFT JOIN jsjh_district d ON d.id=main.district_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN rs_cursor; 
cursor_loop:LOOP
FETCH rs_cursor INTO row_id,row_district_id,row_level; -- 取数据
IF done=1 THEN
leave cursor_loop;
END IF;
-- 更新表
UPDATE jsjh_goods_district SET district_level=row_level WHERE id=row_id;
END LOOP cursor_loop;
CLOSE rs_cursor;
END$$
DELIMITER ;
复制代码

 执行存储过程

CALL update_district_level();

/* Affected rows: 0  已找到记录: 0  警告: 0  持续时间 1 query: 1.014 sec. */

执行时间1秒多


使用存储过程批量插数据

创建测试表
DROP TABLE IF EXISTS test.test;
CREATE TABLE test.test(
id int(10) not null auto_increment,
a int(10) not null,
b int(10) not null,
c int(10) not null,
PRIMARY key (`id`)
)ENGINE INNODB DEFAULT CHARSET utf8 COMMENT '测试表';
 


#清空数据
TRUNCATE table test.test;
 
#定义存储过程
delimiter //
DROP PROCEDURE IF EXISTS insert_test_val;
##num_limit 要插入数据的数量,rand_limit 最大随机的数值
CREATE PROCEDURE insert_test_val(in num_limit int,in rand_limit int)
BEGIN
 
DECLARE i int default 1;
DECLARE a int default 1;
DECLARE b int default 1;
DECLARE c int default 1;
 
WHILE i<=num_limit do
 
set a = FLOOR(rand()*rand_limit);
set b = FLOOR(rand()*rand_limit);
set c = FLOOR(rand()*rand_limit);
INSERT into test.test values (null,a,b,c);
set i = i + 1;
 
END WHILE;
 
END
//
 
#调用存储过程
call insert_test_val(100000,10);
 


结果:..........................


MySQL 存储过程参数有三种类型:in、out、inout。它们各有什么作用和特点呢?


一、MySQL 存储过程参数(in)


MySQL 存储过程 “in” 参数:跟 C 语言的函数参数的值传递类似, MySQL 存储过程内部可能会修改此参数,但对 in 类型参数的修改,对调用者(caller)来说是不可见的(not visible)。






drop procedure if exists pr_param_in;


create procedure pr_param_in
(
   in id int -- in 类型的 MySQL 存储过程参数
)
begin
   if (id is not null) then
      set id = id + 1;
   end if;


   select id as id_inner;
end;










set @id = 10;


call pr_param_in(@id);


select @id as id_out;










mysql> call pr_param_in(@id);
+----------+
| id_inner |
+----------+
|       11 |
+----------+


mysql> select @id as id_out;
+--------+
| id_out |
+--------+
| 10     |
+--------+






可以看到:用户变量 @id 传入值为 10,执行存储过程后,在过程内部值为:11(id_inner),但外部变量值依旧为:10(id_out)。


二、MySQL 存储过程参数(out)


MySQL 存储过程 “out” 参数:从存储过程内部传值给调用者。在存储过程内部,该参数初始值为 null,无论调用者是否给存储过程参数设置值。






drop procedure if exists pr_param_out;


create procedure pr_param_out
(
   out id int
)
begin
   select id as id_inner_1;  -- id 初始值为 null


   if (id is not null) then
      set id = id + 1;


      select id as id_inner_2;
   else
      select 1 into id;
   end if;


   select id as id_inner_3;
end;










set @id = 10;


call pr_param_out(@id);


select @id as id_out;










mysql> set @id = 10;
mysql>
mysql> call pr_param_out(@id);
+------------+
| id_inner_1 |
+------------+
|       NULL |
+------------+


+------------+
| id_inner_3 |
+------------+
|          1 |
+------------+


mysql> select @id as id_out;
+--------+
| id_out |
+--------+
| 1      |
+--------+






可以看出,虽然我们设置了用户定义变量 @id 为 10,传递 @id 给存储过程后,在存储过程内部,id 的初始值总是 null(id_inner_1)。最后 id 值(id_out = 1)传回给调用者。


三、MySQL 存储过程参数(inout)


MySQL 存储过程 inout 参数跟 out 类似,都可以从存储过程内部传值给调用者。不同的是:调用者还可以通过 inout 参数传递值给存储过程。






drop procedure if exists pr_param_inout;


create procedure pr_param_inout
(
   inout id int
)
begin
   select id as id_inner_1;  -- id 值为调用者传进来的值


   if (id is not null) then
      set id = id + 1;


      select id as id_inner_2;
   else
      select 1 into id;
   end if;


   select id as id_inner_3;
end;










set @id = 10;


call pr_param_inout(@id);


select @id as id_out;










mysql> set @id = 10;


mysql>
mysql> call pr_param_inout(@id);
+------------+
| id_inner_1 |
+------------+
|         10 |
+------------+


+------------+
| id_inner_2 |
+------------+
|         11 |
+------------+


+------------+
| id_inner_3 |
+------------+
|         11 |
+------------+
mysql>
mysql> select @id as id_out;
+--------+
| id_out |
+--------+
| 11     |
+--------+






从结果可以看出:我们把 @id(10),传给存储过程后,存储过程最后又把计算结果值 11(id_inner_3)传回给调用者。 MySQL 存储过程 inout 参数的行为跟 C 语言函数中的引用传值类似。


通过以上例子:如果仅仅想把数据传给 MySQL 存储过程,那就使用“in” 类型参数;如果仅仅从 MySQL 存储过程返回值,那就使用“out” 类型参数;如果需要把数据传给 MySQL 存储过程,还要经过一些计算后再传回给我们,此时,要使用“inout” 类型参数。



存储过程基本语法说明

1 CREATE PROCEDURE(创建)
CREATE PROCEDURE存储过程名(参数列表)
BEGIN
       SQL语句代码块
END
注意:
由括号包围的参数列必须总是存在。如果没有参数,也该使用一个空参数列()。每个参数默认都是一个IN参数。要指定为其它参数,可在参数名之前使用关键词 OUT或INOUT
在mysql客户端定义存储过程的时候使用delimiter命令来把语句定界符从;变为//。
当使用delimiter命令时,你应该避免使用反斜杠(‘"’)字符,因为那是MySQL的转义字符。
如:
mysql> delimiter //
mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)
   -> BEGIN
   ->   SELECT COUNT(*) INTO param1 FROM t;
   -> END
   -> //
Query OK, 0 rows affected (0.00 sec)
1.2 ALTER PROCEDURE(修改)
ALTER PROCEDURE存储过程名SQL语句代码块
这个语句可以被用来改变一个存储程序的特征。
1.3 DROP PROCEDURE(删除)
DROP PROCEDURE IF EXISTS存储过程名
eg:DROP PROCEDURE IF EXISTS proc_employee (proc_employee存储过程名)
这个语句被用来移除一个存储程序。不能在一个存储过程中删除另一个存储过程,只能调用另一个存储过程
1.4 SHOW CREATE PROCEDURE(类似于SHOW CREATE TABLE,查看一个已存在的存储过程)
SHOW CREATE PROCEDURE存储过程名
1.5 SHOW PROCEDURE STATUS(列出所有的存储过程)
SHOW PROCEDURE STATUS
1.6 CALL语句(存储过程的调用)
CALL存储过程名(参数列表)
CALL语句调用一个先前用CREATE PROCEDURE创建的程序。
CALL语句可以用声明为OUT或的INOUT参数的参数给它的调用者传回值。
存储过程名称后面必须加括号,哪怕该存储过程没有参数传递
1.7 BEGIN ... END(复合语句)
[begin_label:]
BEGIN
   [statement_list]
END
[end_label]
存储子程序可以使用BEGIN ... END复合语句来包含多个语句。
statement_list代表一个或多个语句的列表。statement_list之内每个语句都必须用分号(;)来结尾。
复合语句可以被标记。除非begin_label存在,否则end_label不能被给出,并且如果二者都存在,他们必须是同样的。
1.8 DECLARE语句(用来声明局部变量)
DECLARE语句被用来把不同项目局域到一个子程序:局部变量
DECLARE仅被用在BEGIN ... END复合语句里,并且必须在复合语句的开头,在任何其它语句之前。
1.9 存储程序中的变量
1.1 DECLARE局部变量
DECLARE var_name[,...] type [DEFAULT value]
这个语句被用来声明局部变量。
要给变量提供一个默认值,请包含一个DEFAULT子句。
值可以被指定为一个表达式,不需要为一个常数。
如果没有DEFAULT子句,初始值为NULL。
局部变量的作用范围在它被声明的BEGIN ... END块内。
它可以被用在嵌套的块中,除了那些用相同名字声明变量的块。
1.2 变量SET语句
SET var_name = expr [, var_name = expr]
在存储程序中的SET语句是一般SET语句的扩展版本。
被参考变量可能是子程序内声明的变量,或者是全局服务器变量。
在存储程序中的SET语句作为预先存在的SET语法的一部分来实现。这允许SET a=x, b=y, ...这样的扩展语法。
其中不同的变量类型(局域声明变量及全局和集体变量)可以被混合起来。
这也允许把局部变量和一些只对系统变量有意义的选项合并起来。
1.3 SELECT ... INTO语句
SELECT col_name[,...] INTO var_name[,...] table_expr
这个SELECT语法把选定的列直接存储到变量。
因此,只有单一的行可以被取回。
SELECT id,data INTO x,y FROM test.t1 LIMIT 1;
注意,用户变量名在MySQL 5.1中是对大小写不敏感的。
重要: SQL变量名不能和列名一样。如果SELECT ... INTO这样的SQL语句包含一个对列的参考,并包含一个与列相同名字的局部变量,MySQL当前把参考解释为一个变量的名字。
1.10 MySQL存储过程参数类型(in、out、inout)
此小节内容来自:
参见地址:http://www.blogjava.net/nonels/archive/2009/04/22/233324.html
MySQL存储过程参数(in)
MySQL存储过程 “in”参数:跟 C语言的函数参数的值传递类似, MySQL存储过程内部可能会修改此参数,但对 in类型参数的修改,对调用者(caller)来说是不可见的(not visible)。
MySQL存储过程参数(out)
MySQL存储过程 “out”参数:从存储过程内部传值给调用者。在存储过程内部,该参数初始值为 null,无论调用者是否给存储过程参数设置值
MySQL存储过程参数(inout)
MySQL存储过程 inout参数跟 out类似,都可以从存储过程内部传值给调用者。不同的是:调用者还可以通过 inout参数传递值给存储过程。
总结
如果仅仅想把数据传给 MySQL存储过程,那就使用“in”类型参数;如果仅仅从 MySQL存储过程返回值,那就使用“out”类型参数;如果需要把数据传给 MySQL存储过程,还要经过一些计算后再传回给我们,此时,要使用“inout”类型参数。
1.11 例子:
1.1 创建存储过程
带(输出参数)返回值的存储过程:
--删除存储过程
DROP PROCEDURE IF EXISTS proc_employee_getCount
--创建存储过程
CREATE PROCEDURE proc_employee_getCount(out n int)
BEGIN
SELECT COUNT(*) FROM employee ;
END
--MYSQL调用存储过程
CALL proc_employee_getCount(@n);
带输入参数的存储过程:
--删除存储过程
DROP PROCEDURE IF EXISTS proc_employee_findById;
--创建存储过程
CREATE PROCEDURE proc_employee_findById(in n int)
BEGIN
SELECT * FROM employee where id=n;
END
--定义变量
SET @n=1;
--调用存储过程
CALL proc_employee_findById(@n);
操作存储过程时应注意:
1. 删除存储过程时只需要指定存储过程名即可,不带括号;
2. 创建存储过程时,不管该存储过程有无参数,都需要带括号;
3. 在使用SET定义变量时应遵循SET的语法规则;
SET @变量名=初始值;
4. 在定义存储过程参数列表时,应注意参数名与数据库中字段名区别开来,否则将出现无法预期的结果


转载自:http://www.cnblogs.com/firadio/p/5109346.html

   http://blog.sina.com.cn/s/blog_9d0b00a4010122wf.html

              http://www.blogjava.net/nonels/archive/2009/04/22/233324.html


版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/u011191463/article/details/78255076
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-06-14 17:13:48
  • 阅读 ( 740 )
  • 分类:数据库

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢