2

问题描述

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

现在我需要为每个客户端运行一个特定的查询。这在多租户设置(所有客户端共享一个模式)中很容易。但是,通过我的设置,我需要迭代模式。更一般地说,我想访问一个名称由变量给出的模式。怎么可能呢?

我试过的

  • 如果我尝试USE varSchemaName( 变量在哪里),我会收到错误消息varSchemaNameERROR 1314: USE is not allowed in stored proceduresvarchar

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

4

2 回答 2

1

您必须先构建语句。

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

您可以在此处阅读有关准备好的语句的更多信息。

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

于 2012-12-11T10:32:21.677 回答
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();
于 2017-11-10T23:44:21.883 回答