我正在编写一个Go应用程序,该应用程序应该将文件中的数千个值插入数据库。只要可以将所有值插入数据库,就可以正常工作。如果其中一个查询失败,则之后的所有查询都会由于pq: : current transaction is aborted, commands ignored until end of transaction block
我想插入所有元素,如果一个元素的插入失败,则应跳过该元素,并插入其他元素。
我的代码:
func (db *Database) Insert(values []Value) (transerr error) {
tx, err := db.Begin()
if transerr != nil {
return nil, err
}
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}
stmt, err := tx.Prepare("INSERT INTO foo VALUES (?)")
if err != nil {
return err
}
defer stmt.Close()
for _, value : range values {
_, err = stmt.Exec(value)
if err != nil {
log.Error(err)
}
}
return nil
}
我尝试添加一个tx.Rollback()以防stmt.Exec失败-但这会导致sql: statement is closed
。
答案 0 :(得分:1)
对于Postgresql,您可以使用 ON CONFLICT DO NOTHING
我已经尝试了下面的代码,并且将postgresql db放在了一边,它忽略了有错误的插入行。我做了一些其他更改以尝试这一点。您可以忽略我的其他更改。
func insert(db *sql.DB, values []string) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Commit()
stmt, err := tx.Prepare("INSERT INTO foo ( foo_col) VALUES ($1) ON CONFLICT DO NOTHING")
if err != nil {
fmt.Println("errro at stmt", err)
return err
}
defer stmt.Close()
for _, value := range values {
_, err = stmt.Exec(value)
if err != nil {
fmt.Println(value, err)
}
}
return nil
}
对于mysql,您可以使用 INSERT IGNORE
stmt, err := tx.Prepare("INSERT IGNORE INTO foo ( foo_col) VALUES ($1) ")
答案 1 :(得分:0)
我针对该问题的解决方案如下: