13.5 Подготовленные запросы
MySQL 5.7 поддерживает подготовленные запросы на стороне сервера. Эта поддержка использует преимущества эффективного двоичного протокола клиент-сервер. Использование подготовленных запросов с заполнителями для значений параметров имеет следующие преимущества:
Меньшие накладные расходы при парсинге запроса каждый раз при его выполнении. Обычно приложения баз данных обрабатывают большие объемы почти идентичных запросов, с изменениями только значений литералов или переменных в таких клаузах, как
WHEREдля запросов и удалений,SETдля обновлений иVALUESдля вставок.-
Защита от атак SQL-инъекций. Значения параметров могут содержать неэкранированные символы кавычек и разделителей SQL.
Следующие разделы содержат обзор характеристик подготовленных запросов:
Подготовленные запросы в прикладных программах
Вы можете использовать подготовленные запросы на стороне сервера через клиентские программные интерфейсы, включая для программ на C, для программ на Java и для программ, использующих технологии .NET. Например, C API предоставляет набор функций, составляющих его API для подготовленных запросов. Смотрите . Другие языковые интерфейсы могут поддерживать подготовленные запросы, использующие двоичный протокол, связывая с клиентской библиотекой C, например, mysqli расширение, доступное в PHP 5.0 и выше.
Подготовленные запросы в скриптах SQL
Доступен альтернативный SQL-интерфейс для подготовленных запросов. Этот интерфейс не так эффективен, как использование двоичного протокола через API подготовленных запросов, но не требует программирования, поскольку он доступен непосредственно на уровне SQL:
Вы можете использовать его, когда у вас нет доступного программного интерфейса.
Вы можете использовать его из любой программы, которая может отправлять SQL-запросы на сервер для выполнения, например, программа-клиент mysql.
Вы можете использовать его, даже если клиент использует старую версию клиентской библиотеки.
Синтаксис SQL для подготовленных запросов предназначен для использования в таких ситуациях:
Для тестирования работы подготовленных запросов в вашем приложении до его кодирования.
Для использования подготовленных запросов, когда у вас нет доступа к программному API, которое их поддерживает.
Для интерактивного устранения неполадок с подготовленными запросами в приложении.
Для создания тестового случая, воспроизводящего проблему с подготовленными запросами, чтобы вы могли отправить отчёт об ошибке.
Операторы PREPARE, EXECUTE и DEALLOCATE PREPARE
Синтаксис SQL для подготовленных запросов основан на трёх SQL-операторах:
PREPAREподготавливает запрос к выполнению (см. Раздел 13.5.1, «Оператор PREPARE»).EXECUTEвыполняет подготовленный запрос (см. Раздел 13.5.2, «Оператор EXECUTE»).DEALLOCATE PREPAREосвобождает подготовленный запрос (см. Раздел 13.5.3, «Оператор DEALLOCATE PREPARE»).
Следующие примеры показывают два равнозначных способа подготовки запроса, вычисляющего гипотенузу треугольника по длинам двух сторон.
Первый пример показывает, как создать подготовленный запрос, используя строковый литерал для предоставления текста запроса:
mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;
+------------+
| hypotenuse |
+------------+
| 5 |
+------------+
mysql> DEALLOCATE PREPARE stmt1;
Второй пример аналогичен, но предоставляет текст запроса в качестве переменной пользователя:
mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> PREPARE stmt2 FROM @s;
mysql> SET @a = 6;
mysql> SET @b = 8;
mysql> EXECUTE stmt2 USING @a, @b;
+------------+
| hypotenuse |
+------------+
| 10 |
+------------+
mysql> DEALLOCATE PREPARE stmt2;
Вот дополнительный пример, который демонстрирует, как выбрать таблицу для выполнения запроса во время выполнения, сохранив имя таблицы как переменную пользователя:
mysql> USE test;
mysql> CREATE TABLE t1 (a INT NOT NULL);
mysql> INSERT INTO t1 VALUES (4), (8), (11), (32), (80);
mysql> SET @table = 't1';
mysql> SET @s = CONCAT('SELECT * FROM ', @table);
mysql> PREPARE stmt3 FROM @s;
mysql> EXECUTE stmt3;
+----+
| a |
+----+
| 4 |
| 8 |
| 11 |
| 32 |
| 80 |
+----+
mysql> DEALLOCATE PREPARE stmt3;
Подготовленный запрос специфичен для сеанса, в котором он был создан. Если вы завершите сеанс, не освободив ранее подготовленный запрос, сервер автоматически освободит его.
Подготовленный запрос также является глобальным для сеанса. Если вы создаете подготовленный запрос внутри хранимой процедуры, он не освобождается при завершении хранимой процедуры.
Для защиты от одновременного создания слишком большого количества подготовленных запросов, установите системную переменную max_prepared_stmt_count. Для предотвращения использования подготовленных запросов установите значение 0.
Разрешенные синтаксические конструкции SQL в подготовленных запросах
Следующие SQL-операторы могут использоваться как подготовленные запросы:
ALTER TABLE
ALTER USER
ANALYZE TABLE
CACHE INDEX
CALL
CHANGE MASTER
CHECKSUM {TABLE | TABLES}
COMMIT
{CREATE | DROP} INDEX
{CREATE | RENAME | DROP} DATABASE
{CREATE | DROP} TABLE
{CREATE | RENAME | DROP} USER
{CREATE | DROP} VIEW
DELETE
DO
FLUSH {TABLE | TABLES | TABLES WITH READ LOCK | HOSTS | PRIVILEGES
| LOGS | STATUS | MASTER | SLAVE | DES_KEY_FILE | USER_RESOURCES}
GRANT
INSERT
INSTALL PLUGIN
KILL
LOAD INDEX INTO CACHE
OPTIMIZE TABLE
RENAME TABLE
REPAIR TABLE
REPLACE
RESET {MASTER | SLAVE | QUERY CACHE}
REVOKE
SELECT
SET
SHOW BINLOG EVENTS
SHOW CREATE {PROCEDURE | FUNCTION | EVENT | TABLE | VIEW}
SHOW {MASTER | BINARY} LOGS
SHOW {MASTER | SLAVE} STATUS
SLAVE {START | STOP}
TRUNCATE TABLE
UNINSTALL PLUGIN
UPDATE
Другие операторы не поддерживаются.
Для соответствия стандарту SQL, который гласит, что операторы диагностики не могут быть подготовлены, MySQL не поддерживает следующие как подготовленные запросы:
SHOW WARNINGS,SHOW COUNT(*) WARNINGSSHOW ERRORS,SHOW COUNT(*) ERRORSОператоры, содержащие ссылки на системную переменную
warning_countилиerror_count.
В общем, операторы, запрещенные в подготовленных SQL-запросах, также запрещены в хранимых программах. Исключения указаны в Разделе 23.8, «Ограничения на хранимые программы».
Изменения метаданных таблиц или представлений, на которые ссылаются подготовленные запросы, обнаруживаются и вызывают автоматическое переподготовку запроса при его последующем выполнении. Для получения дополнительной информации см. Раздел 8.10.4, «Кэширование подготовленных запросов и хранимых программ».
Заполнители могут использоваться для аргументов клаузы LIMIT при использовании подготовленных запросов. См. Раздел 13.2.9, «Оператор SELECT».
В подготовленных операторах CALL, используемых с PREPARE и EXECUTE, поддержка заполнителей для параметров OUT и INOUT доступна начиная с MySQL 5.7. См. Раздел 13.2.1, «Оператор CALL» для примера и обходного решения для более ранних версий. Заполнители могут использоваться для параметров IN независимо от версии.
Синтаксис SQL для подготовленных запросов не может быть использован вложенным образом. То есть оператор, переданный в PREPARE, не может сам по себе быть оператором PREPARE, EXECUTE или DEALLOCATE PREPARE.
Синтаксис SQL для подготовленных запросов отличается от использования вызовов API подготовленных запросов. Например, вы не можете использовать функцию C API для подготовки оператора PREPARE, EXECUTE или DEALLOCATE PREPARE.
Синтаксис SQL для подготовленных запросов может использоваться внутри хранимых процедур, но не в хранимых функциях или триггерах. Однако курсор не может быть использован для динамического оператора, подготовленного и выполняемого с помощью PREPARE и EXECUTE. Оператор для курсора проверяется на этапе создания курсора, поэтому оператор не может быть динамическим.
Синтаксис SQL для подготовленных запросов не поддерживает многооператоры (то есть несколько операторов в одной строке, разделенные символами ;).
Подготовленные запросы используют кэш запросов в условиях, описанных в Разделе 8.10.3.1, «Как работает кэш запросов».
Для написания программ на C, использующих оператор CALL SQL для выполнения хранимых процедур, содержащих подготовленные операторы, необходимо включить флаг CLIENT_MULTI_RESULTS. Это связано с тем, что каждый оператор CALL возвращает результат, указывающий статус вызова, помимо любых наборов результатов, которые могут быть возвращены операторами, выполняемыми внутри процедуры.
CLIENT_MULTI_RESULTS можно включить при вызове, либо явно, передав флаг CLIENT_MULTI_RESULTS, либо неявно, передав CLIENT_MULTI_STATEMENTS (что также включает CLIENT_MULTI_RESULTS). Дополнительную информацию см. в разделе 13.2.1, «Оператор CALL».
© 2025 Oracle
Licensed under the GPLv2 License.