MySql подготовить оператор - возможно ли параметризовать имя столбца или имя функции? - PullRequest
0 голосов
/ 10 ноября 2018

Допустим, я хочу написать процедуру, позволяющую мне вызывать определенную функцию в определенном столбце, например:

call foo('min','age') -> SELECT min(age) FROM table;

Я хочу, чтобы моя процедура была защищена от SQL-инъекций, поэтому я хочу использовать подготовленные операторы и параметризовать ввод

SET @var = "SELECT ?(?) FROM table;"
PREPARE x FROM @var;
EXECUTE x USING a, b;

Где a и b - входные параметры, функция и столбец соответственно.

Однако это не представляется возможным - InnoDB продолжает выдавать ошибку всякий раз, когда я хочу выполнить этот оператор.

Можно ли решить эту проблему таким образом, или мне нужно прибегнуть к белым спискам?

EDIT: Полный код:

create procedure test(in func varchar(20), in col varchar(20))
  begin
    set @f = func;
    set @c = col;
    set @sql = "select ?(?) from table;";
    prepare x from @sql;
    execute x using @f, @c;
  end;

вызов:

call test('min','age');

Полная ошибка:

[42000] [1064] В вашем синтаксисе SQL есть ошибка; проверить руководство что соответствует вашей версии сервера MySQL для правильного синтаксиса используйте рядом с «(?) из таблицы» в строке 1

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018

Вы не можете параметризовать столбец / таблицу / имя функции / псевдоним. Так как оператор PREPARE разрешает использовать в качестве параметров только часть «значения» SQL-запроса. Функция / Таблица / Имя столбца / псевдоним используются для определения достоверности оператора SQL; и, следовательно, не может быть изменено во время выполнения. Изменение его во время выполнения потенциально может повлиять на правильность оператора SQL.

Вы можете думать об этом как о компиляции кода; следовательно, компилятор должен знать все имена функций / классов и т. д. для создания допустимого исполняемого файла (да, мы можем создавать динамические классы, но это редко ). С другой стороны, мы можем изменить входные «значения» для программы, но , как правило, не может изменить операции, выполняемые с входными данными.

Кроме того, сервер MySQL будет рассматривать параметры как литералы и заключать их в кавычки, прежде чем использовать их при выполнении запроса.

Теперь, в вашем случае, вы все равно можете использовать имя функции в качестве параметра для хранимой процедуры и генерировать строку запроса, используя это. Но вы не можете использовать его в качестве параметра для самого запроса.

delimiter $$
create procedure test(in func varchar(20), in col varchar(20))
  begin

    set @c = col;

    -- use concat function to generate the query string using func parameter
    set @sql = concat('select ', func, '(?) from table');

    -- prepare the statement
    prepare stmt from @sql;

    -- execute
    execute x using @c;

    -- don't forget to deallocate the prepared statement
    deallocate prepare stmt;
  end$$
delimiter ;
0 голосов
/ 10 ноября 2018

Единственный способ параметризации ключевых слов SQL в ключевом слове - использовать динамический запрос. Предостережение заключается в том, что динамические запросы, как правило, медленнее, чем статические, главным образом потому, что их нелегко кэшировать.

С предупреждением, что-то вроде этого должно работать:

SET @query = "SELECT ?('?') FROM table";  
EXECUTE stmt USING 'count', 'id';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...