日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Mysql 游標(biāo)使用動態(tài)變量

 instl 2015-11-21
從語法上來講DECLARE cur CURSOR for語句必須寫在SET @sqlstr前面,這就意味著不能通過先執(zhí)行一條動態(tài)語句根據(jù)結(jié)果拼湊游標(biāo)的內(nèi)容,而且游標(biāo)在定義的時候也沒有參數(shù)的概念,而是將定義的結(jié)構(gòu)完全當(dāng)作一個字符串直接處理,不會做任何的處理,也就是靜態(tài)游標(biāo)吧。關(guān)于dynamic cursor的內(nèi)容官方有解釋http://dev./doc/refman/5.6/en/connector-odbc-usagenotes-functionality.html#connector-odbc-usagenotes-functionality-dynamic-cursor我從5.1找到5.6只有這一個地方講dynamic cursor而且內(nèi)容一模一樣。

“Support for the dynamic cursor is provided in Connector/ODBC 3.51, but dynamic cursors are not enabled by default. You can enable this function within Windows by selecting the Enable Dynamic Cursor check box within the ODBC Data Source Administrator.On other platforms, you can enable the dynamic cursor by adding 32 to the OPTION value when creating the DSN. ”話說這個意思是使用ODBC的話就可以經(jīng)過設(shè)置之后使用dynamic cursor,關(guān)鍵是我有JDBC,安裝程序的時候再自帶一個ODBC驅(qū)動的話,貌似不太現(xiàn)實,于是考慮其它方式。我總結(jié)一下解決這個問題有三種途徑。

一、避免使用動態(tài)游標(biāo)的可能性。首先使用所謂動態(tài)就是一段代碼可復(fù)用與多種情況,于是每種情況都寫一種代碼就可避免,但是作為開發(fā)人員,基本沒人會這樣做。

二、拆分存儲過程。假設(shè)存在表結(jié)構(gòu)如下:

Sql代碼  收藏代碼
  1. mysql> desc tree_test;  
  2. +———–+————-+——+—–+———+—————-+  
  3. | Field       | Type        | Null | Key | Default | Extra          |  
  4. +———–+————-+——+—–+———+—————-+  
  5. | id             | int(11)     | NO   | PRI | NULL    | auto_increment |  
  6. | name      | varchar(11) | NO   |     |              |                |  
  7. | parent_id | int(11)     | NO   |         | NULL    |                |  
  8. +———–+————-+——+—–+———+—————-+  
  9. 3 rows in set (0.00 sec)  



現(xiàn)在的問題就是將不確定值傳給游標(biāo),簡單的游標(biāo)定義如下DECLARE cur CURSOR for SELECT * FROM TABLE。這里看到好多人說法是如果在for語句后面使用內(nèi)置方法方法的話,方法參數(shù)可以是你傳入的值,也就是說后面的SQL語句是支持方法調(diào)用的。沒測試,那天測試了再補(bǔ)充吧。就拿后面的 select 語句來說這個語句里面都是確定的值,但是有一個我們可以控制的參數(shù)就是表名。表這里可以看作是一個臨時的數(shù)據(jù)集合,如果我們可以控制里面的值,在游標(biāo)OPEN之后讀這個“動態(tài)的集合”,于是實現(xiàn)這個有臨時表和視圖兩種途徑。在這里我選擇視圖?,F(xiàn)在創(chuàng)建三個PROCEDURE:

Sql代碼  收藏代碼
  1. CREATE DEFINER=`root`@`localhost` PROCEDURE `proc1`(IN top int)  
  2.     BEGIN  
  3.   
  4.     DROP VIEW IF EXISTS tree_test_view;  
  5.     SET @sqlstr = "CREATE VIEW tree_test_view as ";  
  6.     SET @sqlstr = CONCAT(@sqlstr , "SELECT id FROM tree_test WHERE parent_id = 0 LIMIT ", top);  
  7.   
  8.     PREPARE stmt FROM @sqlstr;  
  9.     EXECUTE stmt;  
  10.     DEALLOCATE PREPARE stmt;  
  11.   
  12. END  

第一個功能很簡單,根據(jù)條件獲得一個ID集合,并把集合存在tree_test_view這個視圖中,這里直接在SQL編輯器寫的代碼,直接運(yùn)行需要添加存儲過程存在判斷和DELIMITER轉(zhuǎn)義換行符。現(xiàn)在我們已經(jīng)獲得需要要刪除的樹的ID集合,因為已只有兩級的數(shù),所有只需要知道根的id就可以直接刪除整棵樹,如果是多級的話就需要進(jìn)行遞歸刪除,當(dāng)然前提是需要知道根ID,并且只知道根ID就足夠了。
Sql代碼  收藏代碼
  1. CREATE DEFINER=`root`@`localhost` PROCEDURE `proc2`()  
  2. BEGIN  
  3.   
  4.     DECLARE done INT DEFAULT 0;  
  5.   
  6.     DECLARE temp_id INT;  
  7.     DECLARE cur CURSOR for( SELECT id from tree_test_view);  
  8.     DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;  
  9.   
  10.     OPEN cur;  
  11.     FETCH cur INTO temp_id;  
  12.     WHILE done <> 1 DO  
  13.     delete tree_test WHERE id = temp_id or parent_id = temp_id;  
  14.     FETCH cur INTO temp_id;  
  15.     END WHILE;  
  16.     CLOSE cur;  
  17. END  

這個就是執(zhí)行的刪除操作,基本的游標(biāo)循環(huán)操作,話說這寫法好像很有shell和python的韻味。proc1和proc2兩個分別執(zhí)行就可已,當(dāng)然為了對外的友好,可以再寫一個進(jìn)行統(tǒng)一調(diào)用:
Sql代碼  收藏代碼
  1. REATE DEFINER=`root`@`localhost` PROCEDURE `tree_test_query`(IN top int)  
  2.   
  3. BEGIN  
  4.   
  5.     call proc1(top);  
  6.     call proc2();  
  7.   
  8. END  



三、第三種是我首先想到的,后來發(fā)現(xiàn)原來一般情況下會首先想到第二種,于是我覺得我確實懶的不行了。第三種方法實際就是第二種方法的偷懶方式,把所有的都放在一個存儲過程中實現(xiàn),實際SQL如下:

Sql代碼  收藏代碼
  1. CREATE DEFINER=`root`@`localhost` PROCEDURE `tree_test_query`(IN top int)  
  2. BEGIN  
  3.   
  4.     DECLARE done INT DEFAULT 0;  
  5.   
  6.     DECLARE temp_id INT;  
  7.     DECLARE cur CURSOR for( SELECT id from tree_test_view);  
  8.   
  9.     DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;  
  10.   
  11.     DROP VIEW IF EXISTS tree_test_view;  
  12.   
  13.     SET @sqlstr = "CREATE VIEW tree_test_view as ";  
  14.     SET @sqlstr = CONCAT(@sqlstr , "SELECT id FROM tree_test WHERE parent_id = 0 LIMIT ", top);  
  15.   
  16.     PREPARE stmt FROM @sqlstr;  
  17.     EXECUTE stmt;  
  18.     DEALLOCATE PREPARE stmt;  
  19.   
  20.     OPEN cur;  
  21.     FETCH cur INTO temp_id;  
  22.     WHILE done <> 1 DO  
  23.     DELETE FROM tree_test WHERE id = temp_id or parent_id = temp_id;  
  24.     FETCH cur INTO temp_id;  
  25.     END WHILE;  
  26.     CLOSE cur;  
  27. END  

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多