系統集成 SpringMVC 的測試框架,爲了在測試結束後,清空測試數據庫的全部表單,須要寫一段 SQL 腳本實現。這個任務到了我這裏,尷尬的是,對 MySql 的理解僅在於 CRUD 的我,要寫操做數據庫的 SQL ,簡直是莫大的難事,做爲程序員,不會寫不是問題,不會查就是罪過了。
然而,在查百度的時候,心裏真的有一萬隻草泥馬奔騰而過,沒想到不少資料都是無用的。先不說一大堆博客都是複製粘貼而來,更糟糕的是,博客裏有寫代碼根本運行不起來的,這些測試 Demo 還有什麼意思,結果查了半天都沒找到可用的,也要吐槽百度的搜索引擎,基於商業的排序的算法根本沒辦法和谷歌的搜索引擎相比,神傷。最後爲了解決問題,只能自學 MySql 的一些基本語法,再把這個腳本寫出來。mysql
學習全部的 SQL 語法確定是不現實的,因此,爲了實現目標,只能將這個任務切割開來。程序員
刪除表 SQL算法
獲取數據庫下的全部表 SQLsql
遍歷結果集 SQL數據庫
遍歷過程當中,拼接刪除表的 SQL ,並執行該 SQLexpress
直接查 MySQL 的 語法:服務器
DROP ‘table’ /*刪除數據庫下對應名稱的表*/
抱着僥倖的心理,但願有能夠刪除數據庫下的全部表的語法,這樣就不須要進行下面的步驟了,然並卵,幻想破滅。框架
select table_name from information_schema.tables ; /*獲取數據庫下的全部表單,可添加篩選條件*/
解析 : information_schema表 函數
information_schema這張數據表保存了MySQL服務器全部數據庫的信息。如數據庫名,數據庫的表,表欄的數據類型與訪問權限等。學習
information_schema.schemata 表:數據庫的信息
information_schema.tables 表:數據庫中表的信息
information_schema.columns 表:表的列的信息
information_schema.statistics 表:表的索引信息
只要想找關於數據庫的信息,這張表均可以提供相關的信息。
涉及到遍歷,第一時間就想到了 for / while 這樣的關鍵字,MySql固然提供了相關的語法,可是此次的語句就再也不是簡單的查詢語句,而必須經過函數來實現。
MySql 提供了三種方式:WHILE 、 LOOP 、 REPEAT:
以 REPEAT UNTIL 循環爲例,MySQL 給出的方法中須要明確三個參數:
[ label: ] REPEAT /*label:循環名稱,無關緊要*/ statements /*statements:循環語句內的執行語句*/ UNTIL expression /*expression : 循環條件*/ END REPEAT [ label ] ;
有了前面三點作鋪墊,若要實現目標,只要再循環體裏拼接出刪除表的語句,並執行,也就是如下的重難點。
難點一:循環體內如何遍歷結果集
百度關鍵詞:MySql 循環體內如何遍歷結果集
百度結果,使用遊標,一番查閱後,對遊標的理解是:
遊標充當了指針的做用
遊標可對查詢數據庫所返回的結果集進行遍歷,以便進行相應的操做
儘管遊標能遍歷結果中的全部行,但他一次只指向一行
難點二:循環的判斷條件要怎麼寫
百度關鍵詞:mysql 判斷遊標結束
百度結果:使用如下的 SQL:
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
原理不太懂,可是查了一下 02000 的意思:
發生下述異常之一:
SELECT INTO 語句或 INSERT 語句的子查詢的結果爲空表。
在搜索的 UPDATE 或 DELETE 語句內標識的行數爲零。
在 FETCH 語句中引用的遊標位置處於結果表最後一行以後。
該SQL的語意是:當遊標到告終果集最後一行的時候,設置done=1。
難點三:如何執行拼接好的語句
百度關鍵詞:mysql 如何執行拼接的sql
百度結果:使用 prepare ,語法以下:
PREPARE statement_name FROM preparable_SQL_statement; /*定義*/ EXECUTE statement_name [USING @var_name [, @var_name] ...]; /*執行預處理語句*/
使用的方法和JDBC差很少,因此難度也不算太大,接下來,就要開始實現這個功能:
代碼:遍歷過程當中,拼接刪除表的 SQL ,並執行該 SQL
DECLARE done INT DEFAULT 0; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; OPEN sur; REPEAT /*循環體:使用遊標遍歷結果集*/ FETCH sur INTO tableName; /* 將遊標獲取值設置到 tableName 變量中 */ IF NOT done THEN SET cmd=concat('DROP TABLE ',DB_NAME,'.',tableName); SET @E=cmd; PREPARE stmt FROM @E; EXECUTE stmt; /*執行刪除命令*/ DEALLOCATE PREPARE stmt; /*清空刪除命令*/ END IF; UNTIL done END REPEAT; /*更新done值,並判斷是否跳出循環*/ CLOSE sur;
結合以上四點,最終的SQL腳本是:
DROP PROCEDURE IF EXISTS procedure_drop_table; CREATE PROCEDURE procedure_drop_table() BEGIN DECLARE DB_NAME varchar(50) DEFAULT "testcase"; -- 測試數據庫的名稱 DECLARE done INT DEFAULT 0; DECLARE tableName varchar(50); -- 測試庫代表 DECLARE cmd varchar(50); -- 執行命令 DECLARE sur CURSOR -- 遊標 FOR SELECT table_name FROM information_schema.TABLES WHERE table_schema=DB_NAME; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; OPEN sur; REPEAT FETCH sur INTO tableName; IF NOT done THEN set cmd=concat('DROP TABLE ',DB_NAME,'.',tableName); -- 拼接刪除命令 SET @E=cmd; PREPARE stmt FROM @E; EXECUTE stmt; DEALLOCATE PREPARE stmt; END IF; UNTIL done END REPEAT; CLOSE sur; END call procedure_drop_table();