No PostgreSQL, funções são uma ferramenta poderosa pra automatizar tarefas, criar lógica de negócio e deixar o servidor mais inteligente. Imagina funções como mini-programas que rodam dentro do banco de dados. Elas são úteis pra:
- Reutilizar código. Se você repete as mesmas queries várias vezes, coloca elas numa função e chama quando precisar.
- Automatizar tarefas. Por exemplo, se você precisa calcular o salário dos funcionários baseado nas horas trabalhadas. Uma função resolve isso de boa.
- Encapsular lógica. Dá pra deixar cálculos complicados do lado do servidor, assim os clientes não precisam quebrar a cabeça com SQL.
Sintaxe geral do CREATE FUNCTION
Olha só como é a estrutura básica pra criar uma função:
CREATE FUNCTION function_name(parameters) RETURNS return_type AS $$
BEGIN
-- Corpo da função (lógica)
RETURN resultado;
END;
$$ LANGUAGE plpgsql;
Vamos entender as partes principais:
CREATE FUNCTION function_name(parameters):
Nessa linha a gente define o nome da função function_name e coloca os parâmetros (se precisar).
Os parâmetros podem ter nome e tipo de dado: my_param INTEGER, another_param TEXT.
RETURNS return_type:
Aqui você diz o que a função vai retornar: um valor só (INTEGER, TEXT etc.) ou um conjunto de dados (TABLE, RECORD).
BEGIN ... END:
Entre essas palavras-chave fica o "corpo" da função, onde rola toda a mágica.
RETURN resultado:
Retorna o resultado da função. Fica ligado: o tipo do resultado tem que ser igual ao que você colocou no RETURNS.
LANGUAGE plpgsql:
Aqui você fala que vai usar a linguagem PL/pgSQL. O PostgreSQL aceita outras linguagens, mas agora a gente vai usar essa mesmo.
Exemplo simples: somando dois números
Bora criar uma função que retorna a soma de dois números inteiros.
CREATE FUNCTION add_numbers(a INT, b INT) RETURNS INT AS $$
BEGIN
RETURN a + b;
END;
$$ LANGUAGE plpgsql;
Agora vamos chamar ela:
SELECT add_numbers(5, 7); -- Resultado: 12
O que tá rolando aqui?
- A função recebe dois parâmetros
aebdo tipoINT. - Dentro da função a gente só soma eles (
a + b) e retorna o resultado. - Simples, tipo uma calculadora!
Exemplo usando variáveis
Imagina que temos um banco de dados da faculdade e queremos saber quantos estudantes estão cadastrados.
Vamos criar a função:
CREATE FUNCTION count_students() RETURNS INT AS $$
DECLARE
total INT; -- Declarando variável pra guardar o resultado
BEGIN
SELECT COUNT(*) INTO total FROM students; -- Conta as linhas da tabela
RETURN total; -- Retorna o resultado
END;
$$ LANGUAGE plpgsql;
Chamando a função:
SELECT count_students(); -- Supondo que o resultado seja: 120
Aqui a gente vê:
- Uso da variável
totalpra guardar o resultado da query SQL. - O comando
SELECT ... INTOjoga o resultado da query na variável.
Esse jeito é massa quando você precisa processar os dados antes de retornar.
Retornando vários valores: RETURNS TABLE
No exemplo anterior a gente retornou só um valor. Mas e se a função precisar devolver um conjunto de dados, tipo uma lista de estudantes? É aí que o RETURNS TABLE brilha.
Exemplo:
CREATE FUNCTION get_students() RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
RETURN QUERY SELECT id, name FROM students;
END;
$$ LANGUAGE plpgsql;
Chamando a função:
SELECT * FROM get_students();
Possível resultado:
| id | name |
|---|---|
| 1 | Alice |
| 2 | Bob |
| 3 | Charlie |
Por que usar RETURN QUERY pra rodar queries dentro da função
RETURN QUERY deixa a gente retornar o resultado de uma query SQL direto da função. Isso corta etapas e deixa tudo mais simples.
Vamos criar uma função que retorna só os estudantes que estão ativos:
CREATE FUNCTION get_active_students() RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
RETURN QUERY SELECT id, name FROM students WHERE active = TRUE;
END;
$$ LANGUAGE plpgsql;
Antes de chamar a função get_active_students(), você precisa criar a tabela students e colocar uns dados de teste. Olha só como faz:
-- Criando a tabela de estudantes
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
active BOOLEAN DEFAULT TRUE
);
-- Inserindo alguns registros
INSERT INTO students (name, active) VALUES
('Alice', FALSE),
('Bob', TRUE),
('Charlie', TRUE),
('Dana', FALSE);
Tabela:
| id | name | active |
|---|---|---|
| 1 | Alice | false |
| 2 | Bob | true |
| 3 | Charlie | true |
| 4 | Dana | false |
Agora chama assim:
SELECT * FROM get_active_students();
Resultado:
| id | name |
|---|---|
| 2 | Bob |
| 3 | Charlie |
Checando se os dados estão certos antes de rodar
Funções podem ter checagens com IF pra garantir que os dados estão ok. Por exemplo, dá pra criar uma função pra passar o estudante pro próximo curso só se ele tiver passado em todas as provas.
Exemplo:
CREATE FUNCTION promote_student(student_id INT) RETURNS TEXT AS $$
DECLARE
passed_exams INT;
BEGIN
-- Conta quantas provas o estudante passou
SELECT COUNT(*) INTO passed_exams
FROM exams
WHERE student_id = promote_student.student_id AND status = 'passed';
-- Checa a condição
IF passed_exams < 5 THEN
RETURN 'O estudante não passou em provas suficientes';
END IF;
-- Atualiza o curso do estudante
UPDATE students
SET course = course + 1
WHERE id = promote_student.student_id;
RETURN 'Estudante promovido!';
END;
$$ LANGUAGE plpgsql;
Erros comuns ao criar funções
Faltou o tipo de retorno. O PostgreSQL sempre exige que você diga qual tipo de resultado a função vai retornar. Por exemplo:
CREATE FUNCTION fail() AS $$ -- Erro: faltou RETURNS
BEGIN
RETURN 1;
END;
$$ LANGUAGE plpgsql;
Como corrigir:
CREATE FUNCTION succeed() RETURNS INT AS $$
BEGIN
RETURN 1;
END;
$$ LANGUAGE plpgsql;
Tipo de retorno errado. Se você coloca RETURNS INT, tem que retornar um número. Tentar retornar uma string aqui é furada.
Erro nas queries SQL dentro da função. Sempre testa as queries antes de usar na função. Melhor testar "na mão" pelo psql ou pgAdmin.
GO TO FULL VERSION