Golang中MySQL的RowsAffected返回值为零的问题

Golang中MySQL的RowsAffected返回值为零的问题

我们尝试执行删除或更新操作,并试图获取受影响的行数。它返回了零。

5 回复

你能分享一下你的代码吗?另外,你是否检查过是否返回了错误?你是否确认数据确实已从表中删除?

更多关于Golang中MySQL的RowsAffected返回值为零的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


好的,既然你检查了错误。

你说受影响的行数返回零,我假设在此之前没有错误,那么能否请你回答那个仍然悬而未决的问题:你是否检查过数据库,确认实际上有数据被删除了?

我已经检查过记录是否已存在。

我通过修改以下代码解决了这个问题:

tx, err := easyglobal.Mydb.Begin()
if err != nil {
	return false, err
}
defer func(tx *sql.Tx) {
	if err != nil {
		_ = tx.Rollback()
	} else {
		_ = tx.Commit()
	}
}(tx)

beingX 改为 begin,并将 Sqlx 改为 sql

如果你知道原因,请详细解释给我听。

tx, err := Mydb.Beginx()
if err != nil {
	return false, err
}
defer func(tx *sqlx.Tx) {
	if err != nil {
		_ = tx.Rollback()
	} else {
		_ = tx.Commit()
	}
}(tx)

_Query := `delete from emp where emp_id = ? `

rowsaffected, err := tx.Exec(_Query, _in.Emp_id)
if err != nil {
	return false, err
}

nRows, err := rowsaffected.RowsAffected()
if err != nil {
	//fmt.Println("Error: Failed to read count of affected rows")
	log.Fatal(err)
	return false, err
}
if nRows <= 0 {
	//return false, err
}

在Golang中,RowsAffected()返回零通常有几个常见原因。以下是具体分析和示例代码:

1. SQL语句未实际影响任何行

// 示例:没有匹配WHERE条件的记录
result, err := db.Exec("UPDATE users SET status = ? WHERE id = ?", "active", 999)
if err != nil {
    log.Fatal(err)
}

rowsAffected, err := result.RowsAffected()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("受影响行数: %d\n", rowsAffected) // 如果id=999不存在,返回0

2. 使用sqlx时的常见问题

// 错误示例:使用sqlx的NamedExec时获取受影响行数
type User struct {
    ID     int    `db:"id"`
    Status string `db:"status"`
}

user := User{ID: 1, Status: "inactive"}
result, err := db.NamedExec("UPDATE users SET status = :status WHERE id = :id", user)
if err != nil {
    log.Fatal(err)
}

// 正确获取RowsAffected
rowsAffected, err := result.RowsAffected()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("受影响行数: %d\n", rowsAffected)

3. 事务中的问题

// 示例:在事务中检查受影响行数
tx, err := db.Begin()
if err != nil {
    log.Fatal(err)
}

result, err := tx.Exec("DELETE FROM logs WHERE created_at < ?", time.Now().AddDate(0, -1, 0))
if err != nil {
    tx.Rollback()
    log.Fatal(err)
}

rowsAffected, err := result.RowsAffected()
if err != nil {
    tx.Rollback()
    log.Fatal(err)
}

if rowsAffected == 0 {
    fmt.Println("没有符合条件的记录被删除")
} else {
    fmt.Printf("删除了 %d 条记录\n", rowsAffected)
}

err = tx.Commit()
if err != nil {
    log.Fatal(err)
}

4. 检查SQL执行是否成功

// 完整示例:包含错误处理和调试
func deleteUser(db *sqlx.DB, userID int) (int64, error) {
    result, err := db.Exec("DELETE FROM users WHERE id = ?", userID)
    if err != nil {
        return 0, fmt.Errorf("执行删除失败: %v", err)
    }
    
    rowsAffected, err := result.RowsAffected()
    if err != nil {
        return 0, fmt.Errorf("获取受影响行数失败: %v", err)
    }
    
    // 调试:打印最后执行的SQL(需要开启驱动日志)
    fmt.Printf("删除用户ID: %d, 受影响行数: %d\n", userID, rowsAffected)
    
    return rowsAffected, nil
}

5. 确保使用正确的Result对象

// 错误示例:使用了错误的结果对象
stmt, err := db.Prepare("UPDATE products SET price = ? WHERE category = ?")
if err != nil {
    log.Fatal(err)
}
defer stmt.Close()

// 错误:尝试在stmt上调用RowsAffected
// rowsAffected, err := stmt.RowsAffected() // 编译错误

// 正确:在Exec返回的Result上调用
result, err := stmt.Exec(99.99, "electronics")
if err != nil {
    log.Fatal(err)
}

rowsAffected, err := result.RowsAffected()
if err != nil {
    log.Fatal(err)
}

6. 验证数据库连接和表状态

// 检查数据库连接和表是否存在
func checkDatabase(db *sqlx.DB) error {
    // 检查连接
    err := db.Ping()
    if err != nil {
        return fmt.Errorf("数据库连接失败: %v", err)
    }
    
    // 检查表是否存在
    var tableExists bool
    err = db.Get(&tableExists, 
        "SELECT COUNT(*) > 0 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'users'")
    if err != nil {
        return fmt.Errorf("检查表失败: %v", err)
    }
    
    if !tableExists {
        return fmt.Errorf("表不存在")
    }
    
    return nil
}

如果以上方法都不能解决问题,可以在执行SQL前添加调试日志,确保SQL语句正确执行:

// 调试:打印实际执行的SQL
query := "DELETE FROM orders WHERE status = ? AND created_at < ?"
args := []interface{}{"pending", time.Now().AddDate(0, -6, 0)}

fmt.Printf("执行SQL: %s\n参数: %v\n", query, args)

result, err := db.Exec(query, args...)
// ... 后续处理
回到顶部