Hoje vamos analisar os erros típicos na criação de funções, por que eles acontecem e como resolver. Porque é só na depuração que o verdadeiro mestre aprende sua arte — codar! Let's debug it!
Criar funções, principalmente quando você tá começando com PL/pgSQL, pode parecer complicado. Até os devs mais experientes em PostgreSQL tropeçam em umas armadilhas. Bora ver cada uma delas.
1. Esquecer a palavra-chave RETURNS
PL/pgSQL é bem rígido em como você define funções. Um dos erros mais comuns é esquecer de indicar o tipo de dado que a função vai retornar. Olha só:
-- Erro: faltou a palavra-chave RETURNS
CREATE FUNCTION incorrect_function() AS $$
BEGIN
RETURN 1;
END;
$$ LANGUAGE plpgsql;
O PostgreSQL não vai entender o que essa função deveria retornar. RETURNS é obrigatório e diz qual o tipo de dado que volta (tipo RETURNS INT, RETURNS TEXT ou até RETURNS VOID).
Como corrigir: adiciona a palavra-chave RETURNS com o tipo de dado:
CREATE FUNCTION correct_function() RETURNS INT AS $$
BEGIN
RETURN 1;
END;
$$ LANGUAGE plpgsql;
2. Tentar retornar resultado sem RETURN
Quem tá começando costuma esquecer que, no PL/pgSQL, pra devolver um resultado, tem que usar explicitamente o comando RETURN. Tipo assim:
-- Erro: faltou RETURN
CREATE FUNCTION missing_return() RETURNS TEXT AS $$
BEGIN
'Hello, World!'; -- Só uma string, mas não retorna nada
END;
$$ LANGUAGE plpgsql;
Aqui a string 'Hello, World!' só tá ali, mas não é retornada. O PostgreSQL vê isso como resultado não alcançado e vai dar erro.
Como corrigir: coloca o comando RETURN:
CREATE FUNCTION fixed_return() RETURNS TEXT AS $$
BEGIN
RETURN 'Hello, World!';
END;
$$ LANGUAGE plpgsql;
3. Tentar usar variável não declarada
No PL/pgSQL, antes de usar uma variável, você tem que declarar ela no bloco DECLARE. Tipo assim:
-- Erro: variável my_var não foi declarada
CREATE FUNCTION missing_variable() RETURNS VOID AS $$
BEGIN
my_var := 'Hello, World!';
END;
$$ LANGUAGE plpgsql;
O PostgreSQL não sabe que existe a variável my_var, porque ela não foi declarada no bloco DECLARE.
Como corrigir: sempre declara as variáveis no DECLARE:
CREATE FUNCTION declared_variable() RETURNS VOID AS $$
DECLARE
my_var TEXT;
BEGIN
my_var := 'Hello, World!';
END;
$$ LANGUAGE plpgsql;
4. Usar tipo de retorno VOID errado
O tipo VOID diz que a função não retorna nada. Às vezes, a galera tenta usar RETURN em funções que são VOID, e isso dá ruim:
-- Erro: RETURN em função VOID
CREATE FUNCTION void_example() RETURNS VOID AS $$
BEGIN
RETURN 1; -- Não pode retornar valor
END;
$$ LANGUAGE plpgsql;
Funções com retorno VOID não devem retornar valores. Dá pra usar RETURN, mas sem valor nenhum.
Como corrigir: ou tira o RETURN, ou deixa ele sem valor:
CREATE FUNCTION correct_void() RETURNS VOID AS $$
BEGIN
-- Só faz as paradas
RAISE NOTICE 'Essa função não retorna nada';
RETURN; -- Finaliza a função
END;
$$ LANGUAGE plpgsql;
5. Usar RAISE errado pra debug
Debug em PL/pgSQL geralmente é feito com RAISE NOTICE. Mas se usar formato ou variável errado, vai dar erro.
Exemplo:
-- Erro: formato errado
CREATE FUNCTION debug_example() RETURNS VOID AS $$
BEGIN
RAISE NOTICE 'O valor é %'; -- Faltou variável
END;
$$ LANGUAGE plpgsql;
O comando RAISE espera que depois do % venha uma variável ou valor. Se deixar o % sozinho, o PostgreSQL não entende.
Como corrigir: garante que as variáveis ou valores estão certos:
CREATE FUNCTION fixed_debug() RETURNS VOID AS $$
DECLARE
my_var TEXT := 'PostgreSQL';
BEGIN
RAISE NOTICE 'O valor é %', my_var; -- Agora tem variável
END;
$$ LANGUAGE plpgsql;
6. Problemas com nomes de variáveis e colunas
Se o nome da variável for igual ao nome da coluna, pode dar resultado estranho. Tipo assim:
-- Erro: conflito de nomes entre variável e coluna
CREATE FUNCTION name_conflict() RETURNS TEXT AS $$
DECLARE
name TEXT;
BEGIN
SELECT name INTO name FROM students LIMIT 1; -- Qual name tá usando?
RETURN name;
END;
$$ LANGUAGE plpgsql;
PL/pgSQL dá preferência pra variável se o nome for igual ao da coluna.
Como corrigir: usa alias pra tabela ou evita nomes iguais.
CREATE FUNCTION fixed_conflict() RETURNS TEXT AS $$
DECLARE
student_name TEXT;
BEGIN
SELECT s.name INTO student_name FROM students s LIMIT 1;
RETURN student_name;
END;
$$ LANGUAGE plpgsql;
7. Executar queries erradas dentro de loop
Erros acontecem direto quando tenta rodar query SQL dentro de loop. Tipo assim:
-- Erro: query errada dentro do loop
CREATE FUNCTION cycle_error() RETURNS VOID AS $$
BEGIN
FOR rec IN SELECT * FROM students LOOP
EXECUTE 'UPDATE students SET active = TRUE WHERE id = ' || rec.id;
END LOOP;
END;
$$ LANGUAGE plpgsql;
SQL injection... Perigo! Concatenar string pra query SQL é má ideia. Isso pode abrir brecha de segurança.
Pra corrigir, usa parâmetros:
CREATE FUNCTION safe_cycle() RETURNS VOID AS $$
BEGIN
FOR rec IN SELECT * FROM students LOOP
EXECUTE 'UPDATE students SET active = TRUE WHERE id = $1' USING rec.id;
END LOOP;
END;
$$ LANGUAGE plpgsql;
8. Erros de tipos de dados
Exemplo de erro:
-- Erro: tipos de dados não batem
CREATE FUNCTION type_error() RETURNS INT AS $$
DECLARE
my_var TEXT := 'not_a_number';
BEGIN
RETURN my_var; -- Erro ao retornar texto em vez de INT
END;
$$ LANGUAGE plpgsql;
O PostgreSQL espera INT, mas recebe TEXT. Ele é bem rígido com tipos de dados.
Como corrigir? Garante que os tipos batem, ou faz cast explícito:
CREATE FUNCTION type_correct() RETURNS INT AS $$
DECLARE
my_var TEXT := '42';
BEGIN
RETURN my_var::INT; -- Converte texto pra número
END;
$$ LANGUAGE plpgsql;
Boas práticas e dicas
- Quebra funções grandes em menores. Fica mais fácil de debugar e testar.
- Usa comentários dentro das funções pra explicar operações complicadas.
- Sempre testa funções com poucos dados antes de rodar nas tabelas reais.
- Debuga usando
RAISE NOTICEpra entender o que tá rolando. - Evita SQL injection: usa parâmetros nas queries.
-- Usando RAISE pra debug
DO $$
DECLARE
total_students INT;
BEGIN
SELECT COUNT(*) INTO total_students FROM students;
RAISE NOTICE 'Total de estudantes: %', total_students; -- Mensagem de debug
END;
$$;
Essas dicas vão te poupar muita dor de cabeça e acabar de vez com as "pegadinhas" do PL/pgSQL!
GO TO FULL VERSION