1. 程式人生 > >phpMyAdmin呼叫和生成MySQL的儲存過程以及CURSOR的應用

phpMyAdmin呼叫和生成MySQL的儲存過程以及CURSOR的應用



首先敘述一下我碰到的問題,如果這個講不清楚,則有可能壓根不知道這究竟有什麼用,有些事情總是在碰到困難需要解決非用不可的時候印象才會更深刻。

這是一個轉換工程,需要把dvbbs的access資料庫轉換成phpwind的mysql形式。

phpwind論壇資料庫,

表`pws_threads`存放主題(包括標題)

表`pws_posts` 存放著所有除了一樓之外的帖子,

表`pws_tmsgs`存放著主題第一樓的資料。

dvbbs的做法是將主題和回帖分開,主題用一個表儲存,而所有回帖(包括第一樓)都存在另一個表裡,樓層按順序排列,標記為0的顯然就是1樓,然後以此類推,它沒有再單獨開一個表存放所謂1樓資料。

這倒不麻煩,只需要將原表中相同主題ID並且回帖ID最小的抽出來,然後放到phpwind的pws_tmsgs裡就行了,然後排除這些1樓的回帖,將餘下的全部帖子都放進phpwind的`pws_posts`即可。

問題在,由於操作不當。在原資料庫還沒有排除所謂“1樓”帖子的情況下,又將他們匯入了pws_posts,即在`pws_tmsgs裡有一個“1樓”在,pws_posts裡又出現了一個一模一樣的“1樓”,最後每個主題都存在兩個一模一樣的“1樓”(第二樓內容和第一樓完全一樣),這讓人抓狂!

因為資料量較大,很不情願再推倒重來一次,那麼現在這個局面該怎麼辦?

1. 總的來說,刪除現階段的第二樓即可達到目的。

2. 如何找到第二樓的回帖序號?

3. 在一個主題序號(tid)下,有很多跟帖,這些跟帖以(pid)形式出現,則查出某tid下最小的pid,則是最老的回帖(即1樓),刪除之即可。

4. 單純用SQL語句已經做不到這一點了,因為tid返回的值是一個記錄集,而我們必須再從這個記錄集裡尋找pid最小值並刪除之,也許有SQL高人能靠純查詢做到,但實話說,我不行。

---------------------------

重點(全部親測通過):

1. phpMyadmin中可以建立並執行儲存過程。

2. MySQL支援CURSOR(即遊標)

3. MySQL不支援SELECT * INTO XXX這樣的表複製,而需要

CREATE TABLE aaaa(id int) SELECT yyy FROM ttt

這樣的變通方法完成。

方法:

1. 建立一個表aaaa,獲取所有pid(主題號):

CREATE TABLE aaaa(tid int) SELECT tid FROM `pws_posts` group by tid order by tid

2. 建立一個儲存過程,

DELIMITER $$   
     DROP PROCEDURE IF EXISTS TEST1$$   
     CREATE PROCEDURE TEST1()   
     BEGIN   
      DECLARE tidv INT;
      DECLARE pidv INT;
      DECLARE fig INT;
      DEClARE cur CURSOR FOR Select tid From `aaaa`;
      DECLARE CONTINUE HANDLER FOR NOT FOUND SET fig=1;
      OPEN cur;
      REPEAT
         FETCH cur INTO tidv;
         INSERT INTO bbbb(tids) select min(pid) from `pws_posts` where `tid` = tidv;
         UNTIL fig=1
      END REPEAT;
      CLOSE cur;
     END$$   
DELIMITER;  
Call TEST1;

解釋:臨時建立了一個aaaa,表中存放`pws_posts`相同主題號(tid)中最小的回帖號(pid)

然後我們還得刪除這些資料:

DELIMITER $$    
DROP PROCEDURE IF EXISTS test2$$   
CREATE PROCEDURE test2()   
BEGIN   
DECLARE pidv INT;
DECLARE fig INT;
DEClARE cur CURSOR FOR Select tids From `bbbb`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET fig=1;
OPEN cur;
REPEAT
FETCH cur INTO pidv;
DELETE FROM `pws_posts` WHERE `pid` = pidv;
UNTIL fig=1
END REPEAT;
CLOSE cur; 
END$$   
DELIMITER ;  
Call test2;

至此我的事情到底結束。

-----------------------

無廢話版

1. 開啟phpMyadmin,點SQL,輸入程式碼,即可建立並執行儲存過程

2. 給出一個最簡單的遊標使用,你就照著我這個貼上進去,然後稍作修改即能為之己用:

DELIMITER $$
DROP PROCEDURE IF EXISTS TEST$$   
CREATE PROCEDURE TEST()   
BEGIN   
DECLARE id INT;
DECLARE fig INT;
DEClARE cur CURSOR FOR Select 欄位 From `表`;----> 此處支援所有合乎Select規則的查詢以建立記錄集
DECLARE CONTINUE HANDLER FOR NOT FOUND SET fig=1;
OPEN cur; --------->開啟遊標
REPEAT ->>開始迴圈
FETCH cur INTO id; ---->若是首次進入,則相當於將第一行資料的第一個欄位內容存入了變數id,假設你有多個欄位,可用逗號隔開,比如id,name,age之類。


(此處可以填寫所有合法的SQL語句,此處直接使用變數id,則相當於引用了表中的資料)

UNTIL fig=1 ---->資料行到尾了嗎?如沒有則繼續下一行。
END REPEAT;
CLOSE cur; 
END$$   
DELIMITER ;  
Call test2; --->呼叫剛才這個儲存過程,切記哦,因為儲存過程不會自動執行。