mysql-存儲過程案例-存儲過程中創建表和修改表數據


-- 本存儲過程有特殊執行循環數量的要求,是對security_market_history表進行修正
-- 判斷存儲過程是否存在
drop PROCEDURE if exists proc_security_market_history_update;
CREATE PROCEDURE proc_security_market_history_update()
begin
DECLARE p_i int default 0; -- 設置初始參數
set @p_days = date_sub(curdate(),interval 0 day); -- 設置需要初始化的值
repeat -- 開啟循環

drop table if exists temp_proc_update1;-- 判斷臨時表是否存在
drop table if exists temp_proc_update2;-- 判斷臨時表是否存在
create table temp_proc_update1 (-- 創建臨時表
`idStr` char(32) NOT NULL,
`hqzqdm` varchar(6) DEFAULT NULL,
`hqzqjc` varchar(8) DEFAULT NULL,
`hqzrsp` decimal(9,3) DEFAULT NULL,
`hqjrkq` decimal(9,3) DEFAULT NULL,
`hqzjcj` decimal(9,3) DEFAULT NULL,
`hqcjsl` decimal(12,0) DEFAULT NULL,
`hqcjje` decimal(17,3) DEFAULT NULL,
`hqcjbs` decimal(9,0) DEFAULT NULL,
`hqzgcj` decimal(9,3) DEFAULT NULL,
`hqzdcj` decimal(15,3) DEFAULT NULL,
`hqsyl1` decimal(15,4) DEFAULT NULL,
`hqsyl2` decimal(9,4) DEFAULT NULL,
`hqjsd1` decimal(9,3) DEFAULT NULL,
`hqjsd2` decimal(9,3) DEFAULT NULL,
`hqhycc` decimal(12,0) DEFAULT NULL,
`hqsjw5` decimal(9,3) DEFAULT NULL,
`hqssl5` decimal(12,0) DEFAULT NULL,
`hqsjw4` decimal(9,3) DEFAULT NULL,
`hqssl4` decimal(12,0) DEFAULT NULL,
`hqsjw3` decimal(9,3) DEFAULT NULL,
`hqssl3` decimal(12,0) DEFAULT NULL,
`hqsjw2` decimal(9,3) DEFAULT NULL,
`hqssl2` decimal(12,0) DEFAULT NULL,
`hqsjw1` decimal(9,3) DEFAULT NULL,
`hqssl1` decimal(12,0) DEFAULT NULL,
`hqbjw1` decimal(9,3) DEFAULT NULL,
`hqbsl1` decimal(12,0) DEFAULT NULL,
`hqbjw2` decimal(9,3) DEFAULT NULL,
`hqbsl2` decimal(12,0) DEFAULT NULL,
`hqbjw3` decimal(9,3) DEFAULT NULL,
`hqbsl3` decimal(12,0) DEFAULT NULL,
`hqbjw4` decimal(9,3) DEFAULT NULL,
`hqbsl4` decimal(12,0) DEFAULT NULL,
`hqbjw5` decimal(9,3) DEFAULT NULL,
`hqbsl5` decimal(12,0) DEFAULT NULL,
`mdate` date DEFAULT NULL,
PRIMARY KEY (`idStr`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
create table temp_proc_update2 (-- 創建臨時表
`idStr` char(32) NOT NULL,
`hqzqdm` varchar(6) DEFAULT NULL,
`hqzqjc` varchar(8) DEFAULT NULL,
`hqzrsp` decimal(9,3) DEFAULT NULL,
`hqjrkq` decimal(9,3) DEFAULT NULL,
`hqzjcj` decimal(9,3) DEFAULT NULL,
`hqcjsl` decimal(12,0) DEFAULT NULL,
`hqcjje` decimal(17,3) DEFAULT NULL,
`hqcjbs` decimal(9,0) DEFAULT NULL,
`hqzgcj` decimal(9,3) DEFAULT NULL,
`hqzdcj` decimal(15,3) DEFAULT NULL,
`hqsyl1` decimal(15,4) DEFAULT NULL,
`hqsyl2` decimal(9,4) DEFAULT NULL,
`hqjsd1` decimal(9,3) DEFAULT NULL,
`hqjsd2` decimal(9,3) DEFAULT NULL,
`hqhycc` decimal(12,0) DEFAULT NULL,
`hqsjw5` decimal(9,3) DEFAULT NULL,
`hqssl5` decimal(12,0) DEFAULT NULL,
`hqsjw4` decimal(9,3) DEFAULT NULL,
`hqssl4` decimal(12,0) DEFAULT NULL,
`hqsjw3` decimal(9,3) DEFAULT NULL,
`hqssl3` decimal(12,0) DEFAULT NULL,
`hqsjw2` decimal(9,3) DEFAULT NULL,
`hqssl2` decimal(12,0) DEFAULT NULL,
`hqsjw1` decimal(9,3) DEFAULT NULL,
`hqssl1` decimal(12,0) DEFAULT NULL,
`hqbjw1` decimal(9,3) DEFAULT NULL,
`hqbsl1` decimal(12,0) DEFAULT NULL,
`hqbjw2` decimal(9,3) DEFAULT NULL,
`hqbsl2` decimal(12,0) DEFAULT NULL,
`hqbjw3` decimal(9,3) DEFAULT NULL,
`hqbsl3` decimal(12,0) DEFAULT NULL,
`hqbjw4` decimal(9,3) DEFAULT NULL,
`hqbsl4` decimal(12,0) DEFAULT NULL,
`hqbjw5` decimal(9,3) DEFAULT NULL,
`hqbsl5` decimal(12,0) DEFAULT NULL,
`mdate` date DEFAULT NULL,
PRIMARY KEY (`idStr`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


-- 往臨時表中插入數據 , security_market_history表和臨時表是一樣的
insert into temp_proc_update1 select h.* from security_market_history h where h.mdate = @p_days ;
select @p_days:=(select max(h.mdate) from security_info_history h where h.mdate < @p_days ) as '修正日期';
insert into temp_proc_update2 select h.* from security_market_history h where h.mdate = @p_days ;
-- select @p_days:=(select max(h.mdate) from security_info_history h where h.mdate < @p_days );


-- 與security_market_history表接口一樣,用於修正后存儲數據
insert into temp_proc_update3 
select 
t2.idStr
,t2.hqzqdm 
,t2.hqzqjc
,t2.hqzrsp
,if(t2.hqjrkq is null or t2.hqjrkq = 0 or t2.hqjrkq = '' ,t2.hqzrsp,t2.hqjrkq) hqjrkp -- 今日開盤無,則用昨日收盤取代,
,if(t2.hqzjcj is null or t2.hqzjcj = 0 or t2.hqzjcj = '' ,t1.hqzrsp,t2.hqzjcj) hqzjcj -- 最近成交無,則用下一日的昨日收盤取代
,if(t2.hqcjsl is null or t2.hqcjsl = '' ,0,t2.hqcjsl) hqcjsl
,if(t2.hqcjje is null or t2.hqcjje = '' ,0,t2.hqcjje) hqcjje
,if(t2.hqcjbs is null or t2.hqcjbs = '' ,0,t2.hqcjbs) hqcjbs
,t2.hqzgcj
,t2.hqzdcj
,t2.hqsyl1
,t2.hqsyl2
,t2.hqjsd1
,t2.hqjsd2
,t2.hqhycc
,t2.hqsjw5
,t2.hqssl5
,t2.hqsjw4
,t2.hqssl4
,t2.hqsjw3
,t2.hqssl3
,t2.hqsjw2
,t2.hqssl2
,t2.hqsjw1
,t2.hqssl1
,t2.hqbjw1
,t2.hqbsl1
,t2.hqbjw2
,t2.hqbsl2
,t2.hqbjw3
,t2.hqbsl3
,t2.hqbjw4
,t2.hqbsl4
,t2.hqbjw5
,t2.hqbsl5
,t2.mdate
from temp_proc_update1 t1 ,temp_proc_update2 t2
where t1.hqzqdm = t2.hqzqdm ;
set p_i=p_i+1; -- 設置量
until p_i>=600 -- 斷開循環條件,這里用戶使用分好結尾,否則報錯

end repeat;-- 循環尾部
end;-- 介紹存儲過程

 

 

 

 

在MySQL存儲過程的語句中有三個標准的循環方式:

WHILE循環,
LOOP循環以及REPEAT循環。
GOTO

 

,不過這種循環方式最好別用,很容易引起程序的混亂,在這里就不錯具體介紹了。

這幾個循環語句的格式如下:

WHILE……DO……END WHILE
REPEAT……UNTIL END REPEAT
LOOP……END LOOP
GOTO

 

 

    下面首先使用第一種循環編寫一個例子。

mysql> create procedure pro10()
    -> begin
    -> declare i int;
    -> set i=0;
    -> while i<5 do
    ->     insert into t1(filed) values(i);
    ->     set i=i+1;
    -> end while;
    -> end;//

 

Query OK, 0 rows affected (0.00 sec)

 


    在這個例子中,INSERT和SET語句在WHILE和END WHILE之間,當變量i大於等於5的時候就退出循環。使用set i=0;語句是為了防止一個常見的錯誤,如果沒有初始化,i默認變量值為NULL,而NULL和任何值操作的結果都是NULL。
    執行一下這個存儲過程並產看一下執行結果:

mysql> delete from t1//
Query OK, 0 rows affected (0.00 sec)
mysql> call pro10()//
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1//
+——-+
| filed |
+——-+
|     0 |
|     1 |
|     2 |
|     3 |
|     4 |
+——-+
5 rows in set (0.00 sec)

 


    以上就是執行結果,有5行數據插入到數據庫中,證明存儲過程編寫正確無誤^_^。

    再來看一下第二個循環控制指令 REPEAT……END REPEAT。使用REPEAT循環控制語句編寫下面這個存儲過程:

mysql> create procedure pro11()
    -> begin
    -> declare i int default 0;
    -> repeat
    ->     insert into t1(filed) values(i);
    ->     set i=i+1;
    ->     until i>=5
    -> end repeat;
    -> end;//
Query OK, 0 rows affected (0.00 sec)

 


    這個REPEAT循環的功能和前面WHILE循環一樣,區別在於它的執行后檢查是否滿足循環條件(until i>=5),而WHILE則是執行前檢查(while i<5 do)。
    不過要注意until i>=5后面不要加分號,如果加分號,就是提示語法錯誤。
    編寫完成后,調用一下這個存儲過程,並查看結果:

mysql> delete from t1//
Query OK, 5 rows affected (0.00 sec)

mysql> call pro11()//
Query OK, 1 row affected (0.00 sec) #雖然在這里顯示只有一行數據受到影響,但是下面選擇數據的話,還是插入了5行數據。

mysql> select * from t1//
+——-+
| filed |
+——-+
|     0 |
|     1 |
|     2 |
|     3 |
|     4 |
+——-+
5 rows in set (0.00 sec)

 

一行就是執行結果,實際的作用和使用while編寫的存儲過程一樣,都是插入5行數據。

再來看一下第三個循環控制語句LOOP……END LOOP。編寫一個存儲過程程序如下:

mysql> create procedure pro12()
    -> begin
    -> declare i int default 0;
    -> loop_label: loop
    ->     insert into t1(filed) values(i);
    ->     set i=i+1;
    ->     if i>=5 then
    ->         leave loop_label;
    ->     end if;
    -> end loop;
    -> end;//
Query OK, 0 rows affected (0.00 sec)

 


從上面這個例子可以看出,使用LOOP編寫同樣的循環控制語句要比使用while和repeat編寫的要復雜一些:在循環內部加入了IF……END IF語句,在IF語句中又加入了LEAVE語句,LEAVE語句的意思是離開循環,LEAVE的格式是:LEAVE 循環標號。
    編寫完存儲過程程序后,來執行並查看一下運行結果:

mysql> delete from t1//
Query OK, 5 rows affected (0.00 sec)

 

mysql> call pro12//
Query OK, 1 row affected (0.00 sec) #雖然說只有一行數據受影響,但是實際上是插入了5行數據。

mysql> select * from t1//
+——-+
| filed |
+——-+
|     0 |
|     1 |
|     2 |
|     3 |
|     4 |
+——-+
5 rows in set (0.00 sec)

 

    執行結果和使用WHILE、LOOP編寫的循環一樣,都是往標中插入5行值。

   Labels   標號和 END Labels 結束標號
   在使用loop的時候,使用到的labels標號,對於labels可以用到while,loop,rrepeat等循環控制語句中。而且有必要好好認識一下lables!!

mysql> create procedure pro13()
    -> label_1:begin
    -> label_2:while 0=1 do leave label_2;end while;
    -> label_3:repeat leave label_3;until 0=0 end repeat;
    -> label_4:loop leave label_4;end loop;
    -> end;//
Query OK, 0 rows affected (0.00 sec)

 


    上面這里例子顯示了可以在BEGIN、WHILE、REPEAT或者LOOP語句前使用語句標號,語句標號只能在合法的語句前使用,所以LEAVE label_3意味着離開語句標號名為label_3的語句或符合語句。
    其實,也可以使用END labels來表示標號結束符。

mysql> create procedure pro14()
    -> label_1:begin
    -> label_2:while 0=1 do leave label_2;end while label_2;
    -> label_3:repeat leave label_3;until 0=0 end repeat label_3;
    -> label_4:loop leave label_4;end loop label_4;
    -> end label_1;//
Query OK, 0 rows affected (0.00 sec)

 


    上面就是使用了標號結束符,其實這個結束標號並不是十分有用,而且他必須和開始定義的標號名字一樣,否則就會報錯。如果要養成一個良好的編程習慣方便他人閱讀的話,可以使用這個標號結束符。

ITERATE 迭代        
     如果是在ITERATE語句,即迭代語句中的話,就必須使用LEAVE語句。ITERATE只能出現在LOOP,REPEAT和WHILE語句中,它的意思是“再次循環”,例如:

mysql> create procedure pro15() 
    -> begin
    -> declare i int default 0;
    -> loop_label:loop
    ->     if i=3 then
    ->         set i=i+1;
    ->         iterate loop_label;
    ->     end if;
    ->     insert into t1(filed) values(i);
    ->     set i=i+1;
    ->     if i>=5 then
    ->        leave loop_label;
    ->     end if;
    ->   end loop;
    -> end;//
Query OK, 0 rows affected (0.00 sec)

 


    iterate語句和leave語句一樣,也是在循環內部使用,它有點類似於C/C++語言中的continue。
    那么這個存儲程序是怎么運行的的?首先i的值為0,條件判斷語句if i=3 then判斷為假,跳過if語段,向數據庫中插入0,然后i+1,同樣后面的if i>=5 then判斷也為假,也跳過;繼續循環,同樣插入1和2;在i=3的時候條件判斷語句if i=3 then判斷為真,執行i=i+1,i值為4,然后執行迭代iterate loop_label;,即語句執行到iterate loop_label;后直接跳到if i=3 then判斷語句,執行判斷,這個時候由於i=4,if i=3 then判斷為假,跳過IF語段,將4添加到表中,i變為5,條件判斷if i>=5 then判斷為真,執行leave loop_label;跳出loop循環,然后執行end;//,結束整個存儲過程。
    綜上所述,數據庫中將插入數值:0,1,2,4。執行存儲過程,並查看結果:|

mysql> delete from t1//
Query OK, 5 rows affected (0.00 sec)

 

mysql> call pro15//
Query OK, 1 row affected (0.00 sec)

mysql> select * from t1//
+——-+
| filed |
+——-+
|     0 |
|     1 |
|     2 |
|     4 |
+——-+
4 rows in set (0.00 sec)

 

和我們上面分析的結果一樣,只插入了數值0,1,2,4。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM