2010-01-25 144 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