使用预处理语句

您可以定义一个预处理语句以重复使用。通过避免每次代码执行数据库操作时重新创建语句的开销,这有助于您的代码运行得更快。

注意:预处理语句中的参数占位符会根据您使用的 DBMS 和驱动程序而有所不同。例如,Postgres 的 pq 驱动程序 需要一个占位符,例如 $1,而不是 ?

什么是预处理语句?

预处理语句是 DBMS 解析并保存的 SQL,通常包含占位符,但没有实际的参数值。稍后,可以使用一组参数值执行该语句。

如何使用预处理语句

如果您希望重复执行相同的 SQL,可以使用 sql.Stmt 提前准备 SQL 语句,然后根据需要执行它。

以下示例创建了一个准备好的语句,用于从数据库中选择一个特定的专辑。 DB.Prepare 返回一个 sql.Stmt,表示给定 SQL 文本的准备好的语句。你可以将 SQL 语句的参数传递给 Stmt.ExecStmt.QueryRowStmt.Query 来运行该语句。

// AlbumByID retrieves the specified album.
func AlbumByID(id int) (Album, error) {
    // Define a prepared statement. You'd typically define the statement
    // elsewhere and save it for use in functions such as this one.
    stmt, err := db.Prepare("SELECT * FROM album WHERE id = ?")
    if err != nil {
        log.Fatal(err)
    }

    var album Album

    // Execute the prepared statement, passing in an id value for the
    // parameter whose placeholder is ?
    err := stmt.QueryRow(id).Scan(&album.ID, &album.Title, &album.Artist, &album.Price, &album.Quantity)
    if err != nil {
        if err == sql.ErrNoRows {
            // Handle the case of no rows returned.
        }
        return album, err
    }
    return album, nil
}

准备好的语句行为

准备好的 sql.Stmt 提供了用于调用该语句的常规 ExecQueryRowQuery 方法。有关如何使用这些方法的更多信息,请参阅 查询数据执行不返回数据的 SQL 语句

但是,由于 sql.Stmt 已经表示一个预设的 SQL 语句,因此它的 ExecQueryRowQuery 方法仅获取与占位符相对应的 SQL 参数值,而省略 SQL 文本。

你可以根据使用方式以不同的方式定义一个新的 sql.Stmt

确保在你代码使用完一个语句后调用 stmt.Close。这将释放可能与之关联的任何数据库资源(例如底层连接)。对于函数中仅为局部变量的语句,defer stmt.Close() 就足够了。

用于创建准备好的语句的函数

函数 说明
DB.Prepare
DB.PrepareContext
准备一个用于独立执行或将使用 Tx.Stmt 转换为事务中已准备好的语句的语句。
Tx.Prepare
Tx.PrepareContext
Tx.Stmt
Tx.StmtContext
准备一个用于特定事务的语句。有关更多信息,请参阅 执行事务
Conn.PrepareContext 用于保留连接。更多信息,请参阅管理连接