从可变数量的表中联合。 (重载存储的MySQL过程)

时间:2011-12-09 19:53:14

标签: mysql stored-procedures

我有10个具有相同架构的表。我正在尝试创建一个重载的存储过程,以便我可以将一堆表与简单的选择(SELECT * FROM tableX)结合在一起。如果每个表有1000(不同)行,那么我想创建一个存储过程,其中将发生以下情况:

CALL getRowsByNum(table1); -> 1000 rows
CALL getRowsByNum(table1, table2, table4); -> 3000 rows

...等

我通过编写10个重载程序(SELECT * FROM X UNION ALL SELECT * FROM X UNION ALL .....等)得到了部分内容,但这确实是疯狂

有人有不同的建议吗?这种愚蠢的设置是不久前做出的架构决策的结果。

谢谢!

2 个答案:

答案 0 :(得分:4)

我同意您必须重新考虑您的数据库结构。 顺便说一句,只是为了好玩:)

drop database if exists my_test;

create database my_test;

use my_test;

create table table1 (
id int not null auto_increment primary key,
my_field varchar(10)
) engine = myisam;

create table table2 like table1;
create table table3 like table1;
create table table4 like table1;
create table table5 like table1;

insert into table1 (my_field) values ('aaa'),('bbb');
insert into table2 (my_field) values ('ccc'),('ddd'),('eee');
insert into table3 (my_field) values ('fff'),('ggg');
insert into table4 (my_field) values ('hhh'),('iii'),('jjj');
insert into table5 (my_field) values ('kkk'),('lll');


delimiter //
drop procedure if exists tables_union //
create procedure tables_union (in str varchar(10000),in db varchar(100))
begin
set @qry = (select group_concat(concat('select * from ',table_name) separator ' union all ')
            from information_schema.tables
            where find_in_set(table_name,str) 
            and table_schema = db);
-- select @qry;
prepare stmt from @qry;
execute stmt;
deallocate prepare stmt;            

end; //
delimiter ;

call tables_union('table4,table3,table1','my_test');

+----+----------+
| id | my_field |
+----+----------+
|  1 | aaa      |
|  2 | bbb      |
|  1 | fff      |
|  2 | ggg      |
|  1 | hhh      |
|  2 | iii      |
|  3 | jjj      |
+----+----------+
7 rows in set (0.00 sec)

答案 1 :(得分:1)

不是真的。您不能使用相同名称的可变数量的参数或过程。

我不认为你的问题有一个简单的解决方案。

编辑:我想到了一个非常丑陋的解决方案,但如果您想使用它,我会留给您。这是未经测试的伪代码。

创建一个proc,其中包含varchar,足够长以保存值“table1,table2,table3,...”等等,以便最多可以合并多个表。 (当然可以是另一个标识符)

将所有表格写入联合。因为它们是相同的只是使用*来节省时间和空间

delimiter //

create procedure megaunion (tables varchar(255)) 
begin 
   select * from table1 where find_in_set('table1', tables)   
   union
   select * from table2 where find_in_set('table2', tables)
   ....
end//

列出所有表格。至少你不必列出可能的排列,程序的用户也不会知道你是怎么做的:)