使用預處理語句

您可以定義一個預處理語句以供重複使用。這可以避免程式碼每次執行資料庫操作時重新建立語句的開銷,從而幫助您的程式碼執行得更快一些。

注意:預處理語句中的引數佔位符取決於您使用的 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)
    }
    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 提供了用於呼叫語句的常用 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 用於保留的連線。更多資訊請參閱管理連線