使用预处理语句
您可以定义一个预处理语句以供重复使用。这可以避免代码每次执行数据库操作时重新创建语句的开销,从而帮助您的代码运行得更快一些。
注意:预处理语句中的参数占位符取决于您使用的 DBMS 和驱动程序。例如,用于 Postgres 的 pq 驱动程序 需要像 $1
这样的占位符,而不是 ?
。
什么是预处理语句?
预处理语句是由 DBMS 解析和保存的 SQL,通常包含占位符但没有实际参数值。之后,可以使用一组参数值执行该语句。
如何使用预处理语句
当您期望重复执行相同的 SQL 时,可以使用一个 sql.Stmt
提前准备 SQL 语句,然后根据需要执行它。
以下示例创建了一个预处理语句,用于从数据库中选择特定专辑。DB.Prepare
返回一个 sql.Stmt
,表示给定 SQL 文本的预处理语句。您可以将 SQL 语句的参数传递给 Stmt.Exec
、Stmt.QueryRow
或 Stmt.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)
}
defer stmt.Close()
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
提供了用于调用语句的常用 Exec
、QueryRow
和 Query
方法。有关使用这些方法的更多信息,请参阅查询数据和执行不返回数据的 SQL 语句。
然而,由于 sql.Stmt
已经表示一个预设的 SQL 语句,其 Exec
、QueryRow
和 Query
方法仅接受与占位符对应的 SQL 参数值,而省略了 SQL 文本。
您可以根据用途以不同的方式定义新的 sql.Stmt
。
DB.Prepare
和DB.PrepareContext
创建一个预处理语句,可以独立执行,即在事务外部自行执行,就像DB.Exec
和DB.Query
一样。Tx.Prepare
、Tx.PrepareContext
、Tx.Stmt
和Tx.StmtContext
创建一个预处理语句,用于特定事务中。Prepare
和PrepareContext
使用 SQL 文本定义语句。Stmt
和StmtContext
使用DB.Prepare
或DB.PrepareContext
的结果。也就是说,它们将一个非事务用的sql.Stmt
转换为一个用于当前事务的sql.Stmt
。Conn.PrepareContext
从一个sql.Conn
创建一个预处理语句,后者表示一个保留的连接。
请确保在代码处理完语句后调用 stmt.Close
。这将释放可能与该语句相关的任何数据库资源(例如底层连接)。对于仅作为函数局部变量的语句,defer stmt.Close()
就足够了。
创建预处理语句的函数
函数 | 描述 |
---|---|
DB.Prepare DB.PrepareContext
|
准备一个语句,用于独立执行,或使用 Tx.Stmt 转换为“事务内”的预处理语句。 |
Tx.Prepare Tx.PrepareContext Tx.Stmt Tx.StmtContext
|
准备一个语句,用于特定事务。更多信息请参阅执行事务。 |
Conn.PrepareContext
|
用于保留的连接。更多信息请参阅管理连接。 |