#mysql #sql #stored-procedures #prepared-statement
#mysql #sql #хранимые процедуры #подготовленный оператор
Вопрос:
Сегодня из этого раздела документации MySQL я узнал, что подготовленные инструкции не могут быть выполнены в хранимых функциях, но, начиная с версии MySQL 5.0.13, они могут выполняться в хранимых процедурах.
Сегодня я собирал хранимую процедуру и изначально подумал, что было бы интересно попробовать выполнить инструкцию INSERT в ней как подготовленную инструкцию. Однако, несмотря на то, что это предположительно возможно (я использую MySQL 5.5.14), ? маркер параметра в строке инструкции вызвал синтаксическую ошибку MySQL.
Я собрал пару упрощенных примеров, используя тот же синтаксис, который я использовал для подготовленного оператора INSERT . Я надеюсь, что у меня просто где-то есть синтаксическая ошибка, которую я просто не уловил. Первый блок, приведенный ниже, — это процедура, которая работает, то есть она использует стандартный синтаксис CONCAT (вашей строки запроса).
DROP PROCEDURE IF EXISTS TestConc;
DELIMITER $$
CREATE Procedure TestConc()
BEGIN
SET @sql := CONCAT('CREATE TABLE Foo (FooID INT) ENGINE = InnoDB');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @tn := 'Foo';
SET @sql := CONCAT('INSERT INTO ', @tn, ' VALUES (5)');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
$$
DELIMITER ;
При вызове процедуры с этим кодом происходит ожидаемое; 5 сохраняется в поле fooId вновь сгенерированной таблицы Foo. Однако, если мы изменим строки между двумя директивами DEALLOCATE PREPARE для этого:
SET @tn := 'Foo';
SET @sql := 'INSERT INTO ? VALUES (5)';
PREPARE stmt FROM @sql;
EXECUTE stmt USING @tn;
Мы получаем сообщение об ошибке, которое подсказывает нам проверить синтаксис оператора near ‘? ЗНАЧЕНИЯ (5)’.
Неужели просто невозможно заменить имя таблицы маркером параметра? Я не пробовал делать что-то вроде ‘SELECT? ИЗ Foo’, чтобы посмотреть, будет ли это работать. Кроме того, и я не знаю, важно ли это, я пробовал это, используя MySQL Workbench 5.2.35 CE, а не командную строку.
У меня нет какой-либо конкретной необходимости запускать запросы как подготовленные операторы в procedures ATM, я просто хочу убедиться, что у меня есть правильный синтаксис для этого, если мне когда-нибудь понадобится.
Ответ №1:
Параметр ‘?’ не может использоваться для идентификаторов. Используйте первый вариант. Из ссылки — маркеры параметров могут использоваться только там, где должны отображаться значения данных, а не для ключевых слов SQL, идентификаторов и так далее.
Ответ №2:
Неужели просто невозможно заменить имя таблицы маркером параметра?
Нет, это невозможно. Если вы когда-нибудь подумаете, что вам нужна эта функция, это может быть признаком того, что у вас плохой дизайн таблицы.
Если вам действительно нужно указать таблицу во время выполнения, вы можете использовать динамический SQL, но будьте осторожны, чтобы не вводить уязвимости SQL-инъекций.
Комментарии:
1. Интересно… Оператор INSERT не был особенно важен; Я надеялся создать несколько хранимых процедур общего назначения для некоторых общих задач. В частности, я хотел адаптировать что-то вроде функции PersonName на этой странице , чтобы она не была привязана к определенной таблице. Однако я понимаю, почему это было бы плохой идеей.