【问题标题】:Querying multiple databases at once一次查询多个数据库
【发布时间】:2010-01-25 13:45:47
【问题描述】:

我有 WordPress 实例,每个实例都在自己的数据库中。对于更新,我需要查询所有活动插件,这些插件存储在表 'wp_options' 中并可通过

WHERE option_name='active_plugins'

如何访问所有活动插件设置(分布在多个数据库中)并将它们输出到一个 SQL 结果中?我知道database.tablename 语法,但我该如何继续使用上面的Where 语句?

单个数据库中的请求如下所示:

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

【问题讨论】:

    标签: mysql multiple-databases


    【解决方案1】:
    SELECT option_value
     FROM `database1`.`wp_options`
      WHERE option_name="active_plugins"
    UNION
    SELECT option_value
     FROM `database2`.`wp_options`
      WHERE option_name="active_plugins"
    

    【讨论】:

    • 如果你有多个数据库和表,是否可以将其放在循环或函数中以避免重复工作。
    • 如果每个数据库没有不同的用户名/密码,这不起作用?
    【解决方案2】:

    Pentium10 的解决方案很好,但它的缺点是您必须为要包含的每个模式扩展查询。以下解决方案使用准备好的语句为您的 MySQL 服务器上的 all 模式生成结果集,这些模式具有 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();
    

    【讨论】:

    • 这是一个可重用解决方案的良好开端。但是请记住用分隔符子句包装它,否则它可能会失败,尤其是。在 MySQL WorkBench SQL 编辑器中
    • @Joey T:谢谢,我添加了分隔子句。作为一般说明,由于与模式同步和查询相关的问题,我尝试避免单租户设置。如果有人坚持这样的设置,我发现使用准备好的语句是解决查询问题的好方法。使用这种技术,您基本上可以获得模拟多租户设置的查询。
    • 为什么是表ResultSet?
    【解决方案3】:

    Gruber 的回答效果很好,但它有一个语法错误 --- 第 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
    $$
    

    【讨论】:

    • 欢迎来到 Stack Overflow!编辑现有答案比发布新答案更好。您还有编辑权限吗? (我知道那些刚接触该网站的人可能会在一段时间内处于 catch-22 状态......“正确的做法实际上是这个......而你没有代表。 ") 如果你有足够的代表,你应该编辑答案并删除这个。
    • 非常感谢您对此的回复。是的——完全正确;我有一个catch-22,我无法在该帖子中添加评论或编辑原始答案——所以除了创建一个新答案之外,没有任何方法可以提醒人们注意这一点。我尝试的所有内容都被删除了——所以,谢谢你没有删除这个;只要我有足够的声誉,我就会回来并做出正确的回答!
    【解决方案4】:

    又一个使用过程、游标、union all 和prepared statement 查询多个数据库的示例。不需要删除和删除权限:

    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');
    

    【讨论】:

      猜你喜欢
      • 2021-07-28
      • 1970-01-01
      • 1970-01-01
      • 2012-03-02
      • 1970-01-01
      • 1970-01-01
      • 2013-06-23
      • 1970-01-01
      • 2011-12-25
      相关资源
      最近更新 更多