MySQL在所有前缀数据库表中创建视图

时间:2015-02-23 15:03:22

标签: mysql sql replication

我有名为company_abccompany_xyz等的数据库。这些company_*数据库具有相同的结构,并且包含users表。

我需要做的是从仅company_*数据库聚合所有用户数据,并将此视图复制到另一台服务器。视图就像是

COMPANY NAME | USERNAME
abc          | user@email.com
abc          | user1@email.com
xyz          | user2@email.com
company3     | user3@email.com

在MySQL中是否可以这样?

动态创建数据库以及用户,因此我无法仅使用静态数据库集创建视图。

4 个答案:

答案 0 :(得分:1)

要查找数据库名称列表:

SELECT SCHEMA_NAME
    FROM information_schema.`SCHEMATA`
    WHERE SCHEMA_NAME LIKE 'company%';

如果您可以编写类似PHP的代码,其余的很简单 - 从每个数据库构建一个UNION of SELECTs。但是,如果你必须在SQL中做到这一点......

要构建UNION,请编写存储过程。它将在CURSOR中执行上述查询。在遍历游标的循环内部,CONCAT()将构造的SELECT构建到您正在构建的UNION上。

循环结束后,PREPARE并执行构造的UNION。这将提供类似你的输出示例。

但是,如果您现在需要将其结果插入到另一台服务器中,则应该保留存储过程的范围并使用其他语言。

好的,好的,如果你必须保留在SQL中,那么你需要一些设置:创建一个" Federated"连接到其他服务器的表。现在,在您的SP中,在UNION前面连接INSERT INTO fed_tbl。然后执行应该完成整个任务。

如果您在使用FEDERATED引擎时遇到问题,则可能需要切换到MariaDB中的FederatedX。

"详细信息留给读者练习。"

答案 1 :(得分:1)

正如您所说,您希望使用动态数据库名称创建视图 - 因此在当前版本的mysql中无法实现您想要实现的结果。

所以你有以下例子:

选项1

如果要获取所有数据库用户表的结果,可以定义使用预准备语句的存储过程。此过程需要参数db_prefix,在您的情况下 company _%。基本上,当数据库名称类似于db_prefix参数值时,此过程从 information_schema 中选择名为用户的所有表。之后,它循环遍历结果并创建查询字符串作为union all users表并执行此查询。在创建查询字符串时,我还添加了一个名为source的字段,因此我可以从哪个数据库中识别此结果。在我的示例中,我的数据库都是默认排序规则utf8_unicode_ci。

在这种情况下,您可以定义过程示例" getAllUsers"

-- Dumping structure for procedure company_abc1.getAllUsers
DELIMITER //
CREATE DEFINER=`root`@`localhost` PROCEDURE `getAllUsers`(IN `db_prefix` TEXT)
    DETERMINISTIC
    COMMENT 'test'
BEGIN
    DECLARE qStr TEXT DEFAULT '';
    DECLARE cursor_VAL VARCHAR(255) DEFAULT '';
    DECLARE done INTEGER DEFAULT 0;
    DECLARE cursor_i CURSOR FOR SELECT DISTINCT (table_schema) FROM information_schema.tables WHERE table_name = 'users' AND table_schema LIKE db_prefix COLLATE utf8_unicode_ci;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    OPEN cursor_i;
    read_loop: LOOP
        FETCH cursor_i INTO cursor_VAL;
        IF done = 1 THEN
        LEAVE read_loop;
        END IF;
        IF qStr != '' THEN
            SET qStr = CONCAT(qStr, ' UNION ALL ');
        END IF;
        SET qStr = CONCAT(qStr, ' SELECT *, \'', cursor_VAL ,'\' as source FROM ', cursor_VAL, '.users');
    END LOOP;
    CLOSE cursor_i;

    SET @qStr = qStr;

    PREPARE stmt FROM @qStr;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    SET @qStr = NULL;
END//
DELIMITER ;

现在,您可以将所有用户的结果显示为:

CALL getAllUsers('company_%');

在我的示例数据库中,结果为:

id  name    source
1   User 1  company_abc1
2   User 2  company_abc1
3   User 3  company_abc1
1   User 1  company_abc2
2   User 2  company_abc2
3   User 3  company_abc2
1   User 1  company_abc3
2   User 2  company_abc3
3   User 3  company_abc3
1   User 1  company_abc4
2   User 2  company_abc4
3   User 3  company_abc4
1   User 1  company_abc5
2   User 2  company_abc5
3   User 3  company_abc5

选项2

如果你确实需要查看,那么你可以修改第一个程序而不是执行选择你可以创建视图。像这样的例子:

-- Dumping structure for procedure company_abc1.createAllUsersView
DELIMITER //
CREATE DEFINER=`root`@`localhost` PROCEDURE `createAllUsersView`(IN `db_prefix` TEXT)
    DETERMINISTIC
    COMMENT 'test'
BEGIN
    DECLARE qStr TEXT DEFAULT '';
    DECLARE cursor_VAL VARCHAR(255) DEFAULT '';
    DECLARE done INTEGER DEFAULT 0;
    DECLARE cursor_i CURSOR FOR SELECT DISTINCT (table_schema) FROM information_schema.tables WHERE table_name = 'users' AND table_schema LIKE db_prefix COLLATE utf8_unicode_ci;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    OPEN cursor_i;
    read_loop: LOOP
        FETCH cursor_i INTO cursor_VAL;
        IF done = 1 THEN
        LEAVE read_loop;
        END IF;
        IF qStr != '' THEN
            SET qStr = CONCAT(qStr, ' UNION ALL ');
        END IF;
        SET qStr = CONCAT(qStr, ' SELECT *, \'', cursor_VAL ,'\' as source FROM ', cursor_VAL, '.users');
    END LOOP;
    CLOSE cursor_i;

    SET @qStr = CONCAT('CREATE OR REPLACE VIEW allUsersView AS ', qStr);
    PREPARE stmt FROM @qStr;
   EXECUTE stmt;
    DEALLOCATE PREPARE stmt;  
    SET @qStr = NULL;
END//
DELIMITER ;

在这个存储过程中,我们创建/替换名为 allUsersView 的视图,所以基本上每次执行此过程时它都会更新视图。 在我的测试用例中,它创建了这样的视图:

CREATE OR REPLACE VIEW `allusersview` AS 
    SELECT *, 'company_abc1' as source FROM company_abc1.users 
    UNION ALL  SELECT *, 'company_abc2' as source FROM company_abc2.users 
    UNION ALL  SELECT *, 'company_abc3' as source FROM company_abc3.users 
    UNION ALL  SELECT *, 'company_abc4' as source FROM company_abc4.users 
    UNION ALL  SELECT *, 'company_abc5' as source FROM company_abc5.users ;

现在你可以使用view。

SELECT * FROM allusersview

结果与第一个选项相同。

全部测试:

Mysql 5.6.16

答案 2 :(得分:0)

我已将此标记为Mysql union from multiple database tables

的副本
(SELECT *, 'abc' as COMPANY_NAME from company_abc.users)
union
(SELECT *, 'xyz' as COMPANY_NAME from company_xyz.users)
union
(SELECT *, 'company3' as COMPANY_NAME from company_company3.users)
...

答案 3 :(得分:0)

我认为唯一的方法是编写一个从information_schema.table读取所有数据库和表名的存储过程,使用union select * from company_abc.users union all select * from company_xyz构建一个字符串,然后使用prepared statement执行命令:{ {3}}