CodeGym /Cursos /SQL SELF /Operadores RAISE NOTICE, RETURN QUERY

Operadores RAISE NOTICE, RETURN QUERY

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

No mundo da programação, tem duas paradas que são essenciais: entender o que tá rolando (principalmente quando tudo dá ruim) e devolver dados úteis. Isso é ainda mais importante no PL/pgSQL, porque tudo acontece no servidor, então debugar não é tão simples assim. Pra te ajudar, tem umas ferramentas nativas:

RAISE NOTICE — é o jeito de mostrar mensagens enquanto a função roda. Imagina ele como um console.log no JavaScript ou print no Python. Dá pra mostrar valores de variáveis, o estado atual da execução ou só deixar um "oi" pro seu eu do futuro.

RETURN QUERY — é o jeito de devolver um conjunto de dados, tipo uma tabela inteira ou o resultado de uma query mais complexa. Com isso, funções PL/pgSQL ficam parecidas com queries SQL normais.

Comando RAISE NOTICE

RAISE NOTICE deixa você mostrar mensagens na tela enquanto a função tá rodando. O formato é assim:

RAISE NOTICE 'Mensagem: %', valor;
  • % — é um placeholder pra variável, igualzinho ao printf em C.
  • Depois do texto da mensagem, você pode listar as variáveis que quer mostrar.

Exemplo de uso

Imagina que você tá escrevendo uma função pra contar quantos estudantes tem em cada grupo. Você quer ver os valores intermediários pra sacar se tá tudo certo.

CREATE OR REPLACE FUNCTION count_students_in_groups() RETURNS VOID AS $$
DECLARE
    group_name TEXT;
    student_count INT;
BEGIN
    FOR group_name IN SELECT DISTINCT group_name FROM students LOOP
        SELECT COUNT(*) INTO student_count
        FROM students WHERE group_name = group_name;

        -- Mostrando os resultados
        RAISE NOTICE 'Grupo: %, Quantidade de estudantes: %', group_name, student_count;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

Quando você rodar essa função:

SELECT count_students_in_groups();

Você vai ver mensagens assim nos logs:

NOTICE:  Grupo: Matemática, Quantidade de estudantes: 30
NOTICE:  Grupo: Filosofia, Quantidade de estudantes: 25
NOTICE:  Grupo: Biologia, Quantidade de estudantes: 18

Repara que a função não retorna nada (ela é criada com RETURNS VOID), mas o RAISE NOTICE mostra como o loop tá indo.

Dicas maneiras com RAISE

Além do NOTICE, dá pra usar outros níveis de mensagem:

  • RAISE DEBUG — pra infos extras (só aparece se o nível de log estiver em DEBUG).
  • RAISE INFO — pra infos gerais.
  • RAISE WARNING — pra avisos.
  • RAISE EXCEPTION — pra gerar erros, que a gente vai ver depois.

Pra debugar, o melhor é usar NOTICE ou DEBUG, porque eles não travam a função.

Comando RETURN QUERY: devolva dados como um ninja

RETURN QUERY é usado no PL/pgSQL pra devolver um conjunto de linhas. Com ele, dá pra retornar o resultado de uma query SQL direto da função. O jeito de usar é assim:

RETURN QUERY <SQL-query>;

Dá até pra juntar várias queries:

RETURN QUERY <SQL-query 1>;
RETURN QUERY <SQL-query 2>;

Exemplo 1: função com RETURN QUERY

Bora criar uma função que retorna a lista de estudantes de um grupo específico.

CREATE OR REPLACE FUNCTION get_students_by_group(group_name TEXT)
RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
    RETURN QUERY
    SELECT id, name 
    FROM students
    WHERE group_name = group_name;
END;
$$ LANGUAGE plpgsql;

Agora chama essa função:

SELECT * FROM get_students_by_group('Matemática');

Pra testar a função, primeiro cria a tabela students e coloca uns dados nela:

CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
group_name TEXT NOT NULL
);

INSERT INTO students (name, group_name) VALUES
('Otto Song',     'Física'),
('Alex Lin',      'Matemática'),
('Anna Vel',      'Matemática'),
('Maria Chi',     'História');

Resultado:

id name
2 Alex Lin
3 Anna Vel

Viu? A função funciona igual uma query SQL normal.

Exemplo 2: Juntando várias queries

E se a gente quiser devolver dados combinados de várias tabelas? Bora retornar a lista de estudantes e os cursos em que eles tão matriculados.

CREATE OR REPLACE FUNCTION get_students_and_courses()
RETURNS TABLE(student_name TEXT, course_name TEXT) AS $$
BEGIN
    RETURN QUERY
    SELECT s.name, c.name
    FROM students s
    JOIN enrollments e ON s.id = e.student_id
    JOIN courses c ON e.course_id = c.id;
END;
$$ LANGUAGE plpgsql;

Primeiro, cria três tabelas: students, courses e enrollments, e coloca uns dados:

-- Tabela de estudantes
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);

-- Tabela de cursos
CREATE TABLE courses (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);

-- Tabela de matrículas (ligação)
CREATE TABLE enrollments (
student_id INT REFERENCES students(id),
course_id INT REFERENCES courses(id)
);

-- Adiciona estudantes
INSERT INTO students (name) VALUES
('Otto Song'),
('Alex Lin'),
('Anna Vel'),
('Maria Chi');

-- Adiciona cursos
INSERT INTO courses (name) VALUES
('Matemática'),
('Física'),
('História');

-- Adiciona matrículas
INSERT INTO enrollments (student_id, course_id) VALUES
(1, 2), -- Otto -> Física
(2, 1), -- Alex -> Matemática
(3, 1), -- Anna -> Matemática
(4, 3); -- Maria -> História

Nesse caso, rodar a função:

SELECT * FROM get_students_and_courses();

vai dar esse resultado:

student_name course_name
Otto Song Física
Alex Lin Matemática
Anna Vel Matemática
Maria Chi História

A função junta direitinho os dados das três tabelas e mostra quem tá em qual curso.

Juntando RAISE NOTICE e RETURN QUERY

Às vezes, RETURN QUERY e RAISE NOTICE podem trabalhar juntos na mesma função, assim você controla a execução e vê os resultados intermediários.

Olha esse exemplo de função que retorna dados dos estudantes e ainda mostra mensagens pra acompanhar o que tá rolando:

CREATE OR REPLACE FUNCTION debug_students()
RETURNS TABLE(student_id INT, student_name TEXT) AS $$
DECLARE
    count_students INT;
BEGIN
    -- Conta quantos estudantes tem
    SELECT COUNT(*) INTO count_students FROM students;
    RAISE NOTICE 'Total de estudantes: %', count_students;

    -- Retorna os dados dos estudantes
    RETURN QUERY
    SELECT id, name FROM students;

    RAISE NOTICE 'Função terminou de rodar.';
END;
$$ LANGUAGE plpgsql;

Se a tabela students ainda não existir, cria ela e coloca uns dados:

CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);

INSERT INTO students (name) VALUES
('Otto Song'),
('Alex Lin'),
('Anna Vel'),
('Maria Chi');

Agora, rodando a função:

SELECT * FROM debug_students();

Você vai ver tanto os dados quanto as mensagens:

student_id student_name
1 Otto Song
2 Alex Lin
3 Anna Vel
4 Maria Chi

Mensagem no console:

NOTICE:  Total de estudantes: 4
NOTICE:  Função terminou de rodar.

Erros comuns ao usar

Erro com variáveis no RAISE NOTICE: se você esquecer de declarar uma variável ou errar o nome dela, vai rolar um erro variable does not exist. Sempre confere se as variáveis tão declaradas certinho.

Erro com tipo de retorno: se você usar RETURN QUERY mas não colocar RETURNS TABLE na criação da função, o PostgreSQL vai reclamar. Garante que os tipos de retorno batem com os dados que você tá devolvendo.

Erro com placeholders no RAISE: se o número de % não bater com o número de variáveis, vai dar erro. Tipo assim:

RAISE NOTICE 'Valor: %, %', valor1;

Isso vai dar erro porque faltou a segunda variável.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION