27.3.7.2 Подготовленные запросы
API подготовленных запросов позволяет повторно выполнять поддерживаемые SQL-запросы (см. Разрешенные SQL-конструкции в подготовленных запросах) без затрат на разбор и оптимизацию каждый раз.
Подготовленные запросы поддерживают параметризацию. Вопросительный знак (?) используется в качестве маркера параметра; параметры обновляются (связываются со значениями) предварительно, каждый раз при выполнении запроса, с помощью PreparedStatement.bind(). Подробнее см. описание этого метода.
Для освобождения ресурсов, занимаемых разобранным запросом и параметрами, вызовите PreparedStatement.deallocate(), который закрывает подготовленный запрос и освобождает его ресурсы. Пропуск деаллокации не приводит к ошибке, но память, используемая во время выполнения хранимых процедур, в противном случае не освобождается до завершения выполнения процедуры. После закрытия (деаллокации) подготовленного запроса он больше недоступен для выполнения.
Поток выполнения для подготовленных запросов состоит из следующих шагов:
Подготовка запроса (
prepare())Обновление параметров (
bind())Выполнение запроса (
execute())Закрытие запроса (
deallocate())
Шаги 2 и 3 могут быть повторены любое количество раз до закрытия подготовленного запроса.
Приведенная ниже хранимая процедура JavaScript jssp_prep1() принимает произвольный SQL-запрос, содержащий два маркера параметра, подготавливает запрос, затем дважды выполняет его, привязывая разные значения к параметрам каждый раз и выводя результат в stdout:
CREATE PROCEDURE jssp_prep1(IN query VARCHAR(200))
LANGUAGE JAVASCRIPT AS $$
function print_result(result) {
console.log(result.getColumnNames())
let row = result.fetchOne()
while(row) {
console.log(row.toArray())
row = result.fetchOne()
}
}
function fetch_warnings(result) {
console.log("Number of warnings: " + result.getWarningsCount())
for (var w in result.getWarnings()) {
console.log(w.level + ", " + w.code + ", " + w.message)
}
}
let stmt = session.prepare(query)
stmt.bind(3, 4)
let res1 = stmt.execute()
print_result(res1)
fetch_warnings(res1)
stmt.bind(2, 3)
let res2 = stmt.execute()
print_result(res2)
fetch_warnings(res2)
stmt.bind(5)
let res3 = stmt.execute()
print_result(res3)
fetch_warnings(res3)
stmt.deallocate()
$$;
После завершения работы с подготовленным запросом, мы закрываем его, освобождая любые ресурсы, используемые при подготовке и выполнении запроса, вызвав deallocate().
Разрешается вызывать bind() с меньшим количеством аргументов, чем параметров в запросе, после того, как все параметры были связаны хотя бы один раз. В этом случае, вызов stmt.bind(5) после предыдущего вызова stmt.bind(2,3) эквивалентен вызову stmt.bind(5,3) — отсутствующее второе значение повторно используется из предыдущего вызова, как показано здесь:
mysql> CALL jssp_prep1("
"> SELECT *
"> FROM t1
"> WHERE c1 = ? OR c1 = ?
"> ");
Query OK, 0 rows affected (0.03 sec)
mysql> SELECT mle_session_state("stdout")\G
*************************** 1. row ***************************
mle_session_state('stdout'): c1,c2,c3
3,37,peach
4,221,watermelon
Number of warnings: 0
c1,c2,c3
2,139,apple
3,37,peach
Number of warnings: 0
c1,c2,c3
3,37,peach
5,83,pear
Number of warnings: 0
1 row in set (0.00 sec)
© 2025 Oracle
Licensed under the GPLv2 License.