问题描述
我有一个单租户MySQL数据库设置。也就是说,每个客户端都有一个相同的架构。
现在我需要为每个客户端运行一个特定的查询。这在多租户设置中很容易(所有客户端共享一个模式)。但是,在我的设置中,我需要迭代模式。 更一般地说,我想访问一个名称由变量赋予的模式。如何做到这一点?
我尝试了什么
如果我尝试USE varSchemaName
(其中varSchemaName
是varchar
变量),我收到错误消息 ERROR 1314:不允许使用USE
在存储过程中。
如果我尝试SELECT * FROM varSchemaName.MyTable
,我会得到
错误代码:1146。表'varSchemaName.MyTable'不存在。显然MySQL认为varSchemaName
是文字而不是文字
变量
答案 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();