迭代MySQL模式

时间:2012-12-11 10:11:19

标签: mysql stored-procedures

问题描述

我有一个单租户MySQL数据库设置。也就是说,每个客户端都有一个相同的架构。

现在我需要为每个客户端运行一个特定的查询。这在多租户设置中很容易(所有客户端共享一个模式)。但是,在我的设置中,我需要迭代模式。 更一般地说,我想访问一个名称由变量赋予的模式。如何做到这一点?

我尝试了什么

  • 如果我尝试USE varSchemaName(其中varSchemaNamevarchar 变量),我收到错误消息 ERROR 1314:不允许使用USE 在存储过程中

  • 如果我尝试SELECT * FROM varSchemaName.MyTable,我会得到 错误代码:1146。表'varSchemaName.MyTable'不存在。显然MySQL认为varSchemaName是文字而不是文字 变量

2 个答案:

答案 0 :(得分:2)

你必须先建立声明。

SET @sql = CONCAT('SELECT * FROM ', varSchemaName, '.MyTable');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

您可以阅读有关准备好的陈述 here 的更多信息。

您可能想要使用表名的变量,但这不起作用。这些参数用于where子句中的值等。上面的方法是要走的路。

答案 1 :(得分:1)

根据fancyPants的答案,您可以在另一个查询information_schema.tables的过程的循环中调用该过程,以识别包含MyTable的数据库,然后使用db名称作为参数调用fancyPants的过程。如果数据库具有一致的命名方案或包含具有相同名称的对象,则此方法很容易,这听起来像这里的情况。结构将类似于:

DELIMITER //

DROP PROCEDURE IF EXISTS mydriver //
CREATE PROCEDURE mydriver()
BEGIN

  DECLARE varSchemaName VARCHAR(64);
  DECLARE done BOOLEAN;
  DECLARE cur CURSOR FOR
    SELECT table_schema
    FROM information_schema.tables
    WHERE table_name = 'MyTable';

  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur;
    read_loop: LOOP
      FETCH cur INTO varSchemaName;
      IF done THEN
        LEAVE read_loop;
        CLOSE cur;
      END IF;

      CALL fancypants_proc(varSchemaName);

    END LOOP;
END //

DROP PROCEDURE IF EXISTS fancypants_proc //
CREATE PROCEDURE fancypants_proc(IN varSchemaName VARCHAR(64))
BEGIN

  SET @sql = CONCAT('SELECT * FROM ', varSchemaName, '.MyTable');
  PREPARE stmt FROM @sql;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;

END //

DELIMITER ;

CALL mydriver();