MySQL: Uma explicação detalhada sobre procedimentos…
Última atualização: 2026-08-26
Os procedimentos armazenados são conjuntos pré-compilados de instruções SQL — basta escrevê-los uma vez para chamá-los várias vezes.
Esta aula aborda a criação e o uso de procedimentos armazenados e funções.
graph TB
A[CALL Stored Procedures] --> B[Parameter Passing IN/OUT/INOUT]
B --> C[DECLARE Declare a variable]
C --> D{Process Control}
D --> E[IF / CASE Conditions]
D --> F[WHILE / LOOP Loop]
D --> G[Cursor CURSOR Iterate]
E --> H[ExecuteSQL]
F --> H
G --> H
H --> I[OUTParameter Return]
I --> J[End]
1. O que você vai aprender
- CREATE PROCEDURE: Criar um procedimento armazenado
- Tipos de parâmetros IN/OUT/INOUT
- DECLARE: Declaração de variável
- Controle de fluxo IF/CASE/WHILE
- Cursor CURSOR
2. Cenários da vida real
(1) Desafio: Escrever repetidamente lógicas complexas
Calculamos a folha de pagamento total de cada departamento todos os meses, mas a consulta SQL é muito longa e é executada repetidamente.
(2) Solução utilizando procedimentos armazenados
CREATE PROCEDURE sp_dept_salary_stats()
BEGIN
SELECT department, SUM(salary) AS total_salary, AVG(salary) AS avg_salary
FROM employees
GROUP BY department;
END;
-- Call
CALL sp_dept_salary_stats();
3. Criação de um procedimento armazenado
▶ Exemplo: Procedimento armazenado básico
-- Create a Stored Procedure
DELIMITER //
CREATE PROCEDURE sp_get_user(IN user_id INT)
BEGIN
SELECT * FROM users WHERE id = user_id;
END //
DELIMITER ;
-- Call
CALL sp_get_user(1);
▶ Exemplo: Com um parâmetro OUT
DELIMITER //
CREATE PROCEDURE sp_count_users(OUT total INT)
BEGIN
SELECT COUNT(*) INTO total FROM users;
END //
DELIMITER ;
-- Call
CALL sp_count_users(@total);
SELECT @total;
▶ Exemplo: Com parâmetros INOUT
DELIMITER //
CREATE PROCEDURE sp_double(INOUT num INT)
BEGIN
SET num = num * 2;
END //
DELIMITER ;
-- Call
SET @num = 5;
CALL sp_double(@num);
SELECT @num; -- 10
4. Declaração de variáveis
▶ Exemplo: DECLARE variável
DELIMITER //
CREATE PROCEDURE sp_variable_demo()
BEGIN
DECLARE total INT DEFAULT 0;
DECLARE avg_salary DECIMAL(10,2);
DECLARE user_name VARCHAR(50);
-- Assignment
SELECT COUNT(*) INTO total FROM employees;
SELECT AVG(salary) INTO avg_salary FROM employees;
-- Using Variables
SELECT total, avg_salary;
END //
DELIMITER ;
5. Controle de processos
▶ Exemplo: Instrução IF
DELIMITER //
CREATE PROCEDURE sp_check_salary(IN emp_id INT)
BEGIN
DECLARE emp_salary DECIMAL(10,2);
SELECT salary INTO emp_salary FROM employees WHERE id = emp_id;
IF emp_salary > 10000 THEN
SELECT 'High salary' AS level;
ELSEIF emp_salary > 5000 THEN
SELECT 'Medium salary' AS level;
ELSE
SELECT 'Low salary' AS level;
END IF;
END //
DELIMITER ;
▶ Exemplo: Instrução CASE
DELIMITER //
CREATE PROCEDURE sp_order_status(IN order_id INT)
BEGIN
DECLARE order_status VARCHAR(20);
SELECT status INTO order_status FROM orders WHERE id = order_id;
CASE order_status
WHEN 'pending' THEN SELECT 'Order is pending' AS message;
WHEN 'paid' THEN SELECT 'Order is paid' AS message;
WHEN 'shipped' THEN SELECT 'Order is shipped' AS message;
ELSE SELECT 'Unknown status' AS message;
END CASE;
END //
DELIMITER ;
▶ Exemplo: Laço WHILE
DELIMITER //
CREATE PROCEDURE sp_sum_1_to_n(IN n INT, OUT total INT)
BEGIN
DECLARE i INT DEFAULT 1;
SET total = 0;
WHILE i <= n DO
SET total = total + i;
SET i = i + 1;
END WHILE;
END //
DELIMITER ;
-- Call
CALL sp_sum_1_to_n(100, @total);
SELECT @total; -- 5050
6. Cursor
▶ Exemplo: Iteração do cursor
DELIMITER //
CREATE PROCEDURE sp_list_users()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE user_name VARCHAR(50);
DECLARE user_email VARCHAR(100);
-- Declare cursor
DECLARE cur_users CURSOR FOR
SELECT username, email FROM users;
-- End of cursor handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- Open cursor
OPEN cur_users;
-- Iterate
read_loop: LOOP
FETCH cur_users INTO user_name, user_email;
IF done THEN
LEAVE read_loop;
END IF;
SELECT user_name, user_email;
END LOOP;
-- Close cursor
CLOSE cur_users;
END //
DELIMITER ;
7. Funções armazenadas
▶ Exemplo: Criando uma função
DELIMITER //
CREATE FUNCTION fn_calc_bonus(salary DECIMAL(10,2))
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGIN
DECLARE bonus DECIMAL(10,2);
IF salary > 10000 THEN
SET bonus = salary * 0.2;
ELSEIF salary > 5000 THEN
SET bonus = salary * 0.1;
ELSE
SET bonus = salary * 0.05;
END IF;
RETURN bonus;
END //
DELIMITER ;
-- Using Functions
SELECT name, salary, fn_calc_bonus(salary) AS bonus FROM employees;
8. Gerenciamento de procedimentos armazenados
▶ Exemplo: Visualização e exclusão
-- View All Stored Procedures
SHOW PROCEDURE STATUS WHERE Db = 'mydb';
-- View the CREATE statement
SHOW CREATE PROCEDURE sp_get_user;
-- Delete a Stored Procedure
DROP PROCEDURE IF EXISTS sp_get_user;
-- Delete Function
DROP FUNCTION IF EXISTS fn_calc_bonus;
❓ Perguntas Frequentes
P: Qual é a diferença entre um procedimento armazenado e uma função? R: Um procedimento armazenado é chamado por meio da instrução CALL e não retorna um valor; uma função é chamada por meio da instrução SELECT e deve retornar um valor.
P: O que é DELIMITER? R: É o delimitador de instrução. Como o procedimento armazenado contém
;, ele precisa ser substituído por//para evitar que a instrução termine prematuramente.
P: Os procedimentos armazenados podem melhorar o desempenho? R: Os procedimentos armazenados são pré-compilados, o que reduz o tráfego de rede. No entanto, o otimizador moderno do MySQL já é bastante bom, portanto, o ganho de desempenho é limitado.
P: Qual é a diferença entre um procedimento armazenado e uma função? R: Um procedimento é chamado por meio da instrução CALL e pode ter parâmetros OUT sem retornar um valor, enquanto uma função usada em uma instrução SELECT deve RETURNAR um valor.
P: Os procedimentos armazenados podem ser vulneráveis à injeção de SQL? R: O uso de PREPARE combinado com CONCAT para construir instruções SQL pode levar à injeção; passar parâmetros diretamente é seguro.
📖 Resumo
- Os procedimentos armazenados são criados usando
CREATE PROCEDUREe chamados usandoCALL - Tipo de parâmetro: IN (Entrada), OUT (Saída), INOUT (Bidirecional)
- DECLARE declara uma variável; SET atribui um valor
- Controle de fluxo: IF/CASE/WHILE/LOOP
- Cursores são usados para percorrer o conjunto de resultados, linha por linha
- Funções armazenadas devem retornar um valor
📝 Exercícios
-
Questão básica (Dificuldade: ⭐): Crie um procedimento armazenado que receba um ID de usuário como entrada e retorne as informações do usuário.
-
Problema avançado (Dificuldade ⭐⭐): Crie um procedimento armazenado com uma instrução IF que retorne uma nota com base na pontuação.
-
Problema de desafio (Dificuldade: ⭐⭐⭐): Use um cursor para percorrer a tabela de usuários, calcular e atualizar os pontos de cada usuário.