phpMyAdmin调用和生成MySQL的存储过程以及CURSOR的应用

来源:互联网 发布:监控立杆网络防雷器 编辑:程序博客网 时间:2024/06/18 13:07


首先叙述一下我碰到的问题,如果这个讲不清楚,则有可能压根不知道这究竟有什么用,有些事情总是在碰到困难需要解决非用不可的时候印象才会更深刻。

 

这是一个转换工程,需要把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; --->调用刚才这个存储过程,切记哦,因为存储过程不会自动运行。

0 0