2010-01-25 111 views
25

我在每個數據庫中都有WordPress實例。對於更新我需要查詢所有活動的插件,即通過一次查詢多個數據庫

WHERE option_name='active_plugins' 

存儲在表「wp_options」和訪問如何訪問所有活動插件設置(分佈在多個數據庫),並在輸出一個單一的SQL結果?我知道database.tablename語法,但是我怎麼從那裏繼續使用上面的Where聲明?

在一個數據庫中的請求是這樣的:

SELECT option_value 
    FROM `database`.`wp_options` 
WHERE option_name="active_plugins" 
+0

http://www.dottedidesign.com/node/14 – 2010-01-25 13:51:26

回答

38
​​
+0

很酷,謝謝!以前不知道UNION。 – Boldewyn 2010-01-25 13:54:38

8

通過Pentium10的解決方案是好的,但它的缺點是,你必須擴展查詢要包含所有的模式。以下解決方案使用準備好的語句爲您的MySQL服務器上的全部模式生成一個結果集,其中有wp_options表。這應該對你更方便。

DROP PROCEDURE IF EXISTS `MultipleSchemaQuery`; 

DELIMITER $$ 

CREATE PROCEDURE `MultipleSchemaQuery`() 
BEGIN 
    declare scName varchar(250); 
    declare q varchar(2000); 

    DROP TABLE IF EXISTS ResultSet; 
    create temporary table ResultSet (
    option_value varchar(200) 
    ); 

    DROP TABLE IF EXISTS MySchemaNames; 
    create temporary table MySchemaNames (
     schemaName varchar(250) 
    ); 

    insert into MySchemaNames 
    SELECT distinct 
     TABLE_SCHEMA as SchemaName 
    FROM 
     `information_schema`.`TABLES` 
    where 
     TABLE_NAME = 'wp_options'; 

label1: 
    LOOP 
     set scName = (select schemaName from MySchemaNames limit 1); 
     set @q = concat('select option_value from ', scName, '.wp_options where option_name=\'active_plugins\''); 
     PREPARE stmt1 FROM @q; 
     EXECUTE stmt1; 
     DEALLOCATE PREPARE stmt1; 

     delete from MySchemaNames where schemaName = scName; 
     IF ((select count(*) from MySchemaNames) > 0) THEN 
      ITERATE label1; 
     END IF; 
     LEAVE label1; 

    END LOOP label1; 

    SELECT * FROM ResultSet; 

    DROP TABLE IF EXISTS MySchemaNames; 
    DROP TABLE IF EXISTS ResultSet; 
END 
$$ 

DELIMITER ; 

CALL MultipleSchemaQuery(); 
+0

這是一個可重用解決方案的良好開端。 但是記住要用分隔符來包裝它,否則它可能會失敗,特別是。在MySQL WorkBench SQL編輯器 – 2013-02-25 07:06:39

+0

@Joey T:謝謝,我添加了分隔符子句。作爲一般說明,我嘗試避免單租戶設置,因爲與模式同步和查詢相關的問題。如果有人堅持這樣的設置,我發現使用準備好的語句是糾正查詢問題的好方法。使用這種技術,您基本上可以獲得模擬多租戶設置的查詢。 – Gruber 2013-02-25 09:49:24

2

使用過程,遊標,聯合全部和準備好的語句來查詢多個數據庫的另一個例子。不需要降和刪除權限:

USE `my_db`; 
DROP PROCEDURE IF EXISTS `CountAll`; 
DELIMITER $$ 

CREATE PROCEDURE `CountAll`(IN tableName VARCHAR(255)) 
BEGIN 

    DECLARE db_name   VARCHAR(250); 
    DECLARE exit_loop  BOOLEAN; 
    DECLARE union_query  TEXT DEFAULT ''; 

    DECLARE my_databases CURSOR FOR 
     SELECT DISTINCT `table_schema` 
     FROM `information_schema`.`tables` 
     WHERE 
      `table_schema` LIKE 'myprefix\_%' AND 
      `table_name` = tableName; 

    DECLARE CONTINUE HANDLER 
     FOR NOT FOUND SET exit_loop = TRUE; 

    OPEN my_databases; 

    get_database: LOOP 

     FETCH my_databases INTO db_name; 

     IF exit_loop THEN 
      -- remove trailing UNION ALL statement 
      SET union_query = TRIM(TRAILING ' UNION ALL ' FROM union_query); 
      LEAVE get_database; 
     END IF; 

     SET union_query = concat(union_query, 'SELECT COUNT(*) AS qty FROM ', 
            db_name, '.', tableName, ' UNION ALL '); 

    END LOOP get_database; 

    CLOSE my_databases; 

    SET @final_query = concat('SELECT SUM(qty) FROM (', union_query, 
                ') AS total;'); 
    PREPARE stmt1 FROM @final_query; 
    EXECUTE stmt1; 
    DEALLOCATE PREPARE stmt1; 

END$$ 

DELIMITER ; 

CALL CountAll('wp_options'); 
2

格魯伯的答案的偉大工程,但它有一個語法錯誤---有第10行。這裏的最後一個虛假逗號代碼,與語法錯誤修正:

DELIMITER $$ 

CREATE PROCEDURE `MultipleSchemaQuery`() 
BEGIN 
    declare scName varchar(250); 
    declare q varchar(2000); 

    DROP TABLE IF EXISTS ResultSet; 
    create temporary table ResultSet (
    option_value varchar(200) 
    ); 

    DROP TABLE IF EXISTS MySchemaNames; 
    create temporary table MySchemaNames (
     schemaName varchar(250) 
    ); 

    insert into MySchemaNames 
    SELECT distinct 
     TABLE_SCHEMA as SchemaName 
    FROM 
     `information_schema`.`TABLES` 
    where 
     TABLE_NAME = 'wp_options'; 

label1: 
    LOOP 
     set scName = (select schemaName from MySchemaNames limit 1); 
     set @q = concat('select option_value from ', scName, '.wp_options where option_name=\'active_plugins\''); 
     PREPARE stmt1 FROM @q; 
     EXECUTE stmt1; 
     DEALLOCATE PREPARE stmt1; 

     delete from MySchemaNames where schemaName = scName; 
     IF ((select count(*) from MySchemaNames) > 0) THEN 
      ITERATE label1; 
     END IF; 
     LEAVE label1; 

    END LOOP label1; 

    SELECT * FROM ResultSet; 

    DROP TABLE IF EXISTS MySchemaNames; 
    DROP TABLE IF EXISTS ResultSet; 
END 
$$ 
+0

歡迎來到Stack Overflow!編輯現有答案比發佈新答案要好。你有編輯權限嗎? (我知道他們對這個網站來說是新手的人可以在一段時間內以這種方式進入catch-22 ......「正確的做法實際上就是這個......而且你沒有代表。 「)如果你有足夠的代表,你應該編輯答案並刪除這個答案。 – 2014-08-21 20:36:03

+1

非常感謝回覆。是的 - 完全正確;我有一個catch-22,我無法爲該帖子添加評論,或者編輯原始答案---所以除了創建新答案之外,沒有任何方法提醒人們注意此事。我試過的所有東西都被刪除了---所以,謝謝你不要刪除這個;我會盡快回復並做出正確的回答,只要我有足夠的聲望來做到這一點! – 2015-08-18 15:25:41