VB.NET实现DataGridView批量更新MySQL表并求和的方法
批量更新MySQL库存实现方案
你现有代码存在几个会直接导致功能异常/安全风险的问题:
- 逻辑漏洞:定义了
IncomingStok变量但从未将DataGridView中取到的Stok值赋值给它,计算时永远加0,更新结果完全不符合预期 - 执行冲突:DataReader会独占数据库连接,在Reader未关闭的状态下用同一个连接执行Update命令,会直接触发连接占用异常
- 性能问题:每遍历一行就新建、打开、关闭一次数据库连接,数据量稍大时执行效率极低,还会耗尽连接池资源
- 安全风险:直接拼接SQL字符串,存在SQL注入漏洞,恶意输入可直接篡改、删除全表数据
- 资源泄漏:连接、命令、数据读取器对象都未做释放处理,长期运行会导致数据库连接泄漏
核心实现逻辑
不需要先查询原有库存值再在本地计算求和,MySQL原生支持UPDATE语句内直接做字段累加,单条SQL就能完成「取原有值+求和+更新」全流程,完全省去SELECT查询的开销:
UPDATE tbStok SET Stok = Stok + @新增库存值 WHERE ID = @对应ID
配合单次打开连接、参数化传值、事务包裹一致性保证,即可高效安全完成批量更新。
修正后的可运行代码
' 第一步:提前校验所有行数据合法性,避免执行到一半报错中断 Dim validRows As New List(Of (Id As Integer, IncomingStok As Integer))() For Each row As DataGridViewRow In dgvStok.Rows If row.IsNewRow Then Continue For ' 做空值、格式校验,防止非法值导致执行报错 Dim idVal As Integer Dim stokVal As Integer If Not Integer.TryParse(row.Cells("ID").Value?.ToString(), idVal) Then Throw New Exception($"第{row.Index + 1}行ID格式非法") End If If Not Integer.TryParse(row.Cells("Stok").Value?.ToString(), stokVal) Then Throw New Exception($"第{row.Index + 1}行库存值格式非法") End If validRows.Add((idVal, stokVal)) Next ' 替换为你自己的数据库连接字符串 Using conn As New MySqlConnection("你的数据库连接字符串") conn.Open() ' 开启事务,保证所有更新要么全成功要么全回滚,避免部分更新导致数据不一致 Using tran As MySqlTransaction = conn.BeginTransaction() Try ' 复用同一个命令对象,只定义一次参数结构,减少重复创建开销 Dim cmd As New MySqlCommand("UPDATE tbStok SET Stok = Stok + @incomingStok WHERE ID = @id", conn, tran) cmd.Parameters.Add("@incomingStok", MySqlDbType.Int32) cmd.Parameters.Add("@id", MySqlDbType.Int32) For Each item In validRows cmd.Parameters("@id").Value = item.Id cmd.Parameters("@incomingStok").Value = item.IncomingStok Dim affectRows = cmd.ExecuteNonQuery() ' 校验更新结果,ID不存在时直接终止回滚 If affectRows = 0 Then Throw New Exception($"ID为{item.Id}的库存记录不存在,更新终止") End If Next ' 所有行执行完成提交事务 tran.Commit() MessageBox.Show("批量库存更新完成") Catch ex As Exception ' 出错时回滚所有已执行的变更 tran.Rollback() Throw New Exception($"更新失败:{ex.Message}") End Try End Using End Using
大数据量优化建议
如果单次更新的数据量超过1000条,可改用临时表+批量导入+关联更新的方案,性能比逐行执行UPDATE高10~100倍:
- 创建和tbStok结构匹配的临时表,仅保留ID、待新增库存两个字段
- 用
MySqlBulkCopy把DataGridView中校验通过的待更新数据批量导入临时表 - 执行单条关联更新SQL完成全量更新:
UPDATE tbStok t INNER JOIN 临时表 tmp ON t.ID = tmp.ID SET t.Stok = t.Stok + tmp.Stok - 执行完成后临时表会自动回收,无需额外处理
内容的提问来源于stack exchange,提问作者Selikur
相关产品推荐
相关产品推荐

