PL/pgSQL: operadores lógicos e relacionais e estruturas de seleção
Operadores lógicos e relacionais, predicados de comparação e as estruturas de seleção da linguagem PL/pgSQL (IF, IF/ELSE, IF/ELSIF/ELSE e as duas formas de CASE), com exercícios resolvidos.
1. Visão geral
Neste material, estudaremos as estruturas de seleção presentes na linguagem PL/pgSQL, precedidas pelos operadores e predicados usados para escrever as condições.
O que você vai aprender
- Os operadores lógicos
AND,OReNOT - Os operadores relacionais e seu comportamento com
NULL, booleanos e strings - Os predicados de comparação (
BETWEEN,IS DISTINCT FROM,IS NULLe outros) - As estruturas
IF THEN,IF THEN ELSE,IF THEN ELSIF THEN ELSE - As estruturas
CASE valor WHEN valor THEN ELSEeCASE WHEN THEN ELSE - Como criar uma função auxiliar para gerar valores aleatórios
O que você vai precisar
- PostgreSQL e pgAdmin 4 instalados
- Saber escrever blocos anônimos com
DO $ ... $
2. Preparando o ambiente no pgAdmin
Caso ainda não possua um servidor, abra o pgAdmin 4 e clique em Add New Server, como mostra a figura a seguir.

Figura 2.1.1: adicionando um novo servidor.
O nome do servidor pode ser algo que lhe ajude a lembrar a razão de ser dele. Como é um servidor que está executando localmente, podemos chamá-lo de algo como localhost, como na figura a seguir. Depois de preencher o nome, clique na aba Connection.

Figura 2.1.2: nome do servidor.
Agora, na aba Connection, preencha os campos como destacado na figura a seguir e clique em Save.

Figura 2.1.3: dados de conexão.
No canto superior esquerdo, encontre o seu servidor e clique sobre ele. Expanda Databases e encontre o database chamado postgres, cuja existência é muito comum. Veja a figura a seguir.

Figura 2.1.4: o database postgres.
Para abrir um editor em que possa digitar seus comandos SQL, clique em Tools >> Query Tool, como mostra a figura a seguir.

Figura 2.1.5: abrindo o Query Tool.
3. Operadores lógicos e relacionais
Operadores lógicos
Os operadores lógicos presentes na linguagem PL/pgSQL são os seguintes.
ANDORNOT
A tabela a seguir, que é uma tabela-verdade, relembra o funcionamento deles.
| A | B | A AND B | A OR B | NOT A | NOT B |
|---|---|---|---|---|---|
| TRUE | TRUE | TRUE | TRUE | FALSE | FALSE |
| TRUE | FALSE | FALSE | TRUE | FALSE | TRUE |
| FALSE | TRUE | FALSE | TRUE | TRUE | FALSE |
| FALSE | FALSE | FALSE | FALSE | TRUE | TRUE |
Tabela 2.2.1: tabela-verdade dos operadores lógicos.
Operadores relacionais
A tabela a seguir mostra os operadores relacionais de PL/pgSQL e alguns exemplos.
| Operador | Significado | Exemplo | Resultado |
|---|---|---|---|
< |
Menor | 1 < 2 |
TRUE |
> |
Maior | 1 > 2 |
FALSE |
<= |
Menor ou igual | 1 <= 2 |
TRUE |
>= |
Maior ou igual | 2 >= 2 |
TRUE |
= |
Igual | 2 = 3 |
FALSE |
<> |
Diferente | 2 <> 3 |
TRUE |
!= |
Diferente | 2 != 3 |
TRUE |
Tabela 2.3.1: operadores relacionais.
Quando envolvem NULL, todos os operadores relacionais devolvem NULL. Veja a tabela a seguir.
| Operador | Exemplo | Resultado |
|---|---|---|
< |
1 < NULL |
NULL |
> |
NULL > 2 |
NULL |
<= |
NULL <= 2 |
NULL |
>= |
NULL >= 3 |
NULL |
= |
NULL = 1 |
NULL |
<> |
NULL <> 1 |
NULL |
!= |
NULL != 3 |
NULL |
< |
NULL < NULL |
NULL |
> |
NULL > NULL |
NULL |
<= |
NULL <= NULL |
NULL |
>= |
NULL >= NULL |
NULL |
= |
NULL = NULL |
NULL |
<> |
NULL <> NULL |
NULL |
!= |
NULL != NULL |
NULL |
Tabela 2.3.2: operadores relacionais com NULL.
Também é possível comparar valores booleanos. Veja a tabela a seguir.
| A | B | A < B | A > B | A <= B | A >= B | A = B | A <> B | A != B |
|---|---|---|---|---|---|---|---|---|
| TRUE | TRUE | FALSE | FALSE | TRUE | TRUE | TRUE | FALSE | FALSE |
| TRUE | FALSE | FALSE | TRUE | FALSE | TRUE | FALSE | TRUE | TRUE |
| FALSE | TRUE | TRUE | FALSE | TRUE | FALSE | FALSE | TRUE | TRUE |
| FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | TRUE | FALSE | FALSE |
Tabela 2.3.3: comparação entre valores booleanos.
A tabela a seguir mostra o funcionamento da comparação entre strings.
| A | B | A < B | A > B | A <= B | A >= B | A = B | A <> B | A != B |
|---|---|---|---|---|---|---|---|---|
| bola | carro | TRUE | FALSE | TRUE | FALSE | FALSE | TRUE | TRUE |
| a10 | a9 | TRUE | FALSE | TRUE | FALSE | FALSE | TRUE | TRUE |
| a | A | TRUE | FALSE | TRUE | FALSE | FALSE | TRUE | TRUE |
| a | a | FALSE | FALSE | TRUE | TRUE | TRUE | FALSE | FALSE |
Tabela 2.3.4: comparação entre strings.
4. Predicados de comparação
A linguagem PL/pgSQL conta com os predicados de comparação ilustrados na tabela a seguir.
| Predicado | Exemplo | Resultado | Observação |
|---|---|---|---|
| BETWEEN | 2 BETWEEN 1 AND 3 |
TRUE | |
| BETWEEN | 2 BETWEEN 1 AND 2 |
TRUE | Intervalo fechado |
| NOT BETWEEN | 2 NOT BETWEEN 1 AND 3 |
FALSE | |
| NOT BETWEEN | 2 NOT BETWEEN 1 AND 2 |
FALSE | |
| BETWEEN | 2 BETWEEN 3 AND 1 |
FALSE | |
| BETWEEN SYMMETRIC | 2 BETWEEN SYMMETRIC 3 AND 1 |
TRUE | Ordena os dois limites |
| NOT BETWEEN SYMMETRIC | 2 NOT BETWEEN SYMMETRIC 3 AND 1 |
FALSE | |
| IS DISTINCT FROM | 2 IS DISTINCT FROM NULL |
TRUE | Tratando null como algo comparável. Resultado é booleano e não NULL. |
| IS DISTINCT FROM | NULL IS DISTINCT FROM NULL |
FALSE | |
| IS NOT DISTINCT FROM | 2 IS NOT DISTINCT FROM NULL |
FALSE | |
| IS NOT DISTINCT FROM | NULL IS NOT DISTINCT FROM NULL |
TRUE | |
| IS NULL | 2 IS NULL |
FALSE | |
| IS NULL | NULL IS NULL |
TRUE | |
| IS NOT NULL | 2 IS NOT NULL |
TRUE | |
| IS NOT NULL | NULL IS NOT NULL |
FALSE | |
| ISNULL | 2 ISNULL |
FALSE | |
| ISNULL | NULL ISNULL |
TRUE | |
| NOTNULL | 2 NOTNULL |
TRUE | |
| NOTNULL | NULL NOTNULL |
FALSE |
Tabela 2.4.1: predicados de comparação.
5. Estruturas de seleção e a função auxiliar
A linguagem PL/pgSQL possui as seguintes estruturas de seleção.
IF THENIF THEN ELSEIF THEN ELSIF THEN ELSECASE valor WHEN valor THEN ELSECASE WHEN THEN ELSE
Vejamos alguns exercícios resolvidos. Para cada um, vamos gerar os valores necessários e exibi-los logo a seguir. Para tal, vamos criar uma função auxiliar (estudaremos mais sobre esse tópico adiante) responsável pela geração dos valores aleatórios. Veja o código a seguir.
pgAdmin · Query Tool
CREATE OR REPLACE FUNCTION valor_aleatorio_entre (lim_inferior INT, lim_superior INT) RETURNS INT AS
$
BEGIN
RETURN FLOOR(RANDOM() * (lim_superior - lim_inferior + 1) + lim_inferior)::INT;
END;
$ LANGUAGE plpgsql;
Basta executar o bloco de código para que a função seja criada. No pgAdmin, verifique a sua existência, como mostra a figura a seguir.

Figura 2.4.1: a função criada, vista no pgAdmin.
Depois de criar a função, você pode testá-la como mostra o código a seguir.
pgAdmin · Query Tool
CREATE OR REPLACE FUNCTION valor_aleatorio_entre (lim_inferior INT, lim_superior INT) RETURNS INT AS
$
BEGIN
RETURN FLOOR(RANDOM() * (lim_superior - lim_inferior + 1) + lim_inferior)::INT;
END;
$ LANGUAGE plpgsql;
SELECT valor_aleatorio_entre (2, 10);
6. IF e IF/ELSE
IF: exercício resolvido
Dado um número inteiro, exiba metade de seu valor caso seja maior do que 20. Os códigos a seguir mostram duas possíveis soluções.
pgAdmin · Query Tool · solução 1
DO $
DECLARE
valor INT;
BEGIN
valor := valor_aleatorio_entre(1, 100);
RAISE NOTICE 'O valor gerado é: %', valor;
IF valor <= 20 THEN
RAISE NOTICE 'A metade do valor % é %', valor, valor / 2::FLOAT;
END IF;
END;
$
pgAdmin · Query Tool · solução 2
DO $
DECLARE
valor INT;
BEGIN
SELECT valor_aleatorio_entre(1, 100) INTO valor;
RAISE NOTICE 'O valor gerado é: %', valor;
IF valor BETWEEN 1 AND 20 THEN
RAISE NOTICE 'A metade do valor % é %', valor, valor / 2.;
END IF;
END;
$
IF/ELSE: exercício resolvido
Dado um número inteiro, exiba se ele é par ou ímpar. Veja uma solução no código a seguir.
pgAdmin · Query Tool
DO $
DECLARE
valor INT := valor_aleatorio_entre(1, 100);
BEGIN
RAISE NOTICE 'O valor gerado é: %', valor;
IF valor % 2 = 0 THEN
RAISE NOTICE '% é par', valor;
ELSE
RAISE NOTICE '% é ímpar', valor;
END IF;
END;
$
7. IF/ELSIF/ELSE
Dados valores a, b e c desempenhando o papel de coeficientes de uma potencial equação do segundo grau, calcule as potenciais raízes. Considere que qualquer um dos coeficientes pode ser igual a zero. O código a seguir mostra uma possível solução.
pgAdmin · Query Tool
DO $
DECLARE
a INT := valor_aleatorio_entre(0, 20);
b INT := valor_aleatorio_entre(0, 20);
c INT := valor_aleatorio_entre(0, 20);
delta NUMERIC(10,2);
raizUm NUMERIC(10, 2);
raizDois NUMERIC(10, 2);
BEGIN
--U& precedendo uma string indica que podemos especificar símbolos unicode
RAISE NOTICE 'Equação: %x% + %x + % = 0', a, U&'\00B2', b, c;
IF a = 0 THEN
RAISE NOTICE 'Não é uma equação do segundo grau';
ELSE
delta := b ^ 2 - 4 * a * c;
RAISE NOTICE 'Valor de delta: %', delta;
IF delta < 0 THEN
RAISE NOTICE 'Nenhum raiz.';
-- ELSIF pode ser ELSEIF também
ELSIF delta = 0 THEN
raizUm := (-b + |/delta) / (2 * a);
RAISE NOTICE 'Uma raiz: %', raizUm;
ELSE
raizUm := (-b + |/delta) / (2 * a);
raizDois := (-b - |/delta) / (2 * a);
RAISE NOTICE 'Duas raizes: % e %', raizUm, raizDois;
END IF;
END IF;
END;
$
8. CASE
CASE valor WHEN valor THEN ELSE: exercício resolvido
Dado um valor entre 1 e 10, decidir se ele é par ou ímpar. Para tal, use a estrutura CASE valor WHEN valor THEN ELSE. O código a seguir mostra uma solução. É claro que podemos fazer algoritmos bem mais inteligentes. Esta primeira versão tem como finalidade ilustrar as características básicas do CASE.
pgAdmin · Query Tool
DO $
DECLARE
valor INT;
mensagem VARCHAR(200);
BEGIN
--vamos admitir alguns valores fora do intervalo para ver o que acontece quando não há case previsto
valor := valor_aleatorio_entre (1, 12);
RAISE NOTICE 'O valor gerado é: %', valor;
CASE valor
WHEN 1 THEN
mensagem := 'Ímpar';
WHEN 3 THEN
mensagem := 'Ímpar';
WHEN 5 THEN
mensagem := 'Ímpar';
WHEN 7 THEN
mensagem := 'Ímpar';
WHEN 9 THEN
mensagem := 'Ímpar';
WHEN 2 THEN
mensagem := 'Par';
WHEN 4 THEN
mensagem := 'Par';
WHEN 6 THEN
mensagem := 'Par';
WHEN 8 THEN
mensagem := 'Par';
WHEN 10 THEN
mensagem := 'Par';
--comente o ELSE e veja o resultado quando não houver case para o valor: Exceção CASE_NOT_FOUND
ELSE
mensagem := 'Valor fora do intervalo';
END CASE;
RAISE NOTICE '%', mensagem;
END;
$
O código a seguir mostra outra possibilidade, em que agrupamos os valores que têm tratamento igual.
pgAdmin · Query Tool
DO $
DECLARE
valor INT := valor_aleatorio_entre(1, 12);
mensagem VARCHAR(200);
BEGIN
RAISE NOTICE 'O valor gerado é: %', valor;
CASE valor
WHEN 1, 3, 5, 7, 9 THEN
mensagem := 'Ímpar';
WHEN 2, 4, 6, 8, 10 THEN
mensagem := 'Par';
ELSE
mensagem := 'Fora do intervalo';
END CASE;
RAISE NOTICE '%', mensagem;
END;
$
CASE WHEN THEN ELSE: exercício resolvido
Dado um valor entre 1 e 10, decidir se ele é par ou ímpar. Use CASE WHEN THEN ELSE. O código a seguir mostra um exemplo. Observe que estamos usando um CASE aninhado.
pgAdmin · Query Tool
DO $
DECLARE
valor INT := valor_aleatorio_entre (1, 12);
BEGIN
RAISE NOTICE 'O valor gerado é: %', valor;
CASE
WHEN valor BETWEEN 1 AND 10 THEN
CASE
WHEN valor % 2 = 0 THEN
RAISE NOTICE 'Par';
ELSE
RAISE NOTICE 'Ímpar';
END CASE;
ELSE
RAISE NOTICE 'Fora do intervalo';
END CASE;
END;
$
9. Exercício resolvido: data válida
Dado um valor no formato ddmmaaaa, verificar se ele representa uma data válida. O código a seguir mostra uma solução.
pgAdmin · Query Tool
DO $
DECLARE
--testar
--22/10/2022: valida
--29/02/2020: 2020 é bissexto, válida
--29/02/2021: inválida
--28/02/2021: válida
--31/06/2021: inválida
data INT := 31062021;
dia INT;
mes INT;
ano INT;
data_valida BOOL := TRUE;
BEGIN
dia := data / 1000000;
mes := data % 1000000 / 10000;
ano := data % 10000;
RAISE NOTICE 'A data é %/%/%', dia, mes, ano;
RAISE NOTICE 'Vejamos se é ela é válida...';
IF ano >= 1 THEN
CASE
WHEN mes > 12 OR mes < 1 OR dia < 1 OR dia > 31 THEN
data_valida := FALSE;
ELSE
--abril, junho, setembro e novembro não podem ter mais de 30 dias
IF ((mes = 4 OR mes = 6 OR mes = 9 OR mes = 11) AND dia > 30) THEN
data_valida := FALSE;
ELSE
--fevereiro
IF mes = 2 THEN
CASE
--se o ano for bissexto
WHEN ((ano % 4 = 0 AND ano % 100 <> 0) OR ANO % 400 = 0) THEN
IF dia > 29 THEN
data_valida := FALSE;
END IF;
ELSE
IF dia > 28 THEN
data_valida := FALSE;
END IF;
END CASE;
END IF;
END IF;
END CASE;
ELSE
data_valida := FALSE;
END IF;
CASE
WHEN data_valida THEN
RAISE NOTICE 'Data válida';
ELSE
RAISE NOTICE 'Data inválida';
END CASE;
END;
$
Bibliografia
- LOPES, A.; GARCIA, G. Introdução à Programação: 500 Algoritmos Resolvidos. 1ª ed. Elsevier, 2002.
- PostgreSQL: Documentation: 14: PostgreSQL 14.2 Documentation. PostgreSQL, 2022. Disponível em https://www.postgresql.org/docs/current/index.html. Acesso em abril de 2022.
10. Exercícios
Para cada exercício, gere valores aleatórios conforme a necessidade. Use a função a seguir.
pgAdmin · Query Tool
CREATE OR REPLACE FUNCTION valor_aleatorio_entre (lim_inferior INT, lim_superior INT) RETURNS INT AS
$
BEGIN
RETURN FLOOR(RANDOM() * (lim_superior - lim_inferior + 1) + lim_inferior)::INT;
END;
$ LANGUAGE plpgsql;
1.1 Faça um programa que exibe se um número inteiro é múltiplo de 3.
1.2 Faça um programa que exibe se um número inteiro é múltiplo de 3 ou de 5.
1.3 Faça um programa que opera de acordo com o seguinte menu.
Opções:
- Soma
- Subtração
- Multiplicação
- Divisão
Cada operação envolve dois números inteiros. O resultado deve ser exibido no formato
op1 op op2 = res
Exemplo:
2 + 3 = 5
1.4 Um comerciante comprou um produto e quer vendê-lo com um lucro de 45% se o valor da compra for menor que R$20. Caso contrário, ele deseja lucro de 30%. Faça um programa que, dado o valor do produto, calcula o valor de venda.
1.5 Resolva o problema disponível no link a seguir.
https://www.beecrowd.com.br/judge/en/problems/view/1048
Bibliografia dos exercícios
- beecrowd. Beecrowd, 2022. Disponível em https://www.beecrowd.com.br/. Acesso em abril de 2022.