Procedimento armazenado MySQL vs função, qual eu usaria quando?

160

Eu estou olhando para procedimentos e funções armazenados do MySQL. Qual é a diferença real?

Eles parecem ser semelhantes, mas uma função tem mais limitações.

Provavelmente estou errado, mas parece que um procedimento armazenado pode fazer tudo e mais uma função armazenada. Por que / quando eu usaria um procedimento versus uma função?

Anonimato
fonte

Respostas:

101

Você não pode misturar procedimentos armazenados com SQL comum, enquanto a função armazenada pode.

por exemplo, SELECT get_foo(myColumn) FROM mytablenão é válido se get_foo()for um procedimento, mas você pode fazer isso se get_foo()for uma função. O preço é que as funções têm mais limitações que um procedimento.

n
fonte
18
Que tipo de limitações as funções têm?
Fantius 22/10/11
11
Ah, eu encontrei algumas informações boas aqui: dev.mysql.com/doc/refman/5.0/en/…
Fantius
262

A diferença mais geral entre procedimentos e funções é que eles são chamados de maneira diferente e para diferentes propósitos:

  1. Um procedimento não retorna um valor. Em vez disso, é invocado com uma instrução CALL para executar uma operação como modificar uma tabela ou processar registros recuperados.
  2. Uma função é chamada dentro de uma expressão e retorna um único valor diretamente ao chamador a ser usado na expressão.
  3. Você não pode chamar uma função com uma instrução CALL, nem um procedimento em uma expressão.

A sintaxe para criação de rotina é um pouco diferente para procedimentos e funções:

  1. Os parâmetros do procedimento podem ser definidos como somente entrada, somente saída ou ambos. Isso significa que um procedimento pode passar valores de volta para o chamador usando parâmetros de saída. Esses valores podem ser acessados ​​em instruções que seguem a instrução CALL. As funções têm apenas parâmetros de entrada. Como resultado, embora procedimentos e funções possam ter parâmetros, a declaração de parâmetro do procedimento difere da das funções.
  2. As funções retornam valor, portanto, deve haver uma cláusula RETURNS em uma definição de função para indicar o tipo de dados do valor retornado. Além disso, deve haver pelo menos uma instrução RETURN no corpo da função para retornar um valor ao chamador. RETURNS e RETURN não aparecem nas definições de procedimento.

    • Para invocar um procedimento armazenado, use o CALL statement. Para invocar uma função armazenada, consulte-a em uma expressão. A função retorna um valor durante a avaliação da expressão.

    • Um procedimento é chamado usando uma instrução CALL e só pode transmitir valores usando variáveis ​​de saída. Uma função pode ser chamada de dentro de uma instrução como qualquer outra função (ou seja, invocando o nome da função) e pode retornar um valor escalar.

    • A especificação de um parâmetro como IN, OUT ou INOUT é válida apenas para um PROCEDURE. Para uma FUNÇÃO, os parâmetros são sempre considerados como parâmetros IN.

    Se nenhuma palavra-chave for fornecida antes do nome de um parâmetro, é um parâmetro IN por padrão. Os parâmetros para funções armazenadas não são precedidos por IN, OUT ou INOUT. Todos os parâmetros de função são tratados como parâmetros IN.

Para definir um procedimento ou função armazenada, use CREATE PROCEDURE ou CREATE FUNCTION, respectivamente:

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


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

Uma extensão do MySQL para procedimento armazenado (não funções) é que um procedimento pode gerar um conjunto de resultados, ou mesmo vários conjuntos de resultados, que o chamador processa da mesma maneira que o resultado de uma instrução SELECT. No entanto, o conteúdo desses conjuntos de resultados não pode ser usado diretamente na expressão.

Rotinas armazenadas (referentes a procedimentos armazenados e funções armazenadas) são associadas a um banco de dados específico, assim como tabelas ou visualizações. Quando você solta um banco de dados, quaisquer rotinas armazenadas no banco de dados também são eliminadas.

Procedimentos e funções armazenados não compartilham o mesmo espaço para nome. É possível ter um procedimento e uma função com o mesmo nome em um banco de dados.

Nos procedimentos armazenados, o SQL dinâmico pode ser usado, mas não em funções ou gatilhos.

Instruções preparadas para SQL (PREPARE, EXECUTE, DEALLOCATE PREPARE) podem ser usadas em procedimentos armazenados, mas não em funções ou gatilhos armazenados. Portanto, funções e gatilhos armazenados não podem usar o SQL dinâmico (onde você constrói instruções como seqüências de caracteres e as executa). (SQL dinâmico nas rotinas armazenadas do MySQL)

Algumas diferenças mais interessantes entre FUNÇÃO e PROCEDIMENTO ARMAZENADO:

  1. ( Este ponto é copiado de um post do blog . ) O procedimento armazenado é um plano de execução pré-compilado onde as funções não são. Função Analisada e compilada em tempo de execução. Procedimentos armazenados, Armazenados como um pseudo-código no banco de dados, ou seja, na forma compilada.

  2. ( Não tenho certeza sobre este ponto. )
    O procedimento armazenado tem a segurança e reduz o tráfego da rede e também podemos chamar o procedimento armazenado em qualquer não. de aplicativos por vez. referência

  3. As funções são normalmente usadas para cálculos em que, como procedimentos, são normalmente usados ​​para executar a lógica de negócios.

  4. Funções não podem afetar o estado do banco de dados (Instruções que executam consolidação ou reversão explícita ou implícita não são permitidas na função) Enquanto procedimentos armazenados podem afetar o estado do banco de dados usando consolidação etc.
    refence: J.1. Restrições em rotinas armazenadas e gatilhos

  5. As funções não podem usar instruções FLUSH , enquanto os procedimentos armazenados podem.

  6. As funções armazenadas não podem ser recursivas Enquanto os procedimentos armazenados podem ser. Nota: Os procedimentos armazenados recursivos são desativados por padrão, mas podem ser ativados no servidor configurando a variável de sistema do servidor max_sp_recursion_depth como um valor diferente de zero. Consulte a Seção 5.2.3, “Variáveis ​​do sistema” , para obter mais informações.

  7. Dentro de uma função ou gatilho armazenado, não é permitido modificar uma tabela que já está sendo usada (para leitura ou gravação) pela instrução que invocou a função ou gatilho. Bom exemplo: Como atualizar a mesma tabela ao excluir no MYSQL?

Nota : embora algumas restrições normalmente se apliquem a funções e gatilhos armazenados, mas não a procedimentos armazenados, essas restrições se aplicam a procedimentos armazenados se forem invocados de dentro de uma função ou gatilho armazenado. Por exemplo, embora você possa usar FLUSH em um procedimento armazenado, esse procedimento armazenado não pode ser chamado de uma função ou gatilho armazenado.

Grijesh Chauhan
fonte
2
@GrijeshChauhan, o que você quer dizer quando diz "Função analisada e compilada em tempo de execução" ?
Pacerier 29/01
@Pacerier significa que funções no MySQL são como scripts que compilam e executam em tempo real. Copiei-o de algum post do blog , mas não realizei nenhuma prática para inspecionar esses comportamentos.
Grijesh Chauhan
Em procedimentos que você pode passar uma variável como parâmetro, então chamá-lo com uma instrução SELECT
LTroya
1
O ponto de bala nº 4 na seção inferior desta resposta é, penso eu, o cerne da diferença entre procedimentos e funções. procedimentos podem alterar o banco de dados, funções não. todas as outras diferenças são apenas para servir a esse propósito de forma mais eficaz.
Woodrow Barlow
51

Uma diferença significativa é que você pode incluir uma função em suas consultas SQL, mas os procedimentos armazenados só podem ser chamados com a CALLinstrução:

Exemplo de 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)

Exemplo do 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)
Daniel Vassallo
fonte
1
Sua função tem dois retornos ? Quero dizer, o que é essa linha? RETURNS CHAR(50) DETERMINISTIC?
Martin AJ
Os RETURNS CHAR(50)estados que tipo de dados serão retornados. Os RETURN CONCAT(...dados estão sendo retornados. Ambos são necessários. A DETERMINISTICé necessária para afirmar que os dados subjacentes não será modificado.
precisa saber é o seguinte
8

Uma função armazenada pode ser usada dentro de uma consulta. Você pode aplicá-lo a todas as linhas ou dentro de uma cláusula WHERE.

Um procedimento é executado usando a consulta CALL.

Evert
fonte
0

O procedimento armazenado pode ser chamado recursivamente, mas a função armazenada não pode

palash140
fonte