如何翻译和迁移数据

时间:2009-09-21 17:51:22

标签: php csv ms-access data-migration

我正在构建php web应用程序,让用户上传MS Access数据库(csv导出),然后将其翻译并迁移到MySQL数据库中。

MS Access数据库由一个名为t_product(100k行)的表组成。这个表设计得不好。例如,以下查询:

SELECT part_number, model_number FROM t_product

将返回:

part_number model_number
100  AX1000, AX1001, AX1002
101  CZ10, CZ220, MB100

如您所见,型号列为逗号分隔值,而不是另一个表中的单个记录。还有更多这种性质的问题。我正在编写一个脚本来清理这些数据,然后再导入mysql数据库。该脚本还将现有的Access列映射到适当的关系设计数据库。

我的问题是我的脚本需要很长时间才能完成。这是解释我正在做什么的简化代码:

$handle = fopen("MSAccess.csv, "r");

// get each row from the csv
while ($data=fgetcsv($handle, 1000, ","))
{
 mysql_query("INSERT INTO t_product (col1, col2 etc...) values ($data[0], $data[1], etc...");
 $prodId = mysql_last_insert_id();

 // using model as an example, there are other columns
 // with csv values that need to be broken up
 $arrModel = explode(',', $data[2]);
 foreach($arrModel as $modelNumber)
 mysql_query("INSERT INTO t_model (product_id, col1, col2 etc...) values ($prodId, $modelNumber[0], $modelNumber[1] etc...");
}

这里的问题是每个while循环迭代都会对数据库进行大量调用。对于每个产品记录,我必须插入N个型号,Y部件号,X序列号等......

我开始采用另一种方法将整个CSV存储在一个数组中。然后我写了一个批处理查询,如

$sql = "INSERT INTO t_product (col1, col2, etc...) values ";
foreach($arrParam as $val)
 $sql .= " ($val[0], $val[1], $val[2]), "

但是我用这种方法遇到了过多的内存错误。我将最大内存限制增加到64M,而且我的内存仍然不足。

解决此问题的最佳方法是什么?

也许我应该首先将所有查询写入* .sql文件,然后将* .sql文件导入mysql数据库?

3 个答案:

答案 0 :(得分:1)

这可能完全不是您想要的方向,但您可以使用免费的MySQL Migration Toolkit

直接从MS Access生成MySQL创建脚本

也许您可以允许用户上传Access数据库,然后让您的PHP脚本调用Migration toolkit?

答案 1 :(得分:0)

如果您要尝试优化已经存在的代码,我会尝试聚合INSERTS,看看是否有帮助。这应该很容易添加到您的代码中。像这样的东西(C#伪代码):

int flushCount = 0;

while (!done)
{
    // Build next query, concatenate to last set of queries

    if (++flushCount == 5)
    {
        // Flush queries to database

        // Reset query string to empty

        flushCount = 0;
    }
}

// Flush remaining queries to the database

答案 2 :(得分:0)

我决定将所有查询都写入.SQL文件。这使我有机会将CSV文件规范化为适当的关系数据库。之后,我的php脚本调用了一个exec(“mysql -h dbserver.com -u myuser -pmypass dbname< db.sql”);

这解决了我的内存问题,它比php的多个查询要快得多。