【问题标题】:What is the fastest way to insert values from datagridview to mysql database将值从datagridview插入mysql数据库的最快方法是什么
【发布时间】:2016-04-20 18:30:33
【问题描述】:

我有一个 vb.net 系统,我想将 10,000 条或更多记录从 datagridview 插入 mysql 数据库。但是当我尝试这个时,10,000 条记录需要 8 分钟

For i As Integer = 0 To DataGridView1.Rows.Count - 1

                        Dim queryInsert As String = "INSERT INTO tbl_shipdetails (ship_date, item_type, item_code, imei1, imei2)" & _
                                                    "VALUES('" & DataGridView1.Rows(i).Cells(1).Value & "','" & DataGridView1.Rows(i).Cells(2).Value & "','" & DataGridView1.Rows(i).Cells(3).Value & "','" & DataGridView1.Rows(i).Cells(4).Value & "','" & DataGridView1.Rows(i).Cells(5).Value & "')"
                        MySqlCmd = New MySqlCommand
                        MySqlCmd.Connection = Myconnect
                        MySqlCmd.CommandText = queryInsert
                        MySqlCmd.ExecuteNonQuery()
                    Next

我想知道是否有人知道最快的方法是什么?谁能帮帮我吗。我正在考虑将datagridview中的整个值插入到mysql中,只需一次插入(如批量)而不使用循环,但我不知道是否可能。

提前致谢!

【问题讨论】:

  • @AlexB。是否可以在 datagridview 中使用批量插入?我查看了它,但示例使用 file.txt。谢谢!
  • 我不这么认为。看看第二个例子,每个插入有多个值。
  • 数据从何而来?当然,用户不会输入 10,000 行。这是导入操作吗?
  • @Plutonix 是的,这是一个导入操作。

标签: mysql vb.net datagridview sql-insert bulkinsert


【解决方案1】:

我不知道这会快多少,但是对您的查询有一些简单的优化

Dim queryInsert As String = "INSERT INTO tbl_shipdetails (ship_date, " & _
                             "item_type, item_code, imei1, imei2)" & _
                             "VALUES(@p1,'@p2,@p3,@p4,@p5)"
Dim cmd = New  MySqlCommand(queryInsert, Myconnect)
cmd.Parameters.Add("@p1", MySqlDbType.VarChar)
cmd.Parameters.Add("@p2", MySqlDbType.VarChar)    
cmd.Parameters.Add("@p3", MySqlDbType.VarChar)    
cmd.Parameters.Add("@p4", MySqlDbType.VarChar)    
cmd.Parameters.Add("@p5", MySqlDbType.VarChar)
For i As Integer = 0 To DataGridView1.Rows.Count - 1
    cmd.Parameters("@p1").Value = DataGridView1.Rows(i).Cells(1).Value
    cmd.Parameters("@p2").Value = DataGridView1.Rows(i).Cells(2).Value 
    cmd.Parameters("@p3").Value = DataGridView1.Rows(i).Cells(3).Value
    cmd.Parameters("@p4").Value = DataGridView1.Rows(i).Cells(4).Value
    cmd.Parameters("@p5").Value = DataGridView1.Rows(i).Cells(5).Value
    cmd.ExecuteNonQuery()
Next

使用参数可以让您在循环外只构建一次 MySqlCommand,并且还避免了连接字符串所需的工作。 (更不用说Sql Injection的问题了)

请注意,我在 sql 文本中遵循了您的提示,您的所有字段似乎都是 string(VarChar) 类型。如果您的字段具有不同的数据类型,那么您应该将 MySqlDbType 枚举调整为正确的数据类型(并转换输入值=

【讨论】:

    【解决方案2】:

    注意:史蒂夫的回答显示了创建 SQL 查询的正确方法,而不是将 SQL 与字符串位连接。 没有错。

    但是,如果我想快速插入一堆行,我不想重新设置参数值,也不想从 DGV 中取出值。我也不想花时间将数据放入 DGV。

    不清楚数据来自哪里。考虑到规模,这听起来像是一个导入操作,可能会提供其他选择。但即使使用最初的方法,我认为还有其他问题,因为 8 分钟太长了。

    在 15 秒内插入 10,000 行新行

    我的表少了 1 或 2 列({Id, text(15), Int, Text(30), bool}),但这不应导致增加 40 倍。此方法使用了几个提供程序工具:

    ' class level variables
    Private dtDemo As DataTable
    Private cbDemo As MySqlCommandBuilder
    Private daDemo As MySqlDataAdapter
    

    初始化它们:

    Dim SQL = <sql>
                  SELECT
                       Id, ItemName, ItemValue, Descr,
                       Active, LastUpdated
                 FROM
                       simple
                 WHERE
                       1 = 0
              </sql>.Value
    
    Using dbcon = MySQLDB.GetMySQLConnection
    
        dbcon.Open()
    
        daDemo = New MySqlDataAdapter(SQL, dbcon)
        cbDemo = New MySqlCommandBuilder(daDemo)
        cbDemo.QuotePrefix = "`"
        cbDemo.QuoteSuffix = "`"
        daDemo.InsertCommand = cbDemo.GetInsertCommand()
    
        dtDemo = New DataTable
        daDemo.Fill(dtDemo)
    End Using
    
    dgv1.DataSource = dtDemo
    dgv1.Columns.RemoveAt(0)               ' remove ID from display
    dgv1.Columns.RemoveAt(dgv1.Columns.Count - 1)  ' remove LastUpdated 
    

    WHERE 子句创建一个没有行的表,只有 CommandBuilder 构建各种命令所需的元数据。它确实/将在填充时显示 DGV 中的内容。

    请注意,删除的列只是从显示中删除,而不是从数据表中删除。数据库将设置Id 并且LastUpdated 列上有一个触发器(从另一个答案遗留下来),因此不需要显示这些列。

    获取数据

    为此,我导入了一些我生成的假数据。将数据添加到DataTable不是DataGridView

    Dim csvFile As String = "C:\Temp\mysqlbatch.csv"
    
    Dim lines = File.ReadAllLines(csvFile)
    
    Dim dr As DataRow
    For Each s As String In lines
        ' not the best way to parse a csv
        Dim data = s.Split(","c)
        dr = dtDemo.NewRow        ' create new row with all the Cols
        dr("ItemName") = Data(0)
        dr("ItemValue") = Convert.ToInt32(Data(1))
        dr("Descr") = Data(2)
        dr("Active") = If(Convert.ToInt32(data(3)) = 0, False, True)
        dtDemo.Rows.Add(dr)
    Next
    

    完成后(几秒钟),数据将显示在 DGV 中。我猜用户可能会编辑或修复数据?

    插入数据

    DataAdapter 知道如何插入(来自设置),DataTable 已经拥有数据并且它知道哪些行是新的(所有这些行)。所以让他们整理一下:

    Dim sw As New Stopwatch
    sw.Start()
    Dim rows As Int32
    
    Using dbcon = MySQLDB.GetMySQLConnection
        dbcon.Open()
    
        daDemo.InsertCommand.Connection = dbcon
        rows = daDemo.Update(dtDemo)
    End Using
    
    sw.Stop()
    Console.WriteLine("Inserted {0} rows in {1}ms", rows, sw.ElapsedMilliseconds)
    

    在 10464 毫秒内插入 10000 行
    在 9419 毫秒内插入 10000 行

    注意:可能不需要显式创建更新/插入的连接。没有它,我的工作正常。

    显然,MySqlDataAdapter 从创建时就保留了连接字符串或连接对象以供以后使用。并非所有 DataAdapter 都这样做; OleDB 要求您创建、打开和设置连接对象,如图所示。

    【讨论】:

      【解决方案3】:

      MySQL 允许在单个插入命令中插入多个行集。 按照以下格式创建一个字符串:

      INSERT INTO yourTable(c1,c2,c3)
      VALUES (r1v1,r1v2,r1v3), (r2v1,r2v2,r2v3), (r3v1,r3v2,r3v3), . . . (rNv1,rNv2,rNv3)
      

      此命令插入多行。

      【讨论】:

        猜你喜欢
        • 2022-11-11
        • 2016-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-27
        • 1970-01-01
        • 2013-04-05
        相关资源
        最近更新 更多