将Access数据库表中的记录一一插入/复制到MySQL远程数据库

Posted

技术标签:

【中文标题】将Access数据库表中的记录一一插入/复制到MySQL远程数据库【英文标题】:Insert /copy records from Access database table to MySQL remote database one by one 【发布时间】:2019-01-10 10:06:09 【问题描述】:

我想将表记录从 Access 数据库插入 mysql 远程服务器。

我的方法是:

使用循环在 TextBox 中从第一条到最后一条记录加载 Access 数据库 检查记录是否已经插入MySQL远程数据库 如果没有,就一个一个插入

代码产生错误信息:

值不能为空参数模式:数据源

我的代码在这里:

SQLda = New MySqlDataAdapter(("INSERT INTO approved (word, approveds) Select * FROM (SELECT '" & TextBox3.Text & "', 'No') AS tmp WHERE Not EXISTS (SELECT word FROM approved WHERE word= '" & TextBox3.Text & "') LIMIT 1"), MysqlConn)

MysqlConn = New MySqlConnection
ListBox1.Items.Clear()

MysqlConn.ConnectionString = "server=localhost;userid=root;password=;port=3306;database=sindhila_spellchecker;Character Set=utf8;SslMode=none;"

SQLda = New MySqlDataAdapter(("SELECT * FROM approved"), MysqlConn)
SQLda.Fill(dbds, "doctors")
DataGridView1.DataSource = dbds.Tables("doctors")

Try
    MysqlConn.Open()
    MessageBox.Show("Connection Successful, click ok to continue")
    Label3.Visible = True

    romantranssql = "Select * from approved order by id"

    pth = My.Application.Info.DirectoryPath
    romantransconn.ConnectionString = "Provider=Microsoft.ace.oledb.12.0; Data Source=" & pth & "\database.mdb; User Id=admin; Password=;"
    romantransda = New OleDbDataAdapter(romantranssql, romantransconn)
    romantransds = New DataSet
    romantransda.Fill(romantransds, "DisplayCenterData")
    romantransdt = romantransds.Tables("DisplayCenterData")
    romantranscmb = New OleDbCommandBuilder(romantransda)

    Do Until Me.BindingContext(romantransdt).Position = Me.BindingContext(romantransdt).Count - 1

        TextBox3.DataBindings.Clear()
        TextBox3.DataBindings.Add("text", romantransdt, "word")

        MysqlConn = New MySqlConnection

        MysqlConn.ConnectionString = "server=localhost;userid=root;password=;port=3306;database=sindhila_spellchecker;Character Set=utf8;"

        SQLda = New MySqlDataAdapter(("INSERT INTO approved (word, approveds) Select * FROM (SELECT '" & TextBox3.Text & "', 'No') AS tmp WHERE Not EXISTS (SELECT word FROM approved WHERE word= '" & TextBox3.Text & "') LIMIT 1"), MysqlConn)
        SQLda.Fill(dbds, "approved")

        DataGridView1.DataSource = dbds.Tables("approved")
        romantransdtx = dbds.Tables("approved")
        Me.BindingContext(romantransdtx).Position = 0
        Me.BindingContext(romantransdt).Position = Me.BindingContext(romantransdt).Position + 1
        Me.Refresh()
    Loop

    MsgBox("all New records have been uploded To server")
    Label3.Visible = False

    MysqlConn.Close()

Catch ex As Exception
    MessageBox.Show(ex.Message)
Finally
    MysqlConn.Dispose()

End Try

【问题讨论】:

我认为,您的 Access-table 允许 NULL 值,但您的 MySQL-table 不允许。 SQLda = New MySqlDataAdapter(("INSERT INTO approved (id, word, approveds) Select * FROM (SELECT +1, '" & TextBox3.Text & "', 'No') AS tmp WHERE Not EXISTS (SELECT word FROM approved WHERE word= '" & TextBox3.Text & "') LIMIT 1"), MysqlConn) .......在插入自动增量编号的地方我放了+1或NULL或默认值或 0 但它们都没有工作相同的错误消息显示“值不能为 nul”你能建议查询吗? 【参考方案1】:

这不是对您问题的准确/直接回答,而是更多的建议

老实说,您的代码看起来很难看,而且有时也毫无意义。让我们从丑陋开始。这是我最喜欢的一句话(顺便说一句):

您将花费 20% 的时间编写代码和 80% 的时间来维护它。

您知道有多少大型组织中的开发人员因缺乏经验的程序员编写的糟糕代码而感到沮丧吗?有时他们甚至不得不从头开始编写东西来修复问题。你的整个代码看起来写得不好,我几乎可以在每一行指出一个错误。例如,

为什么

MysqlConn = New MySqlConnection
MysqlConn.ConnectionString = "...."

在哪里可以做到

MysqlConn = New MySqlConnection("....")

是的,即使是一行代码也很重要。它可能对执行根本没有任何影响,但它对它的外观有重大影响。尝试解决这些问题。

现在,让我们谈谈你那里的一些无用代码。

SQLda = New MySqlDataAdapter(("INSERT INTO.....")), MysqlConn)
...
SQLda = New MySqlDataAdapter(("SELECT * FROM approved"), MysqlConn)

如果SQLda 在为它分配新值之前没有被用于任何事情,那么首先给它分配一个值有什么用?好吧,我可能在这里错了如果你没有发布你的整个代码..

现在,您在这里使用了Try-Catch 语句。为什么您要使用Exception 类来捕获所有可能的异常,而您可以像SqlException 一样捕获此处可能真正发生的特定异常?捕获(异常)是一个坏主意。 Read more here

您正在打开与数据库的连接,当事情完成后,您关闭它并处理它(通过调用Dispose 方法)。当您可以简单地使用 Using 语句,因为 SqlConnection 类已经实现 IDisposable 时,为什么还要这么忙?

所以,而不是这个:

 Dim MySqlConn = New SqlConnection("...")
 MySqlConn.Open()
 .....
 .....
 MySqlConn.Close()
 MySqlConn.Dispose()

这样做

Using MySqlConn = New SqlConnection("....")
...
End Using

一些最后的话

您的代码让我觉得您的代码是一个小项目。但对于未来的项目,强烈建议遵循以下建议:

切勿将连接字符串存储在代码或本地文件中

将连接字符串存储在配置文件中,例如app.configweb.config 文件。

切勿将值直接传递给 SQL 语句,而是使用参数

编写代码来传递直接值只会为 SQL 注入打开大门。所以,总是传递参数。

不要隐藏/显示控件,而是在需要时从代码隐藏中创建/删除它们

您可以在表单中创建一个控件(在您的情况下为 Label)并隐藏它,然后在需要时显示它。但这会花费你的资源。如果您使用 1 个或什至 5 个标签,可能不会消耗太多资源......但我们不只是只有标签的 UI,对吗?您很快就会意识到,执行或性能每增加一毫秒就会有很长的路要走。因此,必要时以编程方式创建/删除控件。这将对GarbageCollector 大有帮助。

在没有正确理解的情况下,切勿使用任何对象/类/任何东西

您正在使用DataTables。你知道它消耗了多少内存吗?较轻的替代方法是IEnumerable(T)(通用列表),例如List。甚至一个简单的DataReader 在性能方面也是一个更好的选择。

始终添加有用的 cmets

开发者社区中有一个臭名昭著的表情包。它是这样的:

当我编写代码时,只有上帝和我知道它是如何工作的 ... 现在只有上帝知道它是如何工作的。

始终在代码中添加有用的 cmets。这可能不会直接使您受益,但它将帮助调试您的代码的未来开发人员。此外,在 Visual Studio 中,添加 #region 关键字以将代码划分为部分。

我想这已经足够了。我希望你觉得这很有用。

干杯!

【讨论】:

【参考方案2】:

您不会为自动递增字段插入值。以下适用于我使用的一个小测试数据库。

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    Dim RetVal As Integer
    Dim InsertQuery = "INSERT INTO dbusers (myuser, mypassword)
                      Select  @name, @pass
                      WHERE Not EXISTS
                      (SELECT * FROM dbusers WHERE myuser = @name AND mypassword = @pass);"
    Using cn As New MySqlConnection(My.Settings.dbusersConnection)
        Using cmd As New MySqlCommand(InsertQuery, cn)
            cmd.Parameters.Add("@name", MySqlDbType.VarChar).Value = TextBox1.Text
            cmd.Parameters.Add("@pass", MySqlDbType.VarChar).Value = TextBox2.Text
            cn.Open()
            RetVal = cmd.ExecuteNonQuery
        End Using
    End Using
    If RetVal = 1 Then
        MessageBox.Show("Success")
    Else
        MessageBox.Show("Failure")
    End If
End Sub

【讨论】:

添加一些 cmets 会有所帮助:)

以上是关于将Access数据库表中的记录一一插入/复制到MySQL远程数据库的主要内容,如果未能解决你的问题,请参考以下文章

MySQL如何复制表中的一条记录并插入

VBA Access将数据集中的所有列插入访问表

大型记录集 (VBA) 的 MS Access 插入慢

如何在 Access 表中插入图像

将记录计数插入到不同的表中

宏中的 Access 2010 SQL 错误