从MySQL到MS Access的1GB数据

时间:2015-07-24 03:51:54

标签: c# mysql ms-access odbc oledb

情况:我正在创建一个自动化任务,用于查询MySQL(通过ODBC)并使用OLEDB将结果集插入MS Access数据库(.mdb)。

守则:

OleDbConnection accCon = new OleDbConnection();
OdbcCommand mySQLCon = new OdbcCommand();
try
{
    //connect to mysql
    Connect();                
    mySQLCon.Connection = connection;              

    //connect to access
    accCon.ConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;" +
        @"Data source= " + pathToAccess;
    accCon.Open();
    var cnt = 0;

    while (cnt < 5)
    {
        if (accCon.State == ConnectionState.Open)
            break;
        cnt++;
        System.Threading.Thread.Sleep(50);
    }

    if (cnt == 5)
    {
        ToolBox.logThis("Connection to Access DB did not open. Exit Process");
        return;
    }
} catch (Exception e)
{
    ToolBox.logThis("Faild to Open connections. msg -> " + e.Message + "\\n" + e.StackTrace);
}
OleDbCommand accCmn = new OleDbCommand();
accCmn.Connection = accCon;
//access insert query structure
var insertAccessQuery = "INSERT INTO {0} values({1});";
// key = > tbl name in access, value = > mysql query to b executed
foreach (var table in tblNQuery)
{
    try
    {
        mySQLCon.CommandText = table.Value;
        //executed mysql query                        
        using (var dataReader = mySQLCon.ExecuteReader())
        {
            //variable to hold row data
            var rowData = new object[dataReader.FieldCount];
            var parameters = "";
            //read the result set from mysql query
            while (dataReader.Read())
            {
                //fill rowData with the row values
                dataReader.GetValues(rowData);
                //build the parameters for insert query
                for (var i = 0; i < dataReader.FieldCount; i++)
                    parameters += "'" + rowData[i] + "',";

                parameters = parameters.TrimEnd(',');
                //insert to access
                accCmn.CommandText = string.Format(insertAccessQuery, table.Key, parameters);
                try
                {
                    accCmn.ExecuteNonQuery();
                }
                catch (Exception exc)
                {
                    ToolBox.logThis("Faild to insert to access db. msg -> " + exc.Message + "\\n\\tInsert query -> " + accCmn.CommandText );
                }                              
                parameters = "";
            }
        }
    }
    catch (Exception e)
    {
        ToolBox.logThis("Faild to populate access db. msg -> " + e.Message + "\\n" + e.StackTrace);
    }
}
Disconnect();
accCmn.Dispose();
accCon.Close();

问题:

  1. 内存使用率非常高(300MB ++),而MS Access文件大小不会持续变化!似乎插入缓存数据而不是将其保存到磁盘。

  2. 这很慢!我知道我的查询会在几秒钟内执行,但插入过程需要很长时间。

  3. 我尝试在MS Access中使用预准备语句并将值作为参数而不是字符串concat插入以创建插入查询。但是我收到了这条异常消息:

      

    标准表达式中的数据类型不匹配。

    任何人都知道如何解决这个问题或者有更好的方法吗?

5 个答案:

答案 0 :(得分:6)

您可以创建一个VBA宏,它使用DoCmd.TransferDatabase方法将数据通过ODBC提取到Access数据库中。它可能会更快更简单。

要从外部程序或计划任务运行VBA代码,只需启动Access以使用/ x命令行开关打开文件,它将在启动时运行导入宏。虽然GB数据仍需要一段时间。我找到了article by David Catriel that implemented this approach

更好的选择是使用不同的数据库引擎后端,如免费版的SQL Server Express。那么你有更多的选择,它更强大。如果您需要MS Access表单和报表,则可以在使用SQL Server时创建ADP项目文件,也可以使用链接表来获取数据。如果满足您的要求,您甚至可以use Access as a front-end to your MySQL database而不是复制所有数据。

答案 1 :(得分:5)

您可以转向SQL Server Integration Services(SSIS),而不是编写代码,并在午餐前完成。如果您的计算机上没有SQL Server,则可以extension to Visual Studio的形式使用它。

使用SSIS,您可以创建可重用的SSIS包,可以从命令行或计划任务触发。 This guide显示了如何将数据从MySQL提取到SQL Server,但SQL Server部分应该很容易replace with Access

答案 2 :(得分:4)

通过注释进行一些更改以添加命令执行的事务。如果事务不是手动控制的,那么它将每次自动创建和提交,这是一个耗时的操作

scipy.sparse.eigs

答案 3 :(得分:1)

为SQL Server数据库创建DSN(数据源名称)。然后通过打开Microsoft Access数据库并选择从该DSN导入来选择该DSN。您应该能够导入精确的1GB表(架构,数据,所有内容)。

有关使用DSN的更多信息: https://support.office.com/en-us/article/Link-to-SQL-Server-data-0474c16d-a473-4458-9cf7-f369b78d3db8

或者,您只需使用该DSN链接到SQL Server数据库(不导入Access表),并完全跳过导入。

答案 4 :(得分:1)

INSERT是否应成为TRANSACTION的一部分。在交易中通常会加速BULK INSERTS