Golang中如何使用批量更新查询
Golang中如何使用批量更新查询 我有数千条记录需要在 MySQL 中更新,有没有办法一次性更新所有记录?
Ashutosh_Prakash: 有没有办法一次性更新所有记录
通常来说,是的。你想更新什么?
更多关于Golang中如何使用批量更新查询的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我需要更新两列:列A和列B,条件是列C等于123(举例来说),并且在结构中,有时我会得到10条记录,有时会得到100条。
// 代码部分保持原样
只要遵循一些固定的规则,记录的数量并不重要。SQL并不关心你有多少条记录。你可以使用两层或更多层的CASE语句。
http://sqlfiddle.com/#!17/8c48e/3
你有更具体的例子吗?
是的,它在 MySQL 中可以工作,但我正在解组到结构体中的 JSON 数据不是固定的,它是动态的。有时我有 100 条记录,有时我有 50 条记录。那么,在 Go 语言中,我该如何编写动态的 case 语句呢?
感谢您的回复,Sibert。我想根据(WHERE条件)列C等于某个值来更新表中的两列(A和B)。这些值来自一个JSON数据列表,数据量很大,大约有上千条记录(包含列A、B、C的值)。因此,我需要使用MySQL和Golang一次性将这些值更新到表中。
我尝试提取那三个需要在MySQL中更新的键,并将JSON解组到结构体中。列A、B、C位于map[string]interface{}中,然后在map的for循环中执行更新查询(因此,对于我获取的每个数据,比如列A、B、C),我都在MySQL表中进行更新。
如果我使用case when语句,那么我将如何遍历case语句?
Ashutosh_Prakash:
我想根据条件更新表中两列(A, B)的数据。
我认为在 MySQL 中可以使用类似 CASE WHEN … THEN 的语句来实现。但我需要更多实际数据。
到目前为止你尝试了哪些方法?
如果我使用
case when语句,那么我该如何遍历 case 语句呢?
SQL Fiddle | A tool for easy online testing and sharing of database problems…
这是一个用于测试和共享 SQL 查询的应用程序。
这是 Postgresql 的示例,但据我所知,它也应该适用于 MySQL。你不需要“遍历”。MySQL 会为你处理。
在Golang中可以使用MySQL的批量UPDATE语句配合IN子句或CASE语句来实现批量更新。以下是两种常见方法:
方法1:使用IN子句(适合不同ID更新不同值)
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"strings"
)
type UpdateData struct {
ID int
Value string
}
func batchUpdateWithIN(db *sql.DB, data []UpdateData) error {
if len(data) == 0 {
return nil
}
// 构建ID列表和值映射
ids := make([]string, 0, len(data))
valueMap := make(map[int]string)
for _, item := range data {
ids = append(ids, fmt.Sprintf("%d", item.ID))
valueMap[item.ID] = item.Value
}
// 构建CASE语句
var caseBuilder strings.Builder
caseBuilder.WriteString("CASE id ")
for id, value := range valueMap {
caseBuilder.WriteString(fmt.Sprintf("WHEN %d THEN '%s' ", id, value))
}
caseBuilder.WriteString("ELSE value END")
// 执行批量更新
query := fmt.Sprintf(
"UPDATE your_table SET value = %s WHERE id IN (%s)",
caseBuilder.String(),
strings.Join(ids, ","),
)
_, err := db.Exec(query)
return err
}
方法2:使用VALUES()构造临时表(适合大量数据)
func batchUpdateWithValues(db *sql.DB, data []UpdateData) error {
if len(data) == 0 {
return nil
}
// 构建VALUES部分
var valuesBuilder strings.Builder
for i, item := range data {
if i > 0 {
valuesBuilder.WriteString(", ")
}
valuesBuilder.WriteString(fmt.Sprintf("(%d, '%s')", item.ID, item.Value))
}
query := fmt.Sprintf(`
UPDATE your_table t
JOIN (VALUES %s) AS tmp(id, value)
ON t.id = tmp.id
SET t.value = tmp.value
`, valuesBuilder.String())
_, err := db.Exec(query)
return err
}
方法3:使用预处理语句批量执行(最灵活)
func batchUpdateWithPreparedStmt(db *sql.DB, data []UpdateData) error {
// 开启事务
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
// 准备预处理语句
stmt, err := tx.Prepare("UPDATE your_table SET value = ? WHERE id = ?")
if err != nil {
return err
}
defer stmt.Close()
// 批量执行
for _, item := range data {
_, err := stmt.Exec(item.Value, item.ID)
if err != nil {
return err
}
}
// 提交事务
return tx.Commit()
}
方法4:使用ON DUPLICATE KEY UPDATE(适合有唯一键的表)
func batchUpsert(db *sql.DB, data []UpdateData) error {
if len(data) == 0 {
return nil
}
// 构建批量插入更新语句
var valueStrings []string
var valueArgs []interface{}
for _, item := range data {
valueStrings = append(valueStrings, "(?, ?)")
valueArgs = append(valueArgs, item.ID, item.Value)
}
query := fmt.Sprintf(
"INSERT INTO your_table (id, value) VALUES %s " +
"ON DUPLICATE KEY UPDATE value = VALUES(value)",
strings.Join(valueStrings, ","),
)
_, err := db.Exec(query, valueArgs...)
return err
}
使用示例
func main() {
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/dbname")
if err != nil {
panic(err)
}
defer db.Close()
// 准备测试数据
data := []UpdateData{
{ID: 1, Value: "value1"},
{ID: 2, Value: "value2"},
{ID: 3, Value: "value3"},
// ... 更多数据
}
// 使用方法1
err = batchUpdateWithIN(db, data)
if err != nil {
fmt.Printf("批量更新失败: %v\n", err)
}
// 使用方法3(推荐用于数千条记录)
err = batchUpdateWithPreparedStmt(db, data)
if err != nil {
fmt.Printf("预处理批量更新失败: %v\n", err)
}
}
对于数千条记录,推荐使用方法3(预处理语句+事务),它提供了更好的错误处理和性能平衡。方法1和方法2在单条SQL语句中处理,但需要注意SQL语句长度限制。方法4适合需要插入或更新的场景。

