在一个MYSQL中连接具有相同结构的所有表

在一个MYSQL中连接具有相同结构的所有表,mysql,Mysql,我正在处理一个已经使用多年的旧数据库,它的设计非常糟糕。 有一个表“Articles”,其中包含一个“code”列,它将成为我们的主键。 还有许多像“idXXXXX”这样的表,其中XXXXX是一个结构完全相同的“代码”值。 我查看了使用该数据库的应用程序,发现表之间的关系是在那里建立的 我并不害怕在应用程序中重新设计数据库访问,但我不想丢失数据库中多年的条目 我想创建一个“campain”表,它将有一个“id”主键和一个“id_代码”作为FK链接“campain”到“articles” 我不是S

我正在处理一个已经使用多年的旧数据库,它的设计非常糟糕。 有一个表“Articles”,其中包含一个“code”列,它将成为我们的主键。 还有许多像“idXXXXX”这样的表,其中XXXXX是一个结构完全相同的“代码”值。 我查看了使用该数据库的应用程序,发现表之间的关系是在那里建立的

我并不害怕在应用程序中重新设计数据库访问,但我不想丢失数据库中多年的条目

我想创建一个“campain”表,它将有一个“id”主键和一个“id_代码”作为FK链接“campain”到“articles”

我不是SQL高手,但我知道我可以使用

SELECT TABLE_NAME FROM INFORMATION_SCHEMA WHERE TABLE_NAME LIKE 'id%'
但我真的不知道如何处理结果(这很好)。 那么,我如何访问每个名为“idXXX”的表,并在“campain”表中插入每一行,并将“id_code”列设置为“XXX”


以下是我保存的过程(出于测试目的,我没有在插入行中添加所有字段):

如您所见,我将“idXXXXX”分为“XXXXX”,然后将其转换为整数(带符号)。 但是我猜在“INSERT-INTO”行中,第二个tableName没有指向变量。这就是为什么我得到了一份工作
“#1446-table'bddsoufflage.tablename'不存在”错误:)有什么想法吗?

最简单的方法是在一些脚本(PHP、Python、Perl,以最适合您的为准)中运行信息模式查询,并使用其结果创建如下查询:

INSERT INTO 
  campain (id, id_code, otherfields)
SELECT
  null, 'idXXXX', otherfields FROM idXXXX

编辑:更新答案

我们不能在一个prepared语句中动态更改表名,所以我们必须使用DynamicSQL来使用CONCAT构建查询,然后使用PREPARE编译SQL,执行它并取消分配它

DELIMITER //
CREATE PROCEDURE JoinAllTables()
BEGIN

 DECLARE done INT default 0;
 DECLARE tableName CHAR(9); 
 DECLARE buffStr CHAR(7);
 DECLARE buffId INT default 0;

 DECLARE cur1 CURSOR FOR SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE 'id%'; 
 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

 OPEN cur1;

 read_loop: LOOP
    FETCH cur1 INTO tableName;
    IF done THEN
       LEAVE read_loop;
    END IF;

  SET buffStr = SUBSTRING(tableName, 3);
  SET buffId = CAST(buffStr AS SIGNED);

  set @sql = CONCAT("INSERT INTO campagnes(id, id_code) SELECT null, ", buffId, " FROM ",tableName); # Dynamically building sql statement 
  PREPARE stmt FROM @sql;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt; 

  END LOOP;
  CLOSE cur1;
END; //
请参见此答案

旧答案 程序应该是这样的。感谢Mchl提供了一个Insert Into查询示例,我只是将其添加到过程的其余部分

DELIMITER //
CREATE PROCEDURE JoinAllTables()
BEGIN

 DECLARE done INT default 0;
 DECLARE tableName CHAR(7); # Variable to contain table names CHAr(7) is assuming id + 5Xs as characters.

 DECLARE cur1 CURSOR FOR SELECT TABLE_NAME FROM INFORMATION_SCHEMA WHERE TABLE_NAME LIKE 'id%'; # Create a cursor to iterate over the tables
 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

 OPEN cur1;

 read_loop: LOOP
    FETCH cur1 INTO tableName;
    IF done THEN
      LEAVE read_loop;
    END IF;

    #Your Insert statement here, using tableName as a field.
INSERT INTO campain (id, id_code, otherfields) SELECT null, tableName, otherfields FROM tableName;

  END LOOP;
  CLOSE cur1;
END;//

嗯,我会试试看,但是有没有一种方法可以在纯SQL中实现呢?有,请参阅@NetSquirell的答案;)我只是不喜欢这样写存储过程;非常感谢,我会尝试,但在MYSQL中,我不认为我可以使用像“idXXXX”这样的字段作为主键,也许我应该删除“id”部分并将“XXXX”转换为INT?是的,您可能希望将表名重新处理为其他内容,使用SUBSTRING()函数提取xxx,然后使用CAST()将其转换为数字函数。我在第4行得到一个错误=/(DECLARE tableName CHAR(7);)谈论“”附近的语法错误,这很奇怪,因为我试图删除整行(在复制/粘贴错误的情况下),但它没有更改任何内容。是的,很抱歉,我在离开之前急于添加注释,我省略了分隔符//以使MySQL接受MySQL>提示符上的过程。我还忘了声明done变量。您可能还需要将游标选择查询和插入查询调整到数据库中的特定表中。非常感谢!今天晚些时候我会看一看。
DELIMITER //
CREATE PROCEDURE JoinAllTables()
BEGIN

 DECLARE done INT default 0;
 DECLARE tableName CHAR(7); # Variable to contain table names CHAr(7) is assuming id + 5Xs as characters.

 DECLARE cur1 CURSOR FOR SELECT TABLE_NAME FROM INFORMATION_SCHEMA WHERE TABLE_NAME LIKE 'id%'; # Create a cursor to iterate over the tables
 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

 OPEN cur1;

 read_loop: LOOP
    FETCH cur1 INTO tableName;
    IF done THEN
      LEAVE read_loop;
    END IF;

    #Your Insert statement here, using tableName as a field.
INSERT INTO campain (id, id_code, otherfields) SELECT null, tableName, otherfields FROM tableName;

  END LOOP;
  CLOSE cur1;
END;//