プリペアドステートメントの使用

プリペアドステートメントを繰り返し使用するために定義できます。これにより、コードがデータベース操作を実行するたびにステートメントを再作成するオーバーヘッドを回避できるため、コードの実行速度が少し速くなります。

注意: プリペアドステートメントのパラメータープレースホルダーは、使用しているDBMSおよびドライバによって異なります。例えば、Postgres用のpqドライバは、?の代わりに$1のようなプレースホルダーを必要とします。

プリペアドステートメントとは?

プリペアドステートメントとは、DBMSによって解析され保存されたSQLであり、通常はプレースホルダーを含みますが、実際のパラメータ値は含まれません。その後、ステートメントは一連のパラメータ値とともに実行できます。

プリペアドステートメントの利用方法

同じSQLを繰り返し実行する予定がある場合は、sql.Stmtを使用してSQLステートメントを事前に準備し、必要に応じて実行できます。

以下の例では、データベースから特定のアルバムを選択するプリペアドステートメントを作成します。DB.Prepareは、指定されたSQLテキストのプリペアドステートメントを表すsql.Stmtを返します。SQLステートメントのパラメータをStmt.ExecStmt.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は、ステートメントを呼び出すための通常のExecQueryRow、およびQueryメソッドを提供します。これらのメソッドの使用方法の詳細については、データのクエリおよびデータを返さないSQLステートメントの実行を参照してください。

しかし、sql.StmtはすでにプリセットされたSQLステートメントを表しているため、そのExecQueryRow、およびQueryメソッドは、SQLテキストを省略し、プレースホルダーに対応するSQLパラメータ値のみを受け取ります。

使用方法に応じて、新しいsql.Stmtをさまざまな方法で定義できます。

  • DB.PrepareおよびDB.PrepareContextは、DB.ExecおよびDB.Queryと同様に、トランザクションの外で単独で実行できるプリペアドステートメントを作成します。
  • Tx.PrepareTx.PrepareContextTx.Stmt、およびTx.StmtContextは、特定のトランザクション内で使用するためのプリペアドステートメントを作成します。PrepareおよびPrepareContextはSQLテキストを使用してステートメントを定義します。StmtおよびStmtContextDB.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 予約済み接続での使用。詳細については、接続の管理を参照してください。