Некоторые причины использования хранимых процедур:
- Предположительно, они прошли некоторое тестирование, чтобы убедиться, что они не допускают нарушения бизнес-правил, а также некоторую оптимизацию производительности.
- Они обеспечивают согласованность результатов.Каждый раз, когда вас просят выполнить задачу X, вы запускаете хранимую процедуру, связанную с задачей X. Если вы пишете запрос, вы не можете писать его каждый раз одинаково;может быть, однажды вы забудете что-то глупое, например, принуждение текста к одному и тому же случаю перед сравнением, и что-то будет пропущено.
- Они начинают писать несколько дольше, чем просто запрос, но выполнение этой хранимой процедуры занимает меньше времениснова пишу запрос.Запустите его достаточно раз, и он станет более эффективным для написания хранимой процедуры.
- Они уменьшают или устраняют необходимость знать взаимосвязи базовых таблиц.
- Вы можете предоставить разрешения на выполнение хранимой процедуры.процедуры (с
security definer
), но запрещают разрешения для базовых таблиц. - Программистам (если вы разделяете администраторов баз данных и программистов) может быть предоставлен API, и это все, что им нужно знать.Пока вы поддерживаете API при изменении базы данных, вы можете вносить любые необходимые изменения в базовые отношения, не нарушая их программное обеспечение;на самом деле, вам даже не нужно знать, что они сделали с вашим API.
Скорее всего, вы закончите тем, что сделаете одну хранимую процедуру на запрос, который в противном случае выполняете.
IЯ не уверен, почему вы считаете это неэффективным или особенно трудоемким по сравнению с простым написанием запроса.Если все, что вы делаете, это помещаете запрос в хранимую процедуру, дополнительная работа должна быть минимальной.
CREATE OR REPLACE FUNCTION aSchema.aProcedure (
IN var1 text,
IN var2 text,
OUT col1 text,
OUT col2 text
)
RETURNS setof record
LANGUAGE plpgsql
VOLATILE
CALLED ON NULL INPUT
SECURITY DEFINER
SET search_path = aSchema, pg_temp
AS $body$
BEGIN
RETURN QUERY /*the query you would have written anyway*/;
END;
$body$;
GRANT EXECUTE ON FUNCTION aSchema.aProcedure(text, text) TO public;
Как вы использовали в предыдущем вопросе, функция может быть еще более динамичной, передавая столбцы /таблиц в качестве параметров и использования EXECUTE (хотя это увеличивает то, сколько человек, выполняющий функцию, должен знать о том, как работает функция, поэтому я стараюсь избегать этого).
Если «менее эффективный» исходит из дополнительныхлогика, которая включена в функцию, тогда сравнение с использованием только запросов не справедливо, так как функция выполняет дополнительную работу.