Golang实现高效的批量SQL更新操作
Golang实现高效的批量SQL更新操作 我有一个表,想将具有某个ID的行复制到同一表中的其他行。关于最佳实践有什么建议吗?如何进行批量更新?
示例:
| id | foreign_key_id | param_a | param_b | created_at | updated_at |
|---|---|---|---|---|---|
| 1 | 23 | 23 | 44 | 2022-05-30 | 2022-05-30 |
| 2 | 35 | 32 | 22 | 2022-05-30 | 2022-05-30 |
| 3 | 13 | 12 | 33 | 2022-05-30 | 2022-05-30 |
| 4 | 12 | 33 | 11 | 2022-05-30 | 2022-05-30 |
| 5 | 55 | 18 | 22 | 2022-05-30 | 2022-05-30 |
我想用 param_a 和 param_b 的值为 23 来更新 foreign_key_id 为 12 和 13 的行。
更多关于Golang实现高效的批量SQL更新操作的实战教程也可以访问 https://www.itying.com/category-94-b0.html
4 回复
我正在寻找一种性能更好的模式来进行批量更新,你的回答完全正确,我的问题确实很蠢。
更多关于Golang实现高效的批量SQL更新操作的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
说实话,这个问题与 Go 语言毫无关系;这是一个“纯 SQL”查询。
UPDATE <table_name>
SET
param_a = 23
param_b = 23
WHERE foreign_key_id IN (12, 13);
我是不是遗漏了什么?
是的,是我的错,我会删除它。
在Golang中实现高效的批量SQL更新操作,推荐使用预处理语句和事务处理。以下是具体实现方案:
package main
import (
"database/sql"
"fmt"
"log"
)
func batchUpdate(db *sql.DB, sourceID int, targetIDs []int) error {
// 开启事务
tx, err := db.Begin()
if err != nil {
return fmt.Errorf("开启事务失败: %v", err)
}
defer tx.Rollback()
// 查询源数据
var paramA, paramB int
err = tx.QueryRow(
"SELECT param_a, param_b FROM your_table WHERE id = ?",
sourceID,
).Scan(¶mA, ¶mB)
if err != nil {
return fmt.Errorf("查询源数据失败: %v", err)
}
// 准备批量更新语句
stmt, err := tx.Prepare(`
UPDATE your_table
SET param_a = ?, param_b = ?, updated_at = CURRENT_TIMESTAMP
WHERE foreign_key_id = ?
`)
if err != nil {
return fmt.Errorf("准备语句失败: %v", err)
}
defer stmt.Close()
// 批量执行更新
for _, targetID := range targetIDs {
_, err := stmt.Exec(paramA, paramB, targetID)
if err != nil {
return fmt.Errorf("更新ID %d 失败: %v", targetID, err)
}
}
// 提交事务
if err := tx.Commit(); err != nil {
return fmt.Errorf("提交事务失败: %v", err)
}
return nil
}
func main() {
db, err := sql.Open("mysql", "user:password@/dbname")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 示例:将ID=1的数据复制到foreign_key_id为12和13的行
targetIDs := []int{12, 13}
if err := batchUpdate(db, 1, targetIDs); err != nil {
log.Fatal(err)
}
fmt.Println("批量更新完成")
}
对于更大批量的更新,可以使用 IN 子句的变体:
func batchUpdateOptimized(db *sql.DB, sourceID int, targetIDs []int) error {
// 查询源数据
var paramA, paramB int
err := db.QueryRow(
"SELECT param_a, param_b FROM your_table WHERE id = ?",
sourceID,
).Scan(¶mA, ¶mB)
if err != nil {
return fmt.Errorf("查询源数据失败: %v", err)
}
// 构建IN子句参数
query := `
UPDATE your_table
SET param_a = ?, param_b = ?, updated_at = CURRENT_TIMESTAMP
WHERE foreign_key_id IN (`
args := []interface{}{paramA, paramB}
for i, id := range targetIDs {
if i > 0 {
query += ","
}
query += "?"
args = append(args, id)
}
query += ")"
// 执行批量更新
_, err = db.Exec(query, args...)
if err != nil {
return fmt.Errorf("批量更新失败: %v", err)
}
return nil
}
使用 sqlx 库可以进一步简化操作:
import "github.com/jmoiron/sqlx"
func batchUpdateWithSqlx(db *sqlx.DB, sourceID int, targetIDs []int) error {
// 查询源数据
var sourceRow struct {
ParamA int `db:"param_a"`
ParamB int `db:"param_b"`
}
err := db.Get(&sourceRow,
"SELECT param_a, param_b FROM your_table WHERE id = ?",
sourceID,
)
if err != nil {
return err
}
// 构建批量更新
query, args, err := sqlx.In(`
UPDATE your_table
SET param_a = ?, param_b = ?, updated_at = CURRENT_TIMESTAMP
WHERE foreign_key_id IN (?)`,
sourceRow.ParamA, sourceRow.ParamB, targetIDs,
)
if err != nil {
return err
}
query = db.Rebind(query)
_, err = db.Exec(query, args...)
return err
}
这些方法通过事务保证数据一致性,使用预处理语句提高性能,适合处理批量更新场景。

