MySQL 在表名中使用通配符
Posted
技术标签:
【中文标题】MySQL 在表名中使用通配符【英文标题】:MySQL use a wild card in table name 【发布时间】:2020-09-25 19:24:07 【问题描述】:所以我有一个软件可以在这些表上存储数据。我知道这些表是如何开始的,但它们总会有一个后缀,这是一个我不知道知道的数字
这些表名的例子是"itemid5_4423"
我知道有一个名为 itemid5 的表,但我无法知道后缀号
有没有类似这种逻辑的通配符select * from itemid5_*;
【问题讨论】:
不能在表名或字段名中使用通配符。您可以使用SHOW TABLES
了解数据库中的表。
您可以在存储过程中创建动态查询。遍历以 itemid5 开头的所有表,并创建一个查询,该查询将从每个表中提取数据。您是否正在寻找此类查询或过程的示例?
拥有多个“相同”的表通常是不好的做法,而且很笨拙。您已经找到了它笨拙的原因之一。
这两个答案对你有帮助吗,亚当?
【参考方案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%是所有需要合并的表的前缀。
【讨论】:
以上是关于MySQL 在表名中使用通配符的主要内容,如果未能解决你的问题,请参考以下文章