使用预处理语句
您可以定义预处理语句以供重复使用。这可以通过避免每次代码执行数据库操作时重新创建语句的开销来帮助代码运行得更快一些.
注意: 预处理语句中的参数占位符因您使用的 DBMS 和驱动程序而异。例如,Postgres 的 pq 驱动需要一个占位符,例如是$1
而不是 ?
。
什么是预处理语句?
预处理语句是由 DBMS 解析和保存的 SQL,通常包含占位符但没有实际参数值。稍后,可以使用一组参数值执行该语句。
如何使用预处理语句
当您希望重复执行相同的 SQL 时,您可以使用一个 sql.Stmt
预先准备好 SQL 语句,然后根据需要执行它。
下面的示例创建一个预处理语句,从数据库中选择一个特定的专辑。DB.Prepare
返回一个sql.Stmt
表示给定 SQL 文本的预处理语句。您可以将 SQL 语句的参数传递给Stmt.Exec
, Stmt.QueryRow
, 或 Stmt.Query
以运行该语句。
// AlbumByID 检索指定的专辑.
func AlbumByID(id int) (Album, error) {
// 定义预处理语句。您通常会在其他位置定义语句,
// 并将其保存以用于诸如此函数的函数中
stmt, err := db.Prepare("SELECT * FROM album WHERE id = ?")
if err != nil {
log.Fatal(err)
}
var album Album
// 执行预准备语句,为占位符为 ? 的
// 参数传入 id 值
err := stmt.QueryRow(id).Scan(&album.ID, &album.Title, &album.Artist, &album.Price, &album.Quantity)
if err != nil {
if err == sql.ErrNoRows {
// 处理未返回行的情况.
}
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
的结果。也就是说,他们将 not-for-transactionssql.Stmt
转换为 for-this-transactionsql.Stmt
。Conn.PrepareContext
从sql.Conn
中创建一个预处理语句,它表示一个保留的连接。
确保在您的代码完成语句时调用stmt.Close
。这将释放可能与其关联的任何数据库资源(例如底层连接)。对于函数中仅是局部变量的语句,只需 defer stmt.Close()
。
用于创建预处理语句的函数
Function | Description |
---|---|
DB.Prepare DB.PrepareContext
|
准备一个单独执行的语句,或者使用 Tx.Stmt 将其转换为事务中的预处理语句 |
Tx.Prepare Tx.PrepareContext Tx.Stmt Tx.StmtContext
|
准备用于特定事务的语句。有关更多信息,请参 执行事务. |
Conn.PrepareContext
|
用于保留连接。有关更多信息,请参阅 管理连接. |