MySQL : 刪除數據庫中的全部表的實現

  系統集成 SpringMVC 的測試框架,爲了在測試結束後,清空測試數據庫的全部表單,須要寫一段 SQL 腳本實現。這個任務到了我這裏,尷尬的是,對 MySql 的理解僅在於 CRUD 的我,要寫操做數據庫的 SQL ,簡直是莫大的難事,做爲程序員,不會寫不是問題,不會查就是罪過了。
  然而,在查百度的時候,心裏真的有一萬隻草泥馬奔騰而過,沒想到不少資料都是無用的。先不說一大堆博客都是複製粘貼而來,更糟糕的是,博客裏有寫代碼根本運行不起來的,這些測試 Demo 還有什麼意思,結果查了半天都沒找到可用的,也要吐槽百度的搜索引擎,基於商業的排序的算法根本沒辦法和谷歌的搜索引擎相比,神傷。最後爲了解決問題,只能自學 MySql 的一些基本語法,再把這個腳本寫出來。mysql

  學習全部的 SQL 語法確定是不現實的,因此,爲了實現目標,只能將這個任務切割開來。程序員

  • 刪除表 SQL算法

  • 獲取數據庫下的全部表 SQLsql

  • 遍歷結果集 SQL數據庫

  • 遍歷過程當中,拼接刪除表的 SQL ,並執行該 SQLexpress

SQL:刪除表

直接查 MySQL 的 語法:服務器

DROP ‘table’  /*刪除數據庫下對應名稱的表*/

抱着僥倖的心理,但願有能夠刪除數據庫下的全部表的語法,這樣就不須要進行下面的步驟了,然並卵,幻想破滅。框架

SQL:獲取數據庫下的全部表

select table_name from information_schema.tables ;  /*獲取數據庫下的全部表單,可添加篩選條件*/

解析 : information_schema表 函數

  information_schema這張數據表保存了MySQL服務器全部數據庫的信息。如數據庫名,數據庫的表,表欄的數據類型與訪問權限等。學習

  • information_schema.schemata 表:數據庫的信息

  • information_schema.tables 表:數據庫中表的信息

  • information_schema.columns 表:表的列的信息

  • information_schema.statistics 表:表的索引信息

  只要想找關於數據庫的信息,這張表均可以提供相關的信息。

SQL:遍歷結果集

  涉及到遍歷,第一時間就想到了 for / while 這樣的關鍵字,MySql固然提供了相關的語法,可是此次的語句就再也不是簡單的查詢語句,而必須經過函數來實現。

MySql 提供了三種方式:WHILE 、 LOOP 、 REPEAT:

以 REPEAT UNTIL 循環爲例,MySQL 給出的方法中須要明確三個參數:

[ label: ]  REPEAT   /*label:循環名稱,無關緊要*/

 statements          /*statements:循環語句內的執行語句*/

 UNTIL expression    /*expression : 循環條件*/

 END  REPEAT  [ label ]  ;

有了前面三點作鋪墊,若要實現目標,只要再循環體裏拼接出刪除表的語句,並執行,也就是如下的重難點。

SQL:拼接語句,執行語句

難點一:循環體內如何遍歷結果集

百度關鍵詞: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();
相關文章
相關標籤/搜索