Использование подготовленных операторов
Вы можете определить подготовленный оператор для повторного использования. Это может помочь вашему коду работать немного быстрее, избегая накладных расходов на повторное создание оператора каждый раз, когда ваш код выполняет операцию с базой данных.
Примечание: Заполнители параметров в подготовленных операторах зависят от используемой СУБД и
драйвера. Например, драйвер pq для Postgres требует заполнитель вида $1
вместо ?.
Что такое подготовленный оператор?
Подготовленный оператор — это SQL-запрос, который анализируется и сохраняется СУБД, как правило, содержащий заполнители, но без фактических значений параметров. Позднее такой оператор может быть выполнен с набором значений параметров.
Как использовать подготовленные операторы
Когда вы ожидаете выполнять один и тот же SQL-запрос неоднократно, вы можете использовать sql.Stmt
для подготовки SQL-оператора заранее, а затем выполнять его по мере необходимости.
В следующем примере создаётся подготовленный оператор, который выбирает конкретный альбом из базы данных. DB.Prepare возвращает sql.Stmt,
представляющий подготовленный оператор для заданного текста SQL. Вы можете передать параметры SQL-оператора в
Stmt.Exec, Stmt.QueryRow или Stmt.Query, чтобы выполнить оператор.
<code>// 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
}
</code>
Поведение подготовленного оператора
Подготовленный 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. То есть, они преобразуют инструкцию, не предназначенную для транзакций, в инструкцию, подходящую для данной транзакции.Conn.PrepareContextсоздаёт подготовленную инструкцию изsql.Conn, который представляет зарезервированное подключение.
Убедитесь, что метод stmt.Close вызывается, когда код больше не нуждается в инструкции. Это
освободит все ресурсы базы данных (например, базовые подключения), связанные с ней. Для инструкций, являющихся
локальными переменными внутри функции, достаточно добавить defer stmt.Close().
Функции для создания подготовленной инструкции
| Функция | Описание |
|---|---|
DB.PrepareDB.PrepareContext
|
Подготавливает инструкцию для выполнения в изоляции или которая будет преобразована в инструкцию внутри транзакции с использованием Tx.Stmt. |
Tx.PrepareTx.PrepareContextTx.StmtTx.StmtContext
|
Подготавливает инструкцию для использования в конкретной транзакции. Более подробно см. Выполнение транзакций. |
Conn.PrepareContext
|
Используется с зарезервированными соединениями. Более подробно см. Управление соединениями. |