Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > golang的database.sql包

golang的database.sql包和事务处理操作步骤

作者:草海桐

事务是数据库操作中的一个逻辑单元,由一系列的数据库操作组成,这一系列操作要么全部执行并且提交,要么全部回滚,确保数据的一致性和完整性,这篇文章主要介绍了golang的database.sql包和事务处理操作步骤,需要的朋友可以参考下

事务(Transaction)

事务是数据库操作中的一个逻辑单元,由一系列的数据库操作组成。这一系列操作要么全部执行并且提交,要么全部回滚,确保数据的一致性和完整性。事务具有以下四个主要特性,通常被称为ACID特性:

在Go语言中,使用database/sql包进行事务的基本步骤如下:

事务的使用场景

注意事项

数据库连接方法

dsn := "username:password@tcp(127.0.0.1:3306)/dbname"
方法名描述示例
sql.Open()打开数据库连接db, err := sql.Open("mysql", dsn)
db.Ping()测试数据库连接是否有效err = db.Ping()
db.Close()关闭数据库连接defer db.Close()

事务方法

方法名描述示例
db.Begin()开始一个事务tx, err := db.Begin()
tx.Rollback()回滚事务tx.Rollback()
tx.Commit()提交事务err = tx.Commit()

查询和执行方法

方法名描述示例
tx.Exec()执行不返回结果的SQL语句,用于CREATE、INSERT、UPDATE、DELETE等操作tx.Exec("create table ...")
tx.Query()执行返回多行结果的SQL查询rows, err := tx.Query("select ...")
tx.QueryRow()执行返回单行结果的SQL查询tx.QueryRow("select ...")
stmt.Exec()使用预处理语句执行SQL语句stmt.Exec("f", "g")

预处理语句

方法名描述示例
tx.Prepare()创建预处理语句stmt, err := tx.Prepare(...)
stmt.Close()关闭预处理语句defer stmt.Close()

查询结果处理

方法名描述示例
rows.Next()逐行迭代查询结果rows.Next()
rows.Scan()将当前行的列值赋值给变量rows.Scan(&s1, &s2)
rows.Err()检查查询和迭代过程中的错误rows.Err()
rows.Close()关闭结果集,释放相关资源defer rows.Close()

预处理语句(Prepared Statements)

预处理语句是指在数据库中提前编译和优化的SQL语句模板,可以在之后多次重复使用。预处理语句的主要优点如下:

在Go语言中,使用预处理语句的基本步骤如下:

以下是一个使用预处理语句的示例:

stmt, err := tx.Prepare("INSERT INTO table1 (column1, column2) VALUES(?, ?)")  
if err != nil {  
    fmt.Printf("准备预处理语句失败:%v\n", err)  
    return  
}  
defer stmt.Close()  
// 第一次执行  
_, err = stmt.Exec("f", "g")  
if err != nil {  
    tx.Rollback()  
    fmt.Printf("执行预处理语句第一次失败:%v\n", err)  
    return  
}  
// 第二次执行  
_, err = stmt.Exec("h", "i")  
if err != nil {  
    tx.Rollback()  
    fmt.Printf("执行预处理语句第二次失败:%v\n", err)  
    return  
}  

在这个示例中,预处理语句一次创建,多次执行,提升了效率,并降低了SQL注入的风险。

预处理语句的使用场景

注意事项

总的示例代码:

package main  
import (  
    "database/sql"  
    "fmt"  
    _ "github.com/go-sql-driver/mysql"  
)  
const (  
    dsn = "username:password@tcp(localhost:3306)/test"  
)  
func main() {  
    db, err := sql.Open("mysql", dsn)  
    if err != nil {  
        fmt.Printf("打开数据库连接失败:%v\n", err)  
        return  
    }  
    defer db.Close()  
    if err := db.Ping(); err != nil {  
        fmt.Printf("数据库连接不可用:%v\n", err)  
        return  
    }  
    transactionExample(db)  
}  
func transactionExample(db *sql.DB) {  
    tx, err := db.Begin()  
    if err != nil {  
        fmt.Printf("开始事务失败:%v\n", err)  
        return  
    }  
    defer func() {  
        if err != nil {  
            fmt.Println("事务回滚中...")  
            rollbackErr := tx.Rollback()  
            if rollbackErr != nil && rollbackErr != sql.ErrTxDone {  
                fmt.Printf("事务回滚失败:%v\n", rollbackErr)  
            }  
        }  
    }()  
    // 创建表  
    fmt.Println("创建表...")  
    err = createTable(tx)  
    if err != nil {  
        return  
    }  
    // 插入数据  
    fmt.Println("插入数据到table1...")  
    err = insertData(tx)  
    if err != nil {  
        return  
    }  
    // 更新数据  
    fmt.Println("更新table1的值...")  
    err = updateData(tx)  
    if err != nil {  
        return  
    }  
    // 删除数据  
    fmt.Println("删除数据...")  
    err = deleteData(tx)  
    if err != nil {  
        return  
    }  
    // 查询多行数据  
    fmt.Println("查询多行数据...")  
    err = queryMultiRows(tx)  
    if err != nil {  
        return  
    }  
    // 查询单行数据  
    fmt.Println("查询单行数据...")  
    err = querySingleRow(tx)  
    if err != nil {  
        return  
    }  
    // 预处理语句插入数据  
    fmt.Println("使用预处理语句插入数据...")  
    err = insertWithPrepare(tx)  
    if err != nil {  
        return  
    }  
    // 提交事务  
    fmt.Println("提交事务...")  
    err = tx.Commit()  
    if err != nil {  
        fmt.Printf("提交事务失败:%v\n", err)  
        return  
    }  
    fmt.Println("事务处理成功。")  
}  
func createTable(tx *sql.Tx) error {  
    _, err := tx.Exec("create table if not exists table1 (column1 nchar(10), column2 nchar(10))")  
    return err  
}  
func insertData(tx *sql.Tx) error {  
    _, err := tx.Exec("insert into table1 (column1, column2) values ('a','b'), ('c','d'), ('e','f')")  
    return err  
}  
func updateData(tx *sql.Tx) error {  
    _, err := tx.Exec("update table1 set column1 = 'c' where column1 = 'a'")  
    return err  
}  
func deleteData(tx *sql.Tx) error {  
    _, err := tx.Exec("delete from table1 where column1 = 'b'")  
    return err  
}  
func queryMultiRows(tx *sql.Tx) error {  
    rows, err := tx.Query("select * from table1")  
    if err != nil {  
        return err  
    }  
    defer rows.Close()  
    for rows.Next() {  
        var s1, s2 string  
        err := rows.Scan(&s1, &s2)  
        if err != nil {  
            return fmt.Errorf("扫描失败:%v", err)  
        }  
        fmt.Printf("table1数据:%s, %s\n", s1, s2)  
    }  
    if err := rows.Err(); err != nil {  
        return fmt.Errorf("遍历table1失败:%v", err)  
    }  
    return nil  
}  
func querySingleRow(tx *sql.Tx) error {  
    var c string  
    err := tx.QueryRow("select column1 from table1 where column1 = 'e'").Scan(&c)  
    if err != nil {  
        if err == sql.ErrNoRows {  
            fmt.Println("没有找到匹配的行。")  
        } else {  
            return fmt.Errorf("查询单行数据失败:%v", err)  
        }  
        return nil  
    }  
    fmt.Printf("单行数据:%s\n", c)  
    return nil  
}  
func insertWithPrepare(tx *sql.Tx) error {  
    stmt, err := tx.Prepare("insert into table1 (column1, column2) values(?, ?)")  
    if err != nil {  
        return fmt.Errorf("准备预处理语句失败:%v", err)  
    }  
    defer stmt.Close()  
    _, err = stmt.Exec("f", "g")  
    if err != nil {  
        return fmt.Errorf("执行预处理语句失败:%v", err)  
    }  
    return nil  
}  

到此这篇关于golang的database.sql包和事务处理操作步骤的文章就介绍到这了,更多相关golang的database.sql包内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文