使用预处理语句
您可以定义一个预处理语句以重复使用。通过避免每次代码执行数据库操作时重新创建语句的开销,这有助于您的代码运行得更快。
注意:预处理语句中的参数占位符会根据您使用的 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)
}
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
|
用于保留连接。更多信息,请参阅管理连接。 |