数据库是mysql / mariaDB。
我的数据库旨在存储有关某事的月度报告。他们的名字是(例子):table1,table2,table3 ......
我想创建将创建/重新创建包含所有表union(union ALL)的视图的函数/过程。
类似的东西:
1.首先从信息模式中选择所有表名。
SELECT TABLE_NAME from information_schema.`TABLES` where TABLE_NAME like 'table%'
但我在第一步遇到问题,我尝试仅合并一个固定表+第一个查询中的一个,并向我返回错误。
我试试:
select * from `table4`
UNION
SELECT * from (SELECT TABLE_NAME from information_schema.`TABLES`
where TABLE_NAME like 'table%' limit 1) as dd
它返回错误:使用的SELECT语句具有不同数量的列, 但是当我执行子查询时,我得到1个具有正确表名的结果,并且当我在没有子查询的from子句中设置该名称时,它可以工作。
知道它为什么会发生,也许还有一些建议如何实现这种动态联合。
答案 0 :(得分:1)
我认为有点推动可以帮助您正确处理这个问题。
首先,正如Tim Biegeleisen所说,继续的方法是使用动态SQL,如果在尝试运行查询之前无法绝对确定表名,这是唯一的途径。
其次,你认为你需要从查询information_schema.TABLE开始是正确的,你应该使用CURSOR来做。然后应该使用该查询的结果来构建一个查询字符串,然后使用PREPARE和EXECUTE。
第三,我认为您在帖子中包含的错误消息特指运行该查询,并不表示每月表格有任何不同。除非每个部分的结果返回相同数量的列,否则您无法执行UNION。
第四,因为我们要动态构建查询,这必须在存储过程中完成,所以无法在存储函数中完成。
有关使用CURSOR和PREPARE/EXECUTE的mysql文档中有很好的教程,您应该阅读这些教程。我在下面给出的版本将基于这些示例。我假设唯一的输入参数是模式名称(如果您碰巧在服务器上的另一个数据库中有一些类似命名的表)。
DELIMITER //
DROP PROCEDURE IF EXISTS dyn_union //
CREATE PROCEDURE dyn_union(IN v_sname VARCHAR(64))
READS SQL DATA
BEGIN
-- NB the order of declaration for variables cursor
-- and handler must be strictly observed
DECLARE sname VARCHAR(64); -- variable the schema names
DECLARE tname VARCHAR(64); -- variable the table names
DECLARE done INT DEFAULT FALSE; -- cursor control variable
DECLARE cur1 CURSOR FOR
SELECT table_schema, table_name
FROM information_schema.TABLES
WHERE table_schema = v_sname
AND table_name LIKE 'table%';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET @sql = ''; -- build the query string in this var
OPEN cur1;
read_loop: LOOP -- loop over the rows returned by cursor
FETCH cur1 INTO sname, tname; -- fetching the schema and table names
IF done THEN
LEAVE read_loop;
END IF;
IF @sql = '' THEN -- build the select statement
SET @sql := CONCAT('SELECT * FROM `', sname, '`.`', tname, '`');
ELSE
SET @sql := CONCAT(@sql, ' UNION ALL SELECT * FROM `', sname, '`.`', tname, '`');
END IF;
END LOOP;
CLOSE cur1;
select @sql;
PREPARE stmt FROM @sql; -- prepare and execute the dynamically
EXECUTE stmt; -- created query.
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
-- call the procedure
CALL dyn_union('your_db_name');