CodeGym /Cursos /SQL SELF /Análise dos erros mais comuns na criação de funções

Análise dos erros mais comuns na criação de funções

SQL SELF
Nível 50, Lição 4
Disponível

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 NOTICE pra 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!

2
Tarefa
SQL SELF, nível 50, lição 4
Bloqueado
Depuração usando RAISE NOTICE
Depuração usando RAISE NOTICE
1
Pesquisa/teste
Criando funções simples, nível 50, lição 4
Indisponível
Criando funções simples
Criando funções simples
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION