2010-01-25 22 views
25

Sono presenti istanze di WordPress nel proprio database. Per un aggiornamento ho bisogno di interrogare tutti i plugin attivi, che vengono memorizzati nel 'wp_options' un tavolo e accessibili tramiteInterrogazione su più database contemporaneamente

WHERE option_name='active_plugins' 

Come posso accedere tutti impostazioni attive del plugin (si sviluppa su più database) e li output in un solo risultato SQL? Conosco la sintassi database.tablename, ma come faccio a procedere da lì con la precedente dichiarazione Where?

Una richiesta in un unico database sarebbe simile a questa:

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

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

risposta

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

freddo, grazie! Non ho mai conosciuto UNION. – Boldewyn

8

La soluzione da Pentium10 è buona, ma il suo svantaggio è che si deve estendere la query per ogni schema per essere incluso. La soluzione seguente utilizza una dichiarazione preparata per produrre un set di risultati per tutti gli schemi sul server MySQL che hanno la tabella wp_options. Questo dovrebbe essere più conveniente per te.

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

Questo è un ottimo inizio per una soluzione riutilizzabile. Ma ricorda di avvolgere questo con le clausole del delimitatore o probabilmente fallirà, esp. in MySQL WorkBench SQL Editor –

+0

@Joey T: Grazie, ho aggiunto le clausole del delimitatore. Come nota generale, provo a evitare le impostazioni di un singolo tenant a causa dei problemi relativi alla sincronizzazione e all'interrogazione dello schema. Se uno è bloccato con tale impostazione, ho trovato che l'utilizzo di istruzioni preparate è un ottimo modo per risolvere i problemi di interrogazione. Con questa tecnica, si ottengono essenzialmente query che emulano una configurazione multi-tenant. – Gruber

2

Ancora un altro esempio di interrogare più database utilizzando procedura, cursore, UNION ALL e dichiarazione preparata. Non necessita di goccia ed eliminare permesso:

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

risposta di Gruber grandi opere, ma ha un errore di sintassi --- c'è una virgola spuria alla fine della linea 10. Ecco il codice, con errore di sintassi fisso:

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

Benvenuti in Stack Overflow! Sarebbe meglio modificare la risposta esistente piuttosto che postarne una nuova. Hai ancora i privilegi di modifica? (So ​​che le persone che sono nuove sul sito possono essere in un catch-22 in quel modo per un po '... "Il modo corretto per farlo è in realtà questo ... e tu non hai un rappresentante per questo. ") Se hai abbastanza rep, dovresti modificare la risposta ed eliminare questa. –

+1

Grazie mille per la risposta a questo. Sì, è esattamente giusto; Ho avuto un catch-22 in cui non ero in grado di aggiungere un commento a quel post, o di modificare la risposta originale --- quindi non c'era alcun modo per avvisare le persone di questo oltre a creare una nuova risposta. Tutto ciò che ho provato è stato appena cancellato --- quindi, grazie per non aver eliminato questo; e tornerò e renderò questa una risposta adeguata non appena avrò abbastanza reputazione per farlo! –

Problemi correlati