迭代MySQL模式

迭代MySQL模式,mysql,stored-procedures,Mysql,Stored Procedures,问题描述 我有一个单租户MySQL数据库设置。也就是说,每个客户机都有一个相同的模式 现在我需要为每个客户机运行一个特定的查询。在多租户设置中(所有客户端共享一个模式),这将很容易做到。然而,在我的设置中,我需要迭代模式。更一般地说,我想访问一个模式,其名称由一个变量给出。如何做到这一点 我尝试过的 如果我尝试使用varSchemaName(其中varSchemaName是varchar 变量),我得到错误消息error 1314:不允许使用 在存储过程中 如果我尝试从varSchemaNam

问题描述

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

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

我尝试过的

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

  • 如果我尝试
    从varSchemaName.MyTable中选择*
    错误代码:1146。表“varSchemaName.MyTable”不存在。显然,MySQL认为
    varSchemaName
    是一个文本,而不是一个 变数


    • 您必须首先构建语句

      SET @sql = CONCAT('SELECT * FROM ', varSchemaName, '.MyTable');
      PREPARE stmt FROM @sql;
      EXECUTE stmt;
      DEALLOCATE PREPARE stmt;
      
      您可以阅读有关准备好的语句的更多信息


      您可能会尝试将变量用于表名,但这不起作用。这些参数用于where子句中的值等。上面的方法就是正确的方法。

      基于fancyPants的答案,您可以在另一个过程的循环中调用该过程,该过程查询信息\u 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();
      

      谢谢,我自己刚刚尝试过这个,它似乎起作用了。如果我的查询既长又复杂,那么除了将sql代码粘贴到字符串中之外,还有没有更好的方法来声明
      @sql
      变量呢?恐怕没有更好的方法了。我发现,通过这种方法,您可以查询单租户数据库设置,就像查询多租户一样。这是难以置信的强大,并将解决我的头痛很多。不幸的是,它不能用于发出
      创建
      语句。