2015-03-25 80 views
1

運行以下查詢MYSQL時抱怨:表'DB.tableName'不存在。如何對數據庫中的多個表運行相同的查詢

CREATE PROCEDURE CountSignatures() 
    BEGIN 
    DECLARE done INT DEFAULT FALSE; 
    DECLARE signatureCount INT; 
    DECLARE tableName CHAR(100); 
    DECLARE tableList CURSOR FOR Select table_name from information_schema.tables where table_name like "%FAULT_20150320%"; 
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 
    SET signatureCount = 1; 
    OPEN tableList; 
    tableListLoop: LOOP 
     SET done = FALSE ; 
     FETCH tableList INTO tableName; 
     IF done THEN 
     LEAVE tableListLoop; 
     END IF; 

    **Select count(distinct signature) from tableName;** 

    END LOOP; 
    CLOSE tableList; 
    END$$ 

而如果我使用下面的查詢,然後打印正確tableName變量值:

CREATE PROCEDURE CountSignatures() 
    BEGIN 
    DECLARE done INT DEFAULT FALSE; 
    DECLARE signatureCount INT; 
    DECLARE tableName CHAR(100); 
    DECLARE tableList CURSOR FOR Select table_name from information_schema.tables where table_schema="LogData" and table_name like "%FAULT_20150320%"; 
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 
    SET signatureCount = 1; 
    OPEN tableList; 
    tableListLoop: LOOP 
     SET done = FALSE ; 
     FETCH tableList INTO tableName; 
     IF done THEN 
     LEAVE tableListLoop; 
     END IF; 

     **Select tableName;** 

    END LOOP; 
    CLOSE tableList; 
    END$$ 
+0

我編輯了問題的標題。我認爲,現在更好地描述問題。如果我無意中改變了它的含義,請進一步調整。 – 2015-03-25 09:50:00

回答

0

SELECT語句的FROM部分必須有實際的表名,而不是一個CHAR(100)變量,它包含了表的名稱。它只是不這樣工作。

它看起來像你想運行一個特定的查詢對數據庫中類似結構的許多表。通常意味着數據庫模式可以得到改進。但是,如果你必須處理你有什麼,你將不得不使用dynamic SQL。此鏈接指向MySQL文檔有一個例子「通過將表名稱存儲爲用戶變量,演示如何選擇在其上執行查詢的表」,這正是您所需要的。

在循環中,您需要使用SQL查詢構建一個字符串並使用EXECUTE

SET @s = CONCAT('select count(distinct signature) from ', tableName); 

PREPARE stmt FROM @s; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

據我瞭解,在EXECUTE的結果發送到存儲過程的調用者,如果它是一個正常的SELECT,所以在這個例子中,呼叫者會收到多個結果集,如果你的數據庫有多於一張表where table_name like "%FAULT_20150320%"

下面是一個關於MySQL動態SQL How To have Dynamic SQL in MySQL Stored Procedure的另一個SO問題的鏈接和一些例子。

看起來你想要這樣的東西。它應該總結來自signatureCount變量中幾個表的計數。

CREATE PROCEDURE CountSignatures() 
BEGIN 
    DECLARE done INT DEFAULT FALSE; 
    DECLARE signatureCount INT; 
    DECLARE tableName CHAR(100); 
    DECLARE tableList CURSOR FOR SELECT table_name FROM information_schema.tables WHERE table_name LIKE "%FAULT_20150320%"; 
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 
    SET signatureCount = 0; 
    OPEN tableList; 
    tableListLoop: LOOP 
     SET done = FALSE; 
     FETCH tableList INTO tableName; 
     IF done THEN 
      LEAVE tableListLoop; 
     END IF; 

     SET @VarCount = 0; 
     SET @VarSQL = CONCAT('SET @VarCount = (SELECT COUNT(DISTINCT signature) FROM ', tableName, ')'); 

     PREPARE stmt FROM @VarSQL; 
     EXECUTE stmt; 
     DEALLOCATE PREPARE stmt; 

     SET signatureCount = signatureCount + @VarCount; 
    END LOOP; 
    CLOSE tableList; 

    SELECT signatureCount; 
END$$ 

另一種變型,如果你需要處理表的數量並不多,是建立一個包括你的循環中的所有表動態的一大SQL語句,然後EXECUTE它一氣呵成:

SELECT 
(COUNT(DISTINCT signature) FROM Table1) + 
(COUNT(DISTINCT signature) FROM Table2) + 
... 
(COUNT(DISTINCT signature) FROM TableN) AS TotalCount 
0

我有時也遇到過這種情況,並且有一個非常簡單的技巧。我只是這樣做(需要Excel或谷歌表[警告:我沒有測試過這個過程,谷歌表):

  1. 運行SELECT table_name FROM information_schema.tables where table_schema='your_database_name'得到表列表(MySQL的)。
  2. 打開一個新的電子表格和表列表複製到片材起始的「A」列在第1行中
  3. 第一次測試中的單表查詢,然後在準備好時,查詢複製到「B」列第1行中對於MS Excel中有一個字符串的限制,所以你需要連接字符串作爲這樣的(我只是做逐行):

    ="ALTER TABLE `mydatabasename`.`"&A1&"` 
    "&"CHANGE COLUMN `created` `created` DATETIME NOT NULL COMMENT 'Comment here...' , 
    "&"CHANGE COLUMN `updated` `updated` DATETIME NOT NULL COMMENT 'Comment here...' ;"& 
    "&"...etc... 
    "&"...etc... 
    "&"...etc... 
    " 
    

    "&"之初是需要捕捉新線前一行的字符結束。

  4. 選擇單元格B1並向下填充字符串公式以匹配表名稱的數量。
  5. 您不應該有每個表的查詢列表。選擇整個列B和複製粘貼到新的SQL執行窗口(確保您的目標數據庫設置爲默認模式以確保安全)。
  6. 如果您在粘貼時看到雙引號",則必須將其刪除。如果在MySQL Workbench中,只需按Ctrl + H並全部替換全部"(將第二個框留空)。

這實際上效果很好,因爲公式中的雙引號在大多數情況下與SQL文本不衝突。此外,我將這些行作爲字符串連接起來,但是您可以將每行作爲單獨的行分別放在單獨的工作表上,然後使用公式將其連接起來。我敢肯定,有創意的人可以找到其他類似的方法。

當然這個想法適用於任何數據庫,只需稍作調整,這是一個優點。 ;)

相關問題