2010-01-25 14 views
25

Tengo instancias de WordPress con cada una en su propia base de datos. Para una actualización que necesito para consultar todos los plugins activos, que se almacenan en 'wp_options' una mesa y accesibles a través deConsultar varias bases de datos a la vez

WHERE option_name='active_plugins' 

¿Cómo puedo acceder todos ajustes activos de plugins (divididas en varias bases de datos) y de salida en un solo resultado de SQL? Sé la sintaxis database.tablename, pero ¿cómo puedo continuar desde allí con la declaración anterior Where?

Una petición en una sola base de datos se vería así:

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

http://www.dottedidesign.com/node/14 –

Respuesta

38
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" 
+0

Cool, gracias! No he conocido a UNION antes. – Boldewyn

8

La solución por Pentium10 es bueno, pero su inconveniente es que hay que extender la consulta para cada esquema para ser incluido. La siguiente solución usa una declaración preparada para producir un conjunto de resultados para todos los esquemas en su servidor MySQL que tienen la tabla wp_options. Esto debería ser más conveniente para ti.

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

Este es un gran comienzo para una solución reutilizable. Pero recuerda envolver esto con las cláusulas del delimitador o probablemente fallará, esp. en MySQL WorkBench SQL Editor –

+0

@Joey T: Gracias, agregué las cláusulas del delimitador. Como nota general, trato de evitar las configuraciones de un único inquilino debido a los problemas relacionados con el esquema de sincronización y consulta. Si uno está atascado con dicha configuración, he encontrado que usar declaraciones preparadas es una gran manera de remediar los problemas de consulta. Con esta técnica, básicamente obtienes consultas que emulan una configuración multi-tenant. – Gruber

2

Otro ejemplo más de consultar múltiples bases de datos usando procedimiento, cursor, unión de todos y estado preparado. No requiere soltar y eliminar permisos:

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

respuesta de Gruber funciona muy bien, pero tiene un error de sintaxis --- hay una coma espuria al final de la línea 10. Aquí está el código, la fija error de sintaxis:

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

¡Bienvenido a Stack Overflow! Sería mejor editar la respuesta existente que publicar una nueva. ¿Ya tienes privilegios de edición? (Sé que la gente que es nueva en el sitio puede estar en un catch-22 de esa manera por un tiempo ... "La forma correcta de hacer esto es en realidad esto ... y no tienes representante para eso. ") Si tiene suficientes representantes, debe editar la respuesta y eliminar esta. –

+1

Muchas gracias por la respuesta a esto. Sí, eso es exactamente correcto; Tuve un catch-22 en el que no pude agregar un comentario a esa publicación o editar la respuesta original, por lo que no había ninguna forma de alertar a la gente sobre esto aparte de crear una nueva respuesta. Todo lo que probé fue eliminado, así que, gracias por no eliminar este; ¡y volveré y haré de esta una respuesta adecuada tan pronto como tenga suficiente reputación para hacer eso! –

Cuestiones relacionadas