在运行以下查询MYSQL
时抱怨:表'DB.tableName'
不存在。
CREATE PROCEDURE CountSignatures()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE signatureCount INT;
DECLARE tableName CHAR(100);
DECLARE tableList CURSOR FOR Select table_name from information_schema.tables where table_name like "%FAULT_20150320%";
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET signatureCount = 1;
OPEN tableList;
tableListLoop: LOOP
SET done = FALSE ;
FETCH tableList INTO tableName;
IF done THEN
LEAVE tableListLoop;
END IF;
**Select count(distinct signature) from tableName;**
END LOOP;
CLOSE tableList;
END$$
如果我使用以下查询,则正确打印tableName
变量值:
CREATE PROCEDURE CountSignatures()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE signatureCount INT;
DECLARE tableName CHAR(100);
DECLARE tableList CURSOR FOR Select table_name from information_schema.tables where table_schema="LogData" and table_name like "%FAULT_20150320%";
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET signatureCount = 1;
OPEN tableList;
tableListLoop: LOOP
SET done = FALSE ;
FETCH tableList INTO tableName;
IF done THEN
LEAVE tableListLoop;
END IF;
**Select tableName;**
END LOOP;
CLOSE tableList;
END$$
答案 0 :(得分:0)
FROM
语句的SELECT
部分必须包含实际的表名,而不是包含表名的CHAR(100)
变量。它不会像这样工作。
看起来您希望针对数据库中具有类似结构的许多表运行特定查询。通常,这意味着可以改进数据库模式。但是,如果你必须处理你拥有的东西,你将不得不使用dynamic SQL。这个指向MySQL文档的链接有一个示例"它演示了如何选择在运行时执行查询的表,方法是将表的名称存储为用户变量",这正是您所需要的。
在循环内部,您需要使用SQL查询构建一个字符串并使用EXECUTE
。
SET @s = CONCAT('select count(distinct signature) from ', tableName);
PREPARE stmt FROM @s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
据我所知,EXECUTE
的结果被发送给存储过程的调用者,就像它是正常的SELECT
一样,所以在这个例子中,调用者将收到多个结果集如果您的数据库有多个表where table_name like "%FAULT_20150320%"
。
以下是关于MySQL动态SQL How To have Dynamic SQL in MySQL Stored Procedure的另一个SO问题的链接,其中包含一些示例。
看起来你想要这样的东西。它应该总结signatureCount
变量中的几个表的计数。
CREATE PROCEDURE CountSignatures()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE signatureCount INT;
DECLARE tableName CHAR(100);
DECLARE tableList CURSOR FOR SELECT table_name FROM information_schema.tables WHERE table_name LIKE "%FAULT_20150320%";
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET signatureCount = 0;
OPEN tableList;
tableListLoop: LOOP
SET done = FALSE;
FETCH tableList INTO tableName;
IF done THEN
LEAVE tableListLoop;
END IF;
SET @VarCount = 0;
SET @VarSQL = CONCAT('SET @VarCount = (SELECT COUNT(DISTINCT signature) FROM ', tableName, ')');
PREPARE stmt FROM @VarSQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET signatureCount = signatureCount + @VarCount;
END LOOP;
CLOSE tableList;
SELECT signatureCount;
END$$
另一个变体,如果你需要处理的表的数量不多,那就是动态构建一个包含循环内所有表的大SQL语句,然后一次性EXECUTE
:
SELECT
(COUNT(DISTINCT signature) FROM Table1) +
(COUNT(DISTINCT signature) FROM Table2) +
...
(COUNT(DISTINCT signature) FROM TableN) AS TotalCount
答案 1 :(得分:0)
我有时也碰到这个,并且使用了一个非常简单的技巧。我这样做(需要Excel或Google表格[警告:我没有使用Google表格测试过程]):
SELECT table_name FROM information_schema.tables where table_schema='your_database_name'
以获取表格列表(MySQL)。首先在一个表中测试您的查询,然后在准备好后,将查询复制到列" B"对于MS Excel,有一个字符串限制,所以你需要连接字符串(我只是逐行):
="ALTER TABLE `mydatabasename`.`"&A1&"`
"&"CHANGE COLUMN `created` `created` DATETIME NOT NULL COMMENT 'Comment here...' ,
"&"CHANGE COLUMN `updated` `updated` DATETIME NOT NULL COMMENT 'Comment here...' ;"&
"&"...etc...
"&"...etc...
"&"...etc...
"
开头的"&"
需要从上一行捕获新的行字符。
"
,则必须将其删除。如果在MySQL Workbench中只需按Ctrl + H并将所有"
替换为空(将第二个框留空)。这实际上很有效,因为公式中的双引号在大多数情况下与SQL文本不会发生冲突。此外,我将这些行连接为字符串,但您可以将每一行作为单独的工作表上的单独行进行尝试,并使用公式来连接这种方式。我确信有创意的人可以找到其他类似的方式。
当然,这个想法适用于任何带有微小调整的数据库,因此这是一个优点。 ;)