在不同的数据库上运行MySQL查询

时间:2014-06-26 15:32:27

标签: mysql multiple-databases dynamic-queries

我们有一个系统,每个部门都有一个数据库,目前我们有20多个部门。

因此,当我们必须更新/删除/更改/新表时,我们必须抛弃所有这些数据库并运行查询。

有时人们不遵循程序(总是?),我们最终会得到没有更新的结构。

我正在寻找一种在所有数据库上共享相同查询的方法,而无需使用bash或外部脚本。

所以这里有一些我发现的东西:

CALL FOR EACH("SELECT databases WHERE `DATABASE` LIKE 'division_%'" , ${1});

我可以在$ {1}

中输入查询

或者这个(动力不足):

call $('{a, b}'   , 'ALTER TABLE division_${1}.caching ADD COLUMN notes VARCHAR(4096) CHARSET utf8'');

但是这给了我“没有数据库选择

关于如何处理这种情况的任何想法?

2 个答案:

答案 0 :(得分:0)

这是我找到的解决方案,它可行:

USE division_global;

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_SCHEMA LIKE 'division_%';

label1:
    LOOP
        set scName = (select schemaName from MySchemaNames limit 1);
        // The Query
        set @q = concat('TRUNCATE TABLE ', scName, '.caching');
        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
$$

受此启发:

Querying multiple databases at once

答案 1 :(得分:0)

您将需要使用存储过程和一些准备好的语句,如Simon在评论中指出的那样:

cat procedure.sql
DELIMITER $$

DROP PROCEDURE IF EXISTS alter_all $$

CREATE PROCEDURE alter_all()
BEGIN
  DECLARE done INT DEFAULT 0;
  DECLARE _schema VARCHAR(30);
  DECLARE cur CURSOR FOR select SCHEMA_NAME from information_schema.SCHEMATA where SCHEMA_NAME like 'division_%';
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := 1;

  OPEN cur;

  alterLoop: LOOP
    FETCH cur into _schema;
    if done = 1 THEN
      LEAVE alterLoop;
    END IF;
    SET @mystmt = concat('ALTER TABLE ', _schema, '.caching ADD COLUMN notes VARCHAR(4096)');
    PREPARE stmt3 FROM @mystmt;
    EXECUTE stmt3;
    DEALLOCATE PREPARE stmt3;
  END LOOP alterLoop;

  CLOSE cur;

END $$

DELIMITER ;

有了这个,让我们尝试一下(使用服务器版本:5.5.35-0ubuntu0.12.04.2(Ubuntu)):

> create schema division_1 default character set 'UTF8';
> create table division_1.caching (id int not null auto_increment primary key, value varchar(10));
> create schema division_2 default character set 'UTF8';
> create table division_2.caching (id int not null auto_increment primary key, value varchar(10));
> use division_1;
> source procedure.sql
> CALL alter_all();
Query OK, 0 rows affected, 1 warning (0.05 sec)
> desc caching;
+-------+---------------+------+-----+---------+----------------+
| Field | Type          | Null | Key | Default | Extra          |
+-------+---------------+------+-----+---------+----------------+
| id    | int(11)       | NO   | PRI | NULL    | auto_increment |
| value | varchar(10)   | YES  |     | NULL    |                |
| notes | varchar(4096) | YES  |     | NULL    |                |
+-------+---------------+------+-----+---------+----------------+
> desc division_2.caching
+-------+---------------+------+-----+---------+----------------+
| Field | Type          | Null | Key | Default | Extra          |
+-------+---------------+------+-----+---------+----------------+
| id    | int(11)       | NO   | PRI | NULL    | auto_increment |
| value | varchar(10)   | YES  |     | NULL    |                |
| notes | varchar(4096) | YES  |     | NULL    |                |
+-------+---------------+------+-----+---------+----------------+