MySQL хранимая процедура против функции, что я буду использовать, когда?


160

Я смотрю на хранимые процедуры и функции MySQL. В чем реальная разница?

Они кажутся похожими, но функция имеет больше ограничений.

Я, вероятно, ошибаюсь, но кажется, что хранимая процедура может сделать все, и больше может хранимая функция. Почему / когда я использовал бы процедуру против функции?

Ответы:


101

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

Например SELECT get_foo(myColumn) FROM mytable, недопустимо, если get_foo()это процедура, но вы можете сделать это, если get_foo()это функция. Цена заключается в том, что функции имеют больше ограничений, чем процедура.


18
Какие ограничения есть у функций?
Фантиус

11
Ах, я нашел немного хорошей информации здесь: dev.mysql.com/doc/refman/5.0/en/…
Фантиус

262

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

  1. Процедура не возвращает значение. Вместо этого он вызывается с помощью оператора CALL для выполнения такой операции, как изменение таблицы или обработка полученных записей.
  2. Функция вызывается внутри выражения и возвращает одно значение непосредственно вызывающей стороне для использования в выражении.
  3. Вы не можете вызывать функцию с оператором CALL и не можете вызывать процедуру в выражении.

Синтаксис для рутинного создания несколько отличается для процедур и функций:

  1. Параметры процедуры могут быть определены как только входные, только выходные или оба. Это означает, что процедура может передавать значения обратно вызывающей стороне, используя выходные параметры. Эти значения могут быть доступны в операторах, следующих за оператором CALL. Функции имеют только входные параметры. В результате, хотя и процедуры, и функции могут иметь параметры, объявление параметров процедуры отличается от описания для функций.
  2. Функции возвращают значение, поэтому в определении функции должно быть предложение RETURNS, чтобы указать тип данных возвращаемого значения. Кроме того, в теле функции должен быть хотя бы один оператор RETURN для возврата значения вызывающей стороне. ВОЗВРАТ и ВОЗВРАТ не отображаются в определениях процедур.

    • Чтобы вызвать хранимую процедуру, используйте CALL statement. Чтобы вызвать сохраненную функцию, обратитесь к ней в выражении. Функция возвращает значение во время вычисления выражения.

    • Процедура вызывается с помощью оператора CALL и может только возвращать значения, используя выходные переменные. Функция может быть вызвана из оператора точно так же, как и любая другая функция (то есть путем вызова имени функции), и может возвращать скалярное значение.

    • Указание параметра как IN, OUT или INOUT действительно только для ПРОЦЕДУРЫ. Для ФУНКЦИИ параметры всегда рассматриваются как параметры IN.

    Если перед именем параметра не указано ключевое слово, по умолчанию это параметр IN. Параметрам для сохраненных функций не предшествуют IN, OUT или INOUT. Все параметры функции рассматриваются как параметры IN.

Чтобы определить хранимую процедуру или функцию, используйте CREATE PROCEDURE или CREATE FUNCTION соответственно:

CREATE PROCEDURE proc_name ([parameters])
 [characteristics]
 routine_body


CREATE FUNCTION func_name ([parameters])
 RETURNS data_type       // diffrent
 [characteristics]
 routine_body

Расширение MySQL для хранимой процедуры (не функции) заключается в том, что процедура может генерировать набор результатов или даже несколько наборов результатов, которые вызывающая сторона обрабатывает так же, как результат оператора SELECT. Однако содержимое таких наборов результатов нельзя использовать непосредственно в выражении.

Хранимые подпрограммы (относящиеся как к хранимым процедурам, так и к хранимым функциям) связаны с конкретной базой данных, как таблицы или представления. Когда вы удаляете базу данных, любые сохраненные подпрограммы в базе данных также удаляются.

Хранимые процедуры и функции не разделяют одно и то же пространство имен. Можно иметь процедуру и функцию с одинаковым именем в базе данных.

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

Подготовленные SQL операторы (PREPARE, EXECUTE, DEALLOCATE PREPARE) могут использоваться в хранимых процедурах, но не в хранимых функциях или триггерах. Таким образом, хранимые функции и триггеры не могут использовать динамический SQL (где вы строите операторы как строки, а затем выполняете их). (Динамический SQL в хранимых подпрограммах MySQL)

Еще несколько интересных отличий между FUNCTION и STORED PROCEDURE:

  1. ( Этот пункт скопирован из поста в блоге . ) Хранимая процедура - это предварительно скомпилированный план выполнения, в котором функции отсутствуют. Функция анализируется и компилируется во время выполнения. Хранимые процедуры, хранящиеся в виде псевдокода в базе данных, т.е. скомпилированные формы.

  2. ( Я не уверен в этом. )
    Хранимая процедура имеет безопасность и снижает сетевой трафик, а также мы можем вызвать хранимую процедуру в любом нет. приложений одновременно. ссылка

  3. Функции обычно используются для вычислений, где процедуры обычно используются для выполнения бизнес-логики.

  4. Функции не могут влиять на состояние базы данных (операторы, которые выполняют явную или неявную фиксацию или откат, запрещены в функции), в то время как хранимые процедуры могут влиять на состояние базы данных с помощью фиксации и т. Д.
    Refrence: J.1. Ограничения на хранимые процедуры и триггеры

  5. Функции не могут использовать операторы FLUSH, тогда как хранимые процедуры могут.

  6. Хранимые функции не могут быть рекурсивными, тогда как хранимые процедуры могут быть. Примечание. Рекурсивные хранимые процедуры по умолчанию отключены, но их можно включить на сервере, задав для системной переменной сервера max_sp_recursion_depth ненулевое значение. См. Раздел 5.2.3, «Системные переменные» , для получения дополнительной информации.

  7. Внутри хранимой функции или триггера запрещено изменять таблицу, которая уже используется (для чтения или записи) оператором, который вызвал функцию или триггер. Хороший пример: как обновить ту же таблицу при удалении в MYSQL?

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


2
@GrijeshChauhan, что вы имеете в виду, когда говорите, что «Функция проанализирована и скомпилирована во время выполнения» ?
Pacerier

@Pacerier означает, что функции в MySQL - это что-то вроде скриптов, которые компилируются и выполняются на лету. Я скопировал это из некоторого сообщения в блоге , но не выполнил никакой практической проверки этого поведения.
Грижеш Чаухан

В процедурах вы можете передать переменную out в качестве параметра, а затем вызвать ее с помощью оператора select
LTroya

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

51

Существенным отличием является то, что вы можете включить функцию в ваши запросы SQL, но хранимые процедуры можно вызывать только с помощью CALLоператора:

Пример UDF:

CREATE FUNCTION hello (s CHAR(20))
   RETURNS CHAR(50) DETERMINISTIC
   RETURN CONCAT('Hello, ',s,'!');
Query OK, 0 rows affected (0.00 sec)

CREATE TABLE names (id int, name varchar(20));
INSERT INTO names VALUES (1, 'Bob');
INSERT INTO names VALUES (2, 'John');
INSERT INTO names VALUES (3, 'Paul');

SELECT hello(name) FROM names;
+--------------+
| hello(name)  |
+--------------+
| Hello, Bob!  |
| Hello, John! |
| Hello, Paul! |
+--------------+
3 rows in set (0.00 sec)

Пример Sproc:

delimiter //

CREATE PROCEDURE simpleproc (IN s CHAR(100))
BEGIN
   SELECT CONCAT('Hello, ', s, '!');
END//
Query OK, 0 rows affected (0.00 sec)

delimiter ;

CALL simpleproc('World');
+---------------------------+
| CONCAT('Hello, ', s, '!') |
+---------------------------+
| Hello, World!             |
+---------------------------+
1 row in set (0.00 sec)

1
Ваша функция имеет два возврата ? Я имею в виду, что это за линия? RETURNS CHAR(50) DETERMINISTIC?
Мартин Эй Джей

В RETURNS CHAR(50)состоянии , какой тип данных будет возвращено. Это RETURN CONCAT(...данные, которые возвращаются. Оба необходимы. DETERMINISTICНеобходимо , чтобы состояние , что основные данные не будут изменены.
lemming622

8

Хранимая функция может быть использована в запросе. Затем вы можете применить его к каждой строке или в предложении WHERE.

Процедура выполняется с использованием запроса CALL.


0

Хранимая процедура может вызываться рекурсивно, но хранимая функция не может

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.