在程序上规范化MySQL中的表数据

时间:2013-02-04 19:17:47

标签: mysql normalization

我有一个非规范化格式的大型数据集。以下是列名称的示例:

foreign_key_ID,P1,P2,P3,P4,P5 ...... D1,D2,D3 ......等。

这些字段都包含相似类型的数据。

我需要将其规范化为现有的表结构:

insert into new_table (id, name, index)
select foreign_key_id, P1, 1
from denormalized_table;

但这意味着我需要为我的非规范化表中的每个字段运行单独的查询,只需更改一些内容:

insert into new_table (id, name, index)
select foreign_key_id, P2, 2
from denormalized_table;

考虑到我有多少这些领域,这变得乏味。

有没有办法可以将其自动化为单一操作?即:遍历字段(我不介意在某处创建一个符合条件的字段列表),拉出该字段名称的最后一位数字(即“P1”中的“1”和“P2”中的“2”)在子选择中使用字段名称和提取的索引#。

2 个答案:

答案 0 :(得分:1)

你正在寻找的是动态SQL。这是您执行可以以编程方式汇编的SQL语句的位置。只要您在存储过程中,就可以运行字符串中的任意SQL代码。请看这个链接:How To have Dynamic SQL in MySQL Stored Procedure

基本上,您可以通过迭代一组列来使用mySQL语句构建字符串。您可以使用SHOW COLUMNS语法(请参阅http://dev.mysql.com/doc/refman/5.0/en/show-columns.html)返回一个集合,然后循环该结果集并构建您的动态查询字符串并以此方式执行。

SHOW COLUMNS FROM myTable WHERE Field NOT IN (pkey, otherFieldIDontWantToInclude)

答案 1 :(得分:1)

这是一个开始:

SELECT column_name, substr(column_name,2) AS `index`
  FROM information_schema.columns
 WHERE table_schema = 'mydatabasename'
   AND table_name = 'denormalized_table'
   AND column_name REGEXP '^[PD][0-9]+$'
 ORDER BY column_name

您可以修改该语句中的选择列表,让MySQL为您生成语句:

SELECT CONCAT('INSERT INTO new_table (id, name, `index`) SELECT foreign_key_id, '
         ,column_name,', ',substr(column_name,2)
         ,' FROM denormalized_table ;') AS stmt
  FROM information_schema.columns
 WHERE table_schema = 'mydatabasename'
   AND table_name = 'denormalized_table'
   AND column_name REGEXP '^[PD][0-9]+$'
 ORDER BY column_name

该输出将是一组您可以执行的MySQL INSERT语句。


如果要插入的数据的行数和总大小不是太大,您可以并且希望在“一个操作”中完成整个转换,那么您可以生成一个INSERT INTO ... SELECT语句,使用UNION ALL运算符。我会得到这样的大部分陈述:

SELECT CONCAT('UNION ALL SELECT foreign_key_id, '
         ,column_name,', ',substr(column_name,2)
         ,' FROM denormalized_table ') AS stmt
  FROM information_schema.columns
 WHERE table_schema = 'mydatabasename'
   AND table_name = 'denormalized_table'
   AND column_name REGEXP '^[PD][0-9]+$'
 ORDER BY column_name

我会从中获取输出,并将第一个UNION ALL替换为INSERT INTO ...。这将给我一个单独的声明来完成整个转换。