Альтернативы динамическому SQL в хранимой функции - PullRequest
2 голосов
/ 27 июня 2019

Я пишу хранимую функцию, в которой вычисляю положение ячейки, значение которой мне нужно выбрать из таблицы. Для этого я решил сохранить эту позицию в переменной, чтобы использовать ее в качестве смещения предложения LIMIT.

Согласно моему исследованию, способ использования значений, установленных в локальные переменные с помощью оператора LIMIT, - через подготовленный оператор, но я также понял, что подготовленные операторы (или любой динамический SQL) разрешены в хранимых функциях. Есть ли альтернативы для решения моей проблемы?

Упрощенный пример моей ситуации:

CREATE FUNCTION foo(a int) RETURNS decimal DETERMINISTIC
BEGIN
     SET @var1 := (SELECT COUNT(*) FROM table);
     SET @var2 := (ROUND(@var1 * a/5))
     PREPARE STMT FROM 'RETURN (SELECT * FROM other_table LIMIT ?, ?)';
     EXECUTE STMT USING @var2, @var1;
END
$$ DELIMITER ;

В идеале, это даст мне тот результат, который мне нужен, там, где он мне нужен. Но, конечно, я получаю код ошибки 1336, говорящий «Динамический SQL не разрешен в хранимой функции или триггере»

1 Ответ

1 голос
/ 27 июня 2019

Вам не нужен динамический SQL для этой хранимой функции.Вам не нужно использовать динамический SQL для предложения LIMIT.Вам просто нужно убедиться, что переменные имеют тип INT, а не строки.

Вот краткая демонстрация:

create function foo(a int) returns int reads sql data 
begin 
  return (select x from test limit 1 offset a); 
end

Обратите внимание на несколько других вещей:

  • Используйте READS SQL DATA вместо DETERMINISTIC.Ваша функция не является детерминированной.Вы должны прочитать страницу руководства по функции создания, чтобы лучше понять эти опции.
  • Не используйте SELECT *.Функция может возвращать только одно скалярное значение, а не набор столбцов.Таблица, которую вы запрашиваете, на самом деле может иметь один столбец, но это хорошая привычка делать запросы более понятными.
  • Использование LIMIT без ORDER BY может вас удивить позже, потому что это не гарантируеткакой порядок он будет использовать для определения смещения.Лучше всего, если вы используете ORDER BY явно.
  • При использовании LIMIT, я думаю, более понятно использовать LIMIT <count> OFFSET <offset> вместо LIMIT <offset>, <count>.Они делают то же самое, но легче запомнить, какой аргумент какой.
  • Ваш запрос LIMIT, по-видимому, выбирает много строк.Вам нужен запрос, чтобы выбрать ровно один столбец и одну строку, иначе он недопустим для возврата из сохраненной функции.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...