Заявление PREPARE
Синтаксис
PREPARE stmt_name FROM preparable_stmt
Описание
Заявление PREPARE подготавливает запрос и присваивает ему имя, stmt_name, для дальнейшего обращения к нему. Имена запросов не чувствительны к регистру. preparable_stmt должно быть либо строковой константой, либо переменной пользователя (не локальной переменной, выражения SQL или подзапроса), содержащей текст запроса. Текст должен представлять собой единственное SQL-заявление, а не несколько. Внутри запроса символы "?" могут использоваться в качестве маркеров параметров, чтобы указать, где будут привязаны значения данных к запросу позже при его выполнении. Символы "?" не должны быть заключены в кавычки, даже если вы хотите привязать их к строковым значениям. Маркеры параметров могут использоваться только там, где должны быть выражения, а не для SQL-ключевых слов, идентификаторов и т. п.
Область действия подготовленного запроса — сеанс, в котором он создан. Другие сеансы его не видят.
Если подготовленный запрос с данным именем уже существует, он неявно освобождается перед подготовкой нового запроса. Это означает, что если новый запрос содержит ошибку и не может быть подготовлен, возвращается ошибка, и запрос с данным именем не существует.
Подготовленные запросы могут быть подготовлены (PREPARE) и выполнены (EXECUTE) в хранимой процедуре, но не в хранимой функции или триггере. Кроме того, даже если запрос подготовлен в процедуре, он не будет освобожден при завершении выполнения процедуры.
Подготовленный запрос может обращаться к переменным пользователя, но не к локальным переменным или параметрам процедуры.
Если подготовленный запрос содержит синтаксическую ошибку, PREPARE завершится с ошибкой. В качестве побочного эффекта, хранимые процедуры могут использовать это для проверки валидности запроса. Например:
CREATE PROCEDURE `test_stmt`(IN sql_text TEXT)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SELECT CONCAT(sql_text, ' is not valid');
END;
SET @SQL := sql_text;
PREPARE stmt FROM @SQL;
DEALLOCATE PREPARE stmt;
END;
Функции FOUND_ROWS() и ROW_COUNT(), если вызваны сразу после EXECUTE, возвращают количество прочитанных или затронутых строк подготовленными запросами; однако, если они вызываются после DEALLOCATE PREPARE, они предоставляют информацию об этом запросе. Если подготовленный запрос генерирует ошибки или предупреждения, GET DIAGNOSTICS возвращает информацию о них. DEALLOCATE PREPARE не должен очищать область диагностики, если только это не приводит к ошибке.
Подготовленный запрос выполняется с помощью EXECUTE и высвобождается с помощью DEALLOCATE PREPARE.
Переменная сервера max_prepared_stmt_count определяет количество разрешённых подготовленных запросов, которые могут быть подготовлены на сервере. Если она установлена в 0, подготовленные запросы запрещены. Если предел достигнут, будет генерироваться ошибка, похожая на следующую:
ERROR 1461 (42000): Can't create more than max_prepared_stmt_count statements (current value: 0)
Режим Oracle
В режиме Oracle начиная с MariaDB 10.3, PREPARE stmt FROM 'SELECT :1, :2' используется вместо ?.
Разрешённые заявления
Все заявления могут быть подготовлены, за исключением PREPARE, EXECUTE и DEALLOCATE / DROP PREPARE.
До этого не все заявления можно было готовить. Разрешены только следующие SQL-команды:
- ALTER TABLE
- ANALYZE TABLE
- BINLOG
- CACHE INDEX
- CALL
- CHANGE MASTER
- CHECKSUM {TABLE | TABLES}
- COMMIT
- {CREATE | DROP} DATABASE
- {CREATE | DROP} INDEX
- {CREATE | RENAME | DROP} TABLE
- {CREATE | RENAME | DROP} USER
- {CREATE | DROP} VIEW
- DELETE
- DESCRIBE
- DO
- EXPLAIN
- FLUSH {TABLE | TABLES | TABLES WITH READ LOCK | HOSTS | PRIVILEGES | LOGS | STATUS | MASTER | SLAVE | DES_KEY_FILE | USER_RESOURCES | QUERY CACHE | TABLE_STATISTICS | INDEX_STATISTICS | USER_STATISTICS | CLIENT_STATISTICS}
- GRANT
- INSERT
- INSTALL {PLUGIN | SONAME}
- HANDLER READ
- KILL
- LOAD INDEX INTO CACHE
- OPTIMIZE TABLE
- REPAIR TABLE
- REPLACE
- RESET {MASTER | SLAVE | QUERY CACHE}
- REVOKE
- ROLLBACK
- SELECT
- SET
- SET GLOBAL SQL_SLAVE_SKIP_COUNTER
- SET ROLE
- SET SQL_LOG_BIN
- SET TRANSACTION ISOLATION LEVEL
- SHOW EXPLAIN
- SHOW {DATABASES | TABLES | OPEN TABLES | TABLE STATUS | COLUMNS | INDEX | TRIGGERS | EVENTS | GRANTS | CHARACTER SET | COLLATION | ENGINES | PLUGINS [SONAME] | PRIVILEGES | PROCESSLIST | PROFILE | PROFILES | VARIABLES | STATUS | WARNINGS | ERRORS | TABLE_STATISTICS | INDEX_STATISTICS | USER_STATISTICS | CLIENT_STATISTICS | AUTHORS | CONTRIBUTORS}
- SHOW CREATE {DATABASE | TABLE | VIEW | PROCEDURE | FUNCTION | TRIGGER | EVENT}
- SHOW {FUNCTION | PROCEDURE} CODE
- SHOW BINLOG EVENTS
- SHOW SLAVE HOSTS
- SHOW {MASTER | BINARY} LOGS
- SHOW {MASTER | SLAVE | TABLES | INNODB | FUNCTION | PROCEDURE} STATUS
- SLAVE {START | STOP}
- TRUNCATE TABLE
- SHUTDOWN
- UNINSTALL {PLUGIN | SONAME}
- UPDATE
Синонимы здесь не перечислены, но могут быть использованы. Например, DESC можно использовать вместо DESCRIBE.
Составные заявления также могут быть подготовлены.
Обратите внимание, что если запрос можно выполнить в хранимой процедуре, он будет работать, даже если вызывается подготовленным запросом. Например, SIGNAL нельзя непосредственно подготовить. Однако он разрешен в хранимых процедурах. Если процедура x() содержит SIGNAL, вы по-прежнему можете подготовить и выполнить подготовленный запрос «CALL x();».
PREPARE поддерживает большинство типов выражений, например:
PREPARE stmt FROM CONCAT('SELECT * FROM ', table_name);
Если PREPARE используется с неподдерживаемым заявлением, генерируется следующая ошибка:
ERROR 1295 (HY000): This command is not supported in the prepared statement protocol yet
Пример
create table t1 (a int,b char(10)); insert into t1 values (1,"one"),(2, "two"),(3,"three"); prepare test from "select * from t1 where a=?"; set @param=2; execute test using @param; +------+------+ | a | b | +------+------+ | 2 | two | +------+------+ set @param=3; execute test using @param; +------+-------+ | a | b | +------+-------+ | 3 | three | +------+-------+ deallocate prepare test;
Поскольку идентификаторы не разрешены в качестве параметров подготовленных запросов, иногда необходимо динамически составлять SQL-запрос. Этот метод называется динамическим SQL. Следующий пример демонстрирует использование динамического SQL:
CREATE PROCEDURE test.stmt_test(IN tab_name VARCHAR(64))
BEGIN
SET @sql = CONCAT('SELECT COUNT(*) FROM ', tab_name);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
CALL test.stmt_test('mysql.user');
+----------+
| COUNT(*) |
+----------+
| 4 |
+----------+
Использование переменных в подготовленных запросах:
PREPARE stmt FROM 'SELECT @x;'; SET @x = 1; EXECUTE stmt; +------+ | @x | +------+ | 1 | +------+ SET @x = 0; EXECUTE stmt; +------+ | @x | +------+ | 0 | +------+ DEALLOCATE PREPARE stmt;
См. также
© 2023 MariaDB
Licensed under the Creative Commons Attribution 3.0 Unported License and the GNU Free Documentation License.
https://mariadb.com/kb/en/prepare-statement/