【问题标题】:mysql - create dynamic unionmysql - 创建动态联合
【发布时间】:2018-09-30 01:48:31
【问题描述】:

数据库是mysql/mariaDB。

我的数据库旨在存储有关某事的月度报告。他们的名字是(例子):table1, table2, table3...

我想创建将创建/重新创建包含所有表联合(联合所有)的视图的函数/过程。

类似:
1.首先从信息模式中选择所有表名。

SELECT TABLE_NAME from information_schema.`TABLES` where TABLE_NAME like 'table%'  
  1. 然后我会尝试在某个循环中设置它以使用来自第一个查询的结果集。

但我的第一步有问题,我尝试只合并一个固定表 + 一个来自第一个查询的固定表,它返回错误给我。

我试试:

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 子句中设置该名称时,它可以工作。

知道为什么会发生这种情况,也许还有一些建议如何实现这种动态联合。

【问题讨论】:

  • 我不知道该怎么做,但你需要在这里使用动态 SQL。目前,您正在尝试选择 FROM 一个字符串,not 一个表,所以它当然失败了。
  • 我知道这些不是动态 sql,但我尝试从结果集中传递一条记录。作为 from 子句的表名。就像在 php 示例中一样,循环遍历某个数组或结果集并将每个数组或结果集传递给某个函数。但现在看起来我错过了一切,因为 sql 中的动态完全以另一种方式工作。

标签: mysql dynamic union


【解决方案1】:

我认为稍微推动一下将帮助您找到处理此问题的正确方法。

首先,正如 Tim Biegeleisen 所建议的,继续进行的方法是使用动态 SQL,如果在尝试运行查询之前无法绝对确定表名,这是您唯一的途径。

其次,您认为需要从查询 information_schema.TABLE 开始是正确的,您应该使用 CURSOR 来完成。然后应该使用该查询的结果来构建一个查询字符串,然后您可以准备和执行该查询字符串。

第三,我认为您在帖子中包含的错误消息专门指的是该查询的运行,并不表示月表有任何不同。除非每个部分的结果返回相同数量的列,否则您不能执行 UNION。

第四,因为我们要动态构建查询,这必须在存储过程中完成,不可能在存储函数中完成。

mysql 文档中有很好的使用CURSORPREPARE/EXECUTE 的教程,你应该阅读。我在下面给出的版本将基于这些示例。我假设唯一的输入参数将是模式名称(如果您碰巧在服务器上的另一个数据库中有一些类似命名的表)。

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');

【讨论】:

    猜你喜欢
    • 2018-07-02
    • 1970-01-01
    • 2021-09-03
    • 2014-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-20
    • 1970-01-01
    相关资源
    最近更新 更多