MySQL存储过程例子,包含事务,参数,嵌套调用,游标,循环等

MySQL存储过程例子,包含事务,参数,嵌套调用,游标,循环等

 

[c-sharp] view plaincopy
  1. drop procedure if exists pro_rep_shadow_rs;    
  2. delimiter |    
  3. ----------------------------------    
  4. -- rep_shadow_rs    
  5. -- 用来处理信息的增加,更新和删除    
  6. -- 每次只更新上次以来没有做过的数据    
  7. -- 根据不同的标志位    
  8. -- 需要一个输出的参数,    
  9. -- 如果返回为0,则调用失败,事务回滚    
  10. -- 如果返回为1,调用成功,事务提交    
  11. --    
  12. -- 测试方法    
  13. -- call pro_rep_shadow_rs(@rtn);    
  14. -- select @rtn;    
  15. ----------------------------------    
  16. create procedure pro_rep_shadow_rs(out rtn int)    
  17. begin    
  18.     -- 声明变量,所有的声明必须在非声明的语句前面    
  19.     declare iLast_rep_sync_id int default -1;    
  20.     declare iMax_rep_sync_id int default -1;    
  21.     -- 如果出现异常,或自动处理并rollback,但不再通知调用方了    
  22.     -- 如果希望应用获得异常,需要将下面这一句,以及启动事务和提交事务的语句全部去掉    
  23.     declare exit handler for sqlexception rollback;    
  24.     -- 查找上一次的    
  25.     select eid into iLast_rep_sync_id from rep_de_proc_log where tbl='rep_shadow_rs';    
  26.     -- 如果不存在,则增加一行    
  27.     if iLast_rep_sync_id=-1 then    
  28.       insert into rep_de_proc_log(rid,eid,tbl) values(0,0,'rep_shadow_rs');    
  29.       set iLast_rep_sync_id = 0;    
  30.     end if;    
  31.         
  32.     -- 下一个数字    
  33.     set iLast_rep_sync_id=iLast_rep_sync_id+1;    
  34.     -- 设置默认的返回值为0:失败    
  35.     set rtn=0;    
  36.         
  37.     -- 启动事务    
  38.     start transaction;    
  39.     -- 查找最大编号    
  40.     select max(rep_sync_id) into iMax_rep_sync_id from rep_shadow_rs;    
  41.     -- 有新数据    
  42.     if iMax_rep_sync_id>=iLast_rep_sync_id then    
  43.         -- 调用    
  44.         call pro_rep_shadow_rs_do(iLast_rep_sync_id,iMax_rep_sync_id);    
  45.         -- 更新日志    
  46.         update rep_de_proc_log set rid=iLast_rep_sync_id,eid=iMax_rep_sync_id where tbl='rep_shadow_rs';    
  47.     end if;    
  48.         
  49.     -- 运行没有异常,提交事务    
  50.     commit;    
  51.     -- 设置返回值为1  
  52.     set rtn=1;    
  53. end;    
  54. |    
  55. delimiter ;    
  56. drop procedure if exists pro_rep_shadow_rs_do;    
  57. delimiter |    
  58. ---------------------------------    
  59. -- 处理指定编号范围内的数据    
  60. -- 需要输入2个参数    
  61. -- last_rep_sync_id 是编号的最小值    
  62. -- max_rep_sync_id 是编号的最大值    
  63. -- 无返回值    
  64. ---------------------------------    
  65. create procedure pro_rep_shadow_rs_do(last_rep_sync_id int, max_rep_sync_id int)    
  66. begin    
  67.     declare iRep_operationtype varchar(1);    
  68.     declare iRep_status varchar(1);    
  69.     declare iRep_Sync_id int;    
  70.     declare iId int;    
  71.     -- 这个用于处理游标到达最后一行的情况    
  72.     declare stop int default 0;    
  73.     -- 声明游标    
  74.     declare cur cursor for select id,Rep_operationtype,iRep_status,rep_sync_id from rep_shadow_rs where rep_sync_id between last_rep_sync_id and max_rep_sync_id;    
  75.     -- 声明游标的异常处理,设置一个终止标记    
  76.     declare CONTINUE HANDLER FOR SQLSTATE '02000' SET stop=1;    
  77.         
  78.     -- 打开游标    
  79.     open cur;    
  80.         
  81.     -- 读取一行数据到变量    
  82.     fetch cur into iId,iRep_operationtype,iRep_status,iRep_Sync_id;    
  83.     -- 这个就是判断是否游标已经到达了最后    
  84.     while stop <> 1 do  
  85.         -- 各种判断    
  86.         if iRep_operationtype='I' then    
  87.             insert into rs0811 (id,fnbm) select id,fnbm from rep_shadow_rs where rep_sync_id=iRep_sync_id;    
  88.         elseif iRep_operationtype='U' then    
  89.         begin    
  90.             if iRep_status='A' then    
  91.                 insert into rs0811 (id,fnbm) select id,fnbm from rep_shadow_rs where rep_sync_id=iRep_sync_id;    
  92.             elseif iRep_status='B' then    
  93.                 delete from rs0811 where id=iId;    
  94.             end if;    
  95.         end;    
  96.         elseif iRep_operationtype='D' then    
  97.             delete from rs0811 where id=iId;    
  98.         end if;     
  99.             
  100.         -- 读取下一行的数据     
  101.         fetch cur into iId,iRep_operationtype,iRep_status,iRep_Sync_id;    
  102.     end while; -- 循环结束    
  103.     close cur; -- 关闭游标    
  104. end;    
  105. use testprocedure;  
  106. delimiter //  
  107.   
  108. create procedure simpleproce1 (out par1 int)  
  109. begin  
  110. select count(*) into par1 from proce;  
  111. end  
  112. //  
  113. delimiter ;  
  114. call simpleproce1(@a);  
  115. select @a;  
  116. #<2>,每次只有单一的行可以被取回select id,name into par1,par2 from proce LIMIT 1;中的LIMIT 1;  
  117. use testprocedure;  
  118. delimiter //  
  119. DROP procedure IF EXISTS simpleproce2  
  120. create procedure simpleproce2 (out par1 int,out par2 char(30))  
  121. begin  
  122. select id,name into par1,par2 from proce LIMIT 1;  
  123. end  
  124. //  
  125. delimiter ;  
  126. call simpleproce2(@a,@b);  
  127. select @a,@b;  
  128.  
  129. ## *********second test,function************  
  130. #<3>  
  131. delimiter //  
  132. DROP FUNCTION IF EXISTS hello  
  133. //  
  134. create function hello(s char(20)) returns char(50)  
  135. return concat('Hello, ',s,'!');  
  136. //  
  137. delimiter ;  
  138. select hello('world');  
  139. show create function testprocedure.helloG  
  140. #它返回子程序的特征,如数据库,名字,类型,创建者及创建和修改日期  
  141. show function status like 'hello'G  
  142. #<4>  
  143. #注意name不能和字段名相同  
  144. delimiter //  
  145. DROP procedure IF EXISTS test //  
  146. CREATE PROCEDURE test ()  
  147. BEGIN  
  148.     DECLARE name VARCHAR(5) DEFAULT 'bob';  
  149.     DECLARE newname VARCHAR(5);  
  150.     DECLARE xid INT;  
  151.      
  152.     SELECT name,id INTO newname,xid  
  153.       FROM proce WHERE name = name;  
  154.     SELECT newname;  
  155. END;  
  156. //  
  157. call test1() //  
  158. #***  
  159. delimiter //  
  160. DROP procedure IF EXISTS test2 //  
  161. CREATE PROCEDURE test2 ()  
  162. BEGIN  
  163.      
  164.     DECLARE newname VARCHAR(5);  
  165.     DECLARE xid INT;  
  166.      
  167.     SELECT name,id INTO newname,xid  
  168.       FROM proce limit 1;  
  169.     SELECT newname,xid;  
  170. END;  
  171. //  
  172. call test2() //  
  173. #<5>  
  174. use testprocedure;  
  175. CREATE PROCEDURE p1 () SELECT * FROM proce;  
  176. call p1();  
  177. #<6>注意此处的handler是设置SQLSTATE值,SQLWARNING是对所有以01开头的SQLSTATE代码的速记  
  178. #NOT FOUND是对所有以02开头的SQLSTATE代码的速记  
  179. #SQLEXCEPTION是对所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE代码的速记  
  180. #DECLARE CONTINUE HANDLER声明CONTINUE异常处理  
  181. #事实上这里的23000SQLSTATE是更常用的,当外键约束出错或主键约束出错就被调用了。  
  182. #当没有发生该23000异常时, select @x2的值将是null,而不是1,  
  183. #并且后面的第2个语句执行时将会报主键约束错误,此时@x2=1,@x=4,虽然第2句有了异常,但是后面的语句继续执行  
  184. #保存到数据的数据是3,test3和5,test5  
  185. use testprocedure;  
  186. delimiter //  
  187. DROP procedure IF EXISTS handlerdemo  
  188. //  
  189. create procedure handlerdemo()  
  190. begin  
  191. declare continue handler for sqlstate '23000' set @x2=1;  
  192. set @x=1;  
  193. insert into proce values(3,'test3');  
  194. set @x=2;  
  195. insert into proce values(3,'test4');  
  196. set @x=3;  
  197. insert into proce values(5,'test5');  
  198. set @x=4;  
  199. end;  
  200. //  
  201. call handlerdemo()//  
  202. select @x //  
  203. select @x2 //  
  204. ## ************光标****************  
  205. #<7>光标必须在声明处理程序之前被声明,并且变量和条件必须在声明光标或处理程序之前被声明  
  206. #在这里先声明变量a,b,c,后声明cursor  
  207. create procedure curdemo()  
  208. begin  
  209. declare done int default 0;  
  210. declare a char(16);  
  211. declare b,c int;  
  212. declare cur1 cursor for select id,name from proce;  
  213. declare cur2 cursor for select id from proce2;  
  214. declare continue handler for sqlstate '02000' set done=1;  
  215. open cur1;  
  216. open cur2;  
  217. repeat  
  218. fetch cur1 into b,a;  
  219. fetch cur2 into c;  
  220. if not done then  
  221.    if b<c then  
  222.      insert into proce3 values(b,a);  
  223.    else  
  224.      insert into proce3 values(c,a);  
  225.    end if;  
  226. end if;  
  227. until done end repeat;  
  228. close cur1;  
  229. close cur2;  
  230. end  
  231. ## **************** Case *******************  
  232. #<8>when ... then ;case ... end case;  
  233. delimiter //  
  234. DROP procedure IF EXISTS p13  
  235. //  
  236. create procedure p13(in par1 int)  
  237. begin  
  238. declare var1 int;  
  239. set var1=par1+1;  
  240. case var1  
  241. when 0 then insert into casetest values(17);  
  242. when 1 then insert into casetest values(18);  
  243. else insert into casetest values(19);  
  244. end case;  
  245. end;  
  246. //  
  247. call p13(-1)//  
  248. call p13(0)//  
  249. call p13(1)//  
  250. call p13(null)//  
  251.  
  252. ## **************** while ****************  
  253. #<9>while ... do ... end while;为了防止null的错误,set v=0是必须的  
  254. delimiter //  
  255. DROP procedure IF EXISTS p14  
  256. //  
  257. create procedure p14()  
  258. begin  
  259. declare v int;  
  260. set v=0;  
  261. while v < 5 do  
  262.       insert into casetest values (v);  
  263.       set v=v+1;  
  264. end while;  
  265. end;//  
  266. call p14()//  
  267. ## ***************** repeat *****************  
  268. #<10>repeat ...until ... end repeat; 是执行后检查(until v>=5),而while是执行前检查(while v<5)  
  269. delimiter //  
  270. DROP procedure IF EXISTS p15  
  271. //  
  272. create procedure p15()  
  273. begin  
  274. declare v int;  
  275. set v=0;  
  276. repeat  
  277.     insert into casetest values(v);  
  278.     set v=v+1;  
  279. until v >=5  
  280. end repeat;  
  281. end;  
  282. //  
  283. call p15()//  
  284. ## ***************** loops *****************  
  285. #<11> loop 和while一样不需要初始条件,同时和repeat一样不需要结束条件  
  286. #      loop_label: loop  
  287. #      ...  
  288. #       if .. then  
  289. #       leave loop_label  
  290. #       end if  
  291. #      end loop  
  292. delimiter //  
  293. DROP procedure IF EXISTS p16  
  294. //  
  295. create procedure p16()  
  296. begin  
  297. declare v int;  
  298. set v=0;  
  299. loop_label: loop  
  300.     insert into casetest values(v);  
  301.     set v=v+1;  
  302.     if v >=5 then  
  303.       leave loop_label;  
  304.     end if;  
  305. end loop;  
  306. end;//  
  307. call p16()//  
  308. ## ***************** Labels *****************  
  309. # <12>labels标号; 注意此处的until 0=0后面没有分号“;”  
  310. delimiter //  
  311. DROP procedure IF EXISTS p17//  
  312. create procedure p17()  
  313. label_1:begin  
  314. label_2:while 0=1 do leave label_2; end while;  
  315. label_3:repeat leave label_3;until 0=0 end repeat;  
  316. label_4:loop leave label_4; end loop;  
  317. end;//  
  318. call p17()//  
  319. #<13>labels 标号结束符;  
  320. delimiter //  
  321. DROP procedure IF EXISTS p18//  
  322. create procedure p18()  
  323. label_1:begin  
  324. label_2:while 0=1 do leave label_2; end while label_2;  
  325. label_3:repeat leave label_3;until 0=0 end repeat label_3;  
  326. label_4:loop leave label_4; end loop label_4;  
  327. end label_1;//  
  328. call p18()//  
  329. #<14>leave和labels 跳出和标号;leave 使程序跳出复杂的语句  
  330. delimiter //  
  331. DROP procedure IF EXISTS p19//  
  332. create procedure p19(par char)  
  333. label_1:begin  
  334. label_2:begin  
  335. label_3:begin  
  336. if par is not null then  
  337. if par='a' then leave label_1;  
  338. else  
  339.    begin  
  340.      if par='b' then  
  341.        leave label_2;  
  342.      else  
  343.        leave label_3;  
  344.      end if;  
  345.    end;  
  346. end if;  
  347. end if;  
  348. end label_3;  
  349. end label_2;  
  350. end label_1;  
  351. //  
  352. call p19('a')//  
  353.  
  354. #<15>iterate迭代,必须用leave;iterate意思是重新开始复合语句,相当于 continue  
  355. #该结果中3将不被保存到数据库表中  
  356. delimiter //  
  357. DROP procedure IF EXISTS p20//  
  358. create procedure p20()  
  359. begin  
  360. declare v int;  
  361. set v=0;  
  362. loop_label:loop  
  363.     if v=3 then  
  364.       set v=v+1;  
  365.       iterate loop_label;  
  366.     end if;  
  367.     insert into casetest values(v);  
  368.     set v=v+1;  
  369.     if v>=5 then  
  370.       leave loop_label;  
  371.     end if;  
  372. end loop loop_label;  
  373. end;//  
  374. call p20()//  
  375.  
  376. #<16>Grand combination大组合  
  377. delimiter //  
  378. DROP procedure IF EXISTS p21//  
  379. create procedure p21(in par1 int,out par2 int)  
  380. language sql deterministic sql security invoker  
  381. begin  
  382. declare v int;  
  383. label goto_label;  
  384. start_label:loop  
  385.     if v=v then  
  386.       leave start_label;  
  387.     else  
  388.       iterate start_label;  
  389.     end if;  
  390. end loop start_label;  
  391. repeat  
  392.     while 1=0 do begin end;  
  393.     end while;  
  394. until v=v  
  395. end repeat;  
  396. goto goto_label;  
  397.   
  398. end;  
  399. //  
  400. call p21()//  
  401. ## **************** trigger ***************************  
  402. #<17>  
  403. use testprocedure;  
  404. CREATE TABLE trig1(a1 int);  
  405. CREATE TABLE trig2(a2 int);  
  406. CREATE TABLE trig3(a3 int not null AUTO_INCREMENT PRIMARY KEY);  
  407. CREATE TABLE trig4(  
  408. a4 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,  
  409. b4 INT DEFAULT 0  
  410. );  
  411. insert into trig3(a3) values(null),(null),(null),(null),(null),(null),(null),(null),(null),(null);  
  412. insert into trig4(a4) values(0),(0),(0),(0),(0),(0),(0),(0),(0),(0);  
  413. delimiter //  
  414. DROP trigger trigtest//  
  415. create trigger trigtest before insert on trig1  
  416. for each row begin  
  417. insert into trig2 set a2=NEW.a1;  
  418. delete from trig3 where a3=NEW.a1;  
  419. update trig4 set b4=b4+1 where a4=NEW.a1;  
  420. end;  
  421. //  
  422.   
  423. delimiter ;  
  424. INSERT INTO trig1 VALUES(1), (3), (1), (7), (1), (8), (4), (4);  
  425. ------ -------------------------------------------------------------------------  
  426. Drop Procedure If Exists p_report;  
  427. Delimiter forend  
  428. Create Procedure p_report  
  429. (In year Int,  
  430. In month Int,  
  431. In Id Char(10),  
  432. Out status Int)  
  433. Begin  
  434. SelectYear,  
  435. Month,  
  436. OfficeId,  
  437. OnTimeRate  
  438. FromReportByMonth  
  439. WhereOfficeId = Id And  
  440. Year = year;  
  441. End  
  442. forend  
  443. Delimiter ;  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值