【问题标题】:MySQL use a wild card in table nameMySQL 在表名中使用通配符
【发布时间】:2020-09-25 19:24:07
【问题描述】:

所以我有一个软件可以在这些表上存储数据。我知道这些表是如何开始的,但它们总会有一个后缀,这是一个我不知道知道的数字 这些表名的例子是"itemid5_4423"

我知道有一个名为 itemid5 的表,但我无法知道后缀号 有没有类似这种逻辑的通配符select * from itemid5_*;

【问题讨论】:

  • 不能在表名或字段名中使用通配符。您可以使用SHOW TABLES 了解数据库中的表。
  • 您可以在存储过程中创建动态查询。遍历以 itemid5 开头的所有表,并创建一个查询,该查询将从每个表中提取数据。您是否正在寻找此类查询或过程的示例?
  • 拥有多个“相同”的表通常是不好的做法,而且很笨拙。您已经找到了它笨拙的原因之一。
  • 这两个答案对你有帮助吗,亚当?

标签: mysql mariadb


【解决方案1】:

假设您有 2 个这样的表:

create table itemid5_1111 (id int, itemname varchar(100));
create table itemid5_2222 (id int, itemname varchar(100));

您将数据插入其中:

insert into itemid5_1111 values (1, 'first table');
insert into itemid5_2222 values (2, 'second table');

您的目标是从所有 itemid5* 表中获得这样的输出。

+------+--------------+
| id   | itemname     |
+------+--------------+
|    1 | first table  |
|    2 | second table |
+------+--------------+

您可以通过键入:

          select * from itemid5_1111
union all select * from itemid5_2222;

但是,这需要大量手动输入。可以做一个存储过程动态查询itemid5开头的表名,然后动态创建SQL并执行。

存储过程

delimiter $$

drop procedure if exists get_items$$

create procedure get_items()
begin

    declare eof boolean default false;
    declare mytable varchar(255);
    declare first_run boolean default true;

    declare tablenames_cursor cursor for
        select table_name from information_schema.tables
        where table_name like 'itemid%';

    declare continue handler for not found
        set eof = true;

    set @my_query = '';

    open tablenames_cursor;
    read_loop: loop

        fetch tablenames_cursor into mytable;
        if eof then
            leave read_loop;
        end if;

        if first_run then
            set @my_query = concat('select * from ', mytable);
            set first_run = false;
        else
            set @my_query = concat(@my_query, ' union all ', 'select * from ', mytable);
        end if;

    end loop;
    close tablenames_cursor;

    prepare stmt from @my_query;
    execute stmt;
    deallocate prepare stmt;

end$$

delimiter ;

你这样调用这个过程来得到你的结果:

call get_items();

如果您像这样创建了第三张表:

create table itemid5_3333 (id int, itemname varchar(100));
insert into itemid5_3333 values (3, 'third table');

然后,你调用 proc,你会得到

call get_items();
+------+--------------+
| id   | itemname     |
+------+--------------+
|    1 | first table  |
|    2 | second table |
|    3 | third table  |
+------+--------------+

【讨论】:

    【解决方案2】:

    我认为使用数据字典来检索结果会有所帮助,运行它。

    select * from information_schema.tables where table_name like 'itemid5_% ';
    

    您可以选择此查询输出的列,table_name 是您需要的列之一,就像我们在 where 子句中使用的一样。

    【讨论】:

      【解决方案3】:
      SELECT
      REPLACE
          (
              GROUP_CONCAT(
                  CONCAT("SELECT * FROM ", `TABLE_NAME`)
              ),
              ",",
              " UNION ALL "
          )
      INTO @sq
      FROM
          information_schema.tables
      WHERE
          `TABLE_SCHEMA` = "test";
      USE
          test;
      PREPARE
          stmt1
      FROM
          @sq;
      EXECUTE
          stmt1;
      

      【讨论】:

      • 所有模式表都应该具有相同的结构,这一点很重要。我没有提到,但我只是假设它是。根据您的要求更改sql。它是从许多表中收集数据的捷径。
      【解决方案4】:
      DELIMITER //
      CREATE PROCEDURE merge_tables(IN in_sname VARCHAR(64),IN in_tname VARCHAR(64))
      READS SQL DATA
      BEGIN
        DECLARE sname VARCHAR(64);   
        DECLARE tname VARCHAR(64);
        DECLARE cname VARCHAR(64);   
        DECLARE done INT DEFAULT FALSE; 
        DECLARE table_cur CURSOR FOR SELECT table_schema, table_name FROM 
          information_schema.TABLES WHERE table_schema = in_sname AND table_name LIKE 
          'table%';
        DECLARE column_cur CURSOR FOR SELECT `COLUMN_NAME` FROM 
          `INFORMATION_SCHEMA`.`COLUMNS` where table_schema = in_sname and table_name 
          = in_tname;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
      
        -- build column list (Using the column list for table listed in second 
           parameter in PROC Call)
        SET @column = '';  
        OPEN column_cur;
        column_cur_loop: LOOP          
          FETCH column_cur INTO cname; 
          IF done THEN
            -- SET @column := CONCAT(@column, ') ');
             LEAVE column_cur_loop;
          END IF;
          IF @column = '' THEN    
            SET @column := CONCAT(@column,cname);
          ELSE
            SET @column := CONCAT(@column,',',cname);
          END IF;
        END LOOP;
        CLOSE column_cur;
      
      
        -- Build UNION Query for all table starting with table%)
        SET done = FALSE;
        SET @sql = '';  
        OPEN table_cur;
          table_list_loop: LOOP                 
              FETCH table_cur INTO sname, tname; 
              IF done THEN
                LEAVE table_list_loop;
              END IF;
      
              IF @sql = '' THEN    
                SET @sql := CONCAT('INSERT INTO MERGED_TABLE (', @column , ') SELECT 
                ', @column , ' FROM `', sname, '`.`', tname, '`');
              ELSE
                SET @sql := CONCAT(@sql, ' UNION ALL SELECT ' , @column , ' FROM `', 
                sname, '`.`', tname, '`');
              END IF;
            END LOOP;
            CLOSE table_cur;
      
      
        PREPARE stmt FROM @sql;  -- prepare and execute the dynamically
        EXECUTE stmt;            -- created query.
        DEALLOCATE PREPARE stmt;  
      
      END //
      
      DELIMITER ;`    
      

      调用 merge_tables(testdb,table1)


      • testdb 是表所在的架构名称
      • table1 是需要合并以获取列名的表之一
      • 过程中的table%是所有需要合并的表的前缀。

      【讨论】:

        猜你喜欢
        • 2021-11-27
        • 1970-01-01
        • 2011-02-09
        • 1970-01-01
        • 2012-03-22
        • 2012-07-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多