Capa do Ebook gratuito Escriturário do Banco do Brasil - Agente de Tecnologia: Preparação para Concurso

Escriturário do Banco do Brasil - Agente de Tecnologia: Preparação para Concurso

Novo curso

16 páginas

Banco de Dados relacionais (SQL) para o Agente de Tecnologia do Banco do Brasil

Capítulo 5

Tempo estimado de leitura: 15 minutos

+ Exercício

1) Modelagem relacional na prática

Entidades, atributos e tabelas

No modelo relacional, uma entidade representa um “objeto” do domínio (por exemplo, Cliente, Conta, Cartão, Transação). Cada entidade vira uma tabela. Os atributos viram colunas (por exemplo, nome, cpf, saldo).

Boas práticas: use nomes consistentes, tipos adequados (DATE, DECIMAL), e evite colunas “genéricas” (ex.: campo1, campo2). Prefira atributos atômicos (um valor por coluna), como telefone separado de ddd se isso for relevante para consultas e validações.

Chave primária (PK) e chave estrangeira (FK)

Chave primária identifica unicamente uma linha. Pode ser um identificador artificial (id_cliente) ou natural (CPF), mas em sistemas bancários é comum usar IDs numéricos e manter CPF com UNIQUE.

Chave estrangeira referencia a PK de outra tabela, conectando os dados. Exemplo: conta.id_cliente referencia cliente.id_cliente.

Cardinalidade (1:1, 1:N, N:N)

  • 1:N: um cliente pode ter várias contas; uma conta pertence a um cliente. Implementação: FK em conta apontando para cliente.
  • 1:1: um cliente e um “perfil” exclusivo (depende do caso). Implementação: FK com UNIQUE ou PK compartilhada.
  • N:N: uma conta pode ter vários titulares e um cliente pode ser titular de várias contas. Implementação: tabela associativa (ex.: titularidade com PK composta).

Esquema bancário fictício (base para exercícios)

Vamos usar um esquema simplificado com clientes, contas, transações e cartões. Ele é suficiente para praticar JOINs, agregações, integridade referencial e transações.

Continue em nosso aplicativo

Você poderá ouvir o audiobook com a tela desligada, ganhar gratuitamente o certificado deste curso e ainda ter acesso a outros 5.000 cursos online gratuitos.

ou continue lendo abaixo...
Download App

Baixar o aplicativo

-- CLIENTES: dados cadastrais (CPF único, mas não necessariamente PK no exemplo)  CREATE TABLE cliente (   id_cliente      BIGINT PRIMARY KEY,   nome            VARCHAR(120) NOT NULL,   cpf             CHAR(11) NOT NULL UNIQUE,   data_nascimento DATE,   email           VARCHAR(120),   criado_em       TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP );  -- CONTAS: cada conta pertence a um cliente (modelo 1:N) CREATE TABLE conta (   id_conta     BIGINT PRIMARY KEY,   id_cliente   BIGINT NOT NULL,   agencia      CHAR(4) NOT NULL,   numero       CHAR(8) NOT NULL,   tipo         VARCHAR(20) NOT NULL,   saldo        DECIMAL(15,2) NOT NULL DEFAULT 0,   status       VARCHAR(20) NOT NULL DEFAULT 'ATIVA',   criada_em    TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,   CONSTRAINT fk_conta_cliente FOREIGN KEY (id_cliente) REFERENCES cliente(id_cliente),   CONSTRAINT uq_conta UNIQUE (agencia, numero) );  -- CARTOES: um cliente pode ter vários cartões; cartão pode estar vinculado a uma conta CREATE TABLE cartao (   id_cartao     BIGINT PRIMARY KEY,   id_cliente    BIGINT NOT NULL,   id_conta      BIGINT,   numero_mask   VARCHAR(19) NOT NULL,   bandeira      VARCHAR(20) NOT NULL,   validade      DATE NOT NULL,   status        VARCHAR(20) NOT NULL DEFAULT 'ATIVO',   CONSTRAINT fk_cartao_cliente FOREIGN KEY (id_cliente) REFERENCES cliente(id_cliente),   CONSTRAINT fk_cartao_conta   FOREIGN KEY (id_conta)   REFERENCES conta(id_conta) );  -- TRANSACOES: lançamentos na conta (crédito/débito) CREATE TABLE transacao (   id_transacao  BIGINT PRIMARY KEY,   id_conta      BIGINT NOT NULL,   data_hora     TIMESTAMP NOT NULL,   tipo          VARCHAR(10) NOT NULL, -- 'CREDITO' ou 'DEBITO'   valor         DECIMAL(15,2) NOT NULL,   descricao     VARCHAR(200),   CONSTRAINT fk_transacao_conta FOREIGN KEY (id_conta) REFERENCES conta(id_conta),   CONSTRAINT ck_transacao_tipo CHECK (tipo IN ('CREDITO','DEBITO')),   CONSTRAINT ck_transacao_valor CHECK (valor > 0) );

Observação importante para prova e prática: integridade referencial impede inserir uma transação para uma conta inexistente, ou uma conta para um cliente inexistente (a menos que a FK permita nulos, o que não é o caso em conta e transacao).

2) Normalização (visão prática para evitar problemas)

Por que normalizar

Normalização reduz redundância e evita anomalias:

  • Anomalia de inserção: não conseguir cadastrar algo sem outro dado “forçado”.
  • Anomalia de atualização: atualizar o mesmo dado em vários lugares e esquecer um.
  • Anomalia de exclusão: apagar um registro e perder informação que não deveria sumir.

1FN, 2FN, 3FN (o que mais cai na prática)

1FN: valores atômicos e sem “listas” na mesma coluna. Ex.: não guardar “(11)99999-0000,(11)98888-0000” em uma coluna telefones. Crie tabela telefone_cliente.

2FN: quando a PK é composta, nenhum atributo não-chave pode depender só de parte da PK. Ex.: em uma tabela associativa titularidade(id_cliente, id_conta, nome_cliente), nome_cliente depende apenas de id_cliente, então deve ficar em cliente.

3FN: atributos não-chave não devem depender de outros atributos não-chave (dependência transitiva). Ex.: em conta, guardar nome_agencia junto com agencia pode gerar inconsistência; melhor ter tabela agencia e referenciar.

Exemplo de “desnormalização” problemática e correção

Problema: tabela conta com colunas cpf_cliente e nome_cliente. Se o cliente mudar o nome, você teria que atualizar em todas as contas. Correção: manter dados do cliente apenas em cliente e referenciar por id_cliente.

3) Integridade referencial e regras de consistência

O que a FK garante

Uma FK garante que o valor exista na tabela referenciada. Ex.: não existe transacao.id_conta = 999 se não existir conta.id_conta = 999.

ON DELETE / ON UPDATE (comportamentos comuns)

Ao criar a FK, você pode definir o que acontece ao excluir/alterar a PK referenciada:

  • RESTRICT/NO ACTION (padrão em muitos SGBDs): impede excluir o “pai” se houver “filhos”.
  • CASCADE: exclui/atualiza em cascata (cuidado em dados bancários).
  • SET NULL: define FK como NULL (só se a coluna permitir NULL).
-- Exemplo: impedir exclusão de conta com transações (padrão) ALTER TABLE transacao DROP CONSTRAINT fk_transacao_conta;  ALTER TABLE transacao ADD CONSTRAINT fk_transacao_conta   FOREIGN KEY (id_conta) REFERENCES conta(id_conta)   ON DELETE RESTRICT; -- ou NO ACTION

Em cenários bancários, é comum não apagar transações (auditoria). Em vez de DELETE, usa-se status (ex.: estorno, cancelado) ou tabelas de histórico.

4) SQL: do básico ao avançado (com foco em prova e prática)

SELECT básico (projeção e FROM)

-- Listar clientes (colunas específicas) SELECT id_cliente, nome, cpf FROM cliente;

Erros comuns: esquecer o FROM, errar nome de coluna, confundir id_cliente com cpf.

Filtros (WHERE) e operadores

-- Contas ativas de um cliente específico SELECT id_conta, agencia, numero, saldo FROM conta WHERE id_cliente = 10 AND status = 'ATIVA';  -- Faixa de saldo SELECT id_conta, saldo FROM conta WHERE saldo BETWEEN 1000 AND 5000;  -- Busca por padrão (cuidado com performance) SELECT id_cliente, nome FROM cliente WHERE nome LIKE 'ANA%';

Erros comuns: usar = NULL (o correto é IS NULL), confundir AND e OR sem parênteses.

-- Correto para nulos SELECT * FROM cartao WHERE id_conta IS NULL;

Ordenação (ORDER BY)

-- Maiores saldos primeiro SELECT id_conta, saldo FROM conta ORDER BY saldo DESC;

Erros comuns: achar que o banco “sempre” retorna ordenado. Sem ORDER BY, a ordem não é garantida.

Funções e expressões úteis

-- Contar cartões ativos por bandeira SELECT bandeira, COUNT(*) AS qtd FROM cartao WHERE status = 'ATIVO' GROUP BY bandeira;  -- Data (varia por SGBD): exemplo genérico de extração do ano (pode ser EXTRACT) SELECT id_transacao, data_hora FROM transacao WHERE data_hora >= TIMESTAMP '2025-01-01 00:00:00';

Em prova, atenção: funções de data/hora mudam entre SGBDs. O conceito (filtrar por período, extrair partes) é o que costuma ser cobrado.

Agregações, GROUP BY e HAVING

GROUP BY agrupa linhas para calcular agregações (COUNT, SUM, AVG, MIN, MAX). HAVING filtra grupos (após agregação), enquanto WHERE filtra linhas (antes).

-- Total movimentado por conta (somatório de valores) SELECT id_conta, SUM(valor) AS total_valor FROM transacao GROUP BY id_conta;  -- Contas com mais de 100 transações SELECT id_conta, COUNT(*) AS qtd_transacoes FROM transacao GROUP BY id_conta HAVING COUNT(*) > 100;

Erro comum: colocar condição de agregação no WHERE:

-- ERRADO (COUNT(*) não pode no WHERE) SELECT id_conta FROM transacao WHERE COUNT(*) > 100 GROUP BY id_conta;

JOINs (INNER, LEFT) e leitura de resultados

JOIN é o ponto central para interpretar consultas em prova. A regra: defina a tabela “base” no FROM, depois conecte com ON usando PK/FK.

-- INNER JOIN: só retorna contas que têm cliente correspondente SELECT c.id_conta, c.agencia, c.numero, cl.nome FROM conta c INNER JOIN cliente cl ON cl.id_cliente = c.id_cliente;  -- LEFT JOIN: retorna todas as contas, mesmo que o cliente esteja ausente (em FK NOT NULL isso não ocorre, mas é didático) SELECT c.id_conta, cl.nome FROM conta c LEFT JOIN cliente cl ON cl.id_cliente = c.id_cliente;

Erros comuns:

  • Esquecer condição do JOIN (gera produto cartesiano e explode linhas).
  • Colocar condição no WHERE que anula o LEFT JOIN. Ex.: filtrar coluna da tabela “da direita” no WHERE transforma o resultado em algo parecido com INNER JOIN.
-- Exemplo do erro: vira “quase INNER” porque cl.nome no WHERE elimina nulos SELECT c.id_conta, cl.nome FROM conta c LEFT JOIN cliente cl ON cl.id_cliente = c.id_cliente WHERE cl.nome LIKE 'A%';  -- Forma correta: condição no ON para preservar contas sem cliente (quando aplicável) SELECT c.id_conta, cl.nome FROM conta c LEFT JOIN cliente cl ON cl.id_cliente = c.id_cliente AND cl.nome LIKE 'A%';

Subconsultas (subqueries) e EXISTS

Subconsultas aparecem para “filtrar por um conjunto” ou “comparar com um agregado”.

-- Contas com saldo acima da média SELECT id_conta, saldo FROM conta WHERE saldo > (SELECT AVG(saldo) FROM conta);  -- Clientes que possuem pelo menos um cartão ativo (EXISTS) SELECT cl.id_cliente, cl.nome FROM cliente cl WHERE EXISTS (   SELECT 1   FROM cartao ca   WHERE ca.id_cliente = cl.id_cliente     AND ca.status = 'ATIVO' );

Erro comum: subconsulta retornando várias linhas quando se espera uma só (ex.: usar = (SELECT ...) quando a subconsulta retorna múltiplos valores; nesse caso, usar IN).

-- Correto quando pode retornar vários id_cliente SELECT id_conta FROM conta WHERE id_cliente IN (SELECT id_cliente FROM cartao WHERE status = 'ATIVO');

Views (visões) para simplificar consultas

View é uma consulta “salva” que pode ser usada como tabela. Útil para padronizar relatórios e reduzir repetição de JOINs.

CREATE VIEW vw_conta_cliente AS SELECT   c.id_conta, c.agencia, c.numero, c.tipo, c.saldo, c.status,   cl.id_cliente, cl.nome, cl.cpf FROM conta c INNER JOIN cliente cl ON cl.id_cliente = c.id_cliente;  -- Uso da view SELECT id_conta, nome, saldo FROM vw_conta_cliente WHERE status = 'ATIVA' ORDER BY saldo DESC;

5) DDL: CREATE e ALTER (estrutura do banco)

CREATE TABLE: pontos que mais geram erro

  • Definir NOT NULL quando o dado é obrigatório.
  • Definir UNIQUE para chaves naturais (CPF, combinação agência+número).
  • Definir CHECK para domínios (tipo de transação, valor positivo).
  • Definir FK com a tabela e coluna corretas.
-- Adicionando coluna (ALTER) ALTER TABLE cliente ADD COLUMN telefone VARCHAR(20);  -- Alterando restrição (exemplo genérico; sintaxe pode variar) ALTER TABLE conta ADD CONSTRAINT ck_conta_saldo CHECK (saldo >= 0);

Erro comum: tentar criar FK para coluna que não é PK/UNIQUE na tabela referenciada (muitos SGBDs exigem isso).

6) DML: INSERT, UPDATE, DELETE (manipulação de dados)

INSERT (inserção) com cuidado em FKs

Passo a passo prático: primeiro insira o “pai” (cliente), depois o “filho” (conta), depois dependentes (transação, cartão).

-- 1) Inserir cliente INSERT INTO cliente (id_cliente, nome, cpf, data_nascimento, email) VALUES (1, 'Ana Silva', '12345678901', DATE '1995-04-10', 'ana@exemplo.com');  -- 2) Inserir conta vinculada ao cliente INSERT INTO conta (id_conta, id_cliente, agencia, numero, tipo, saldo) VALUES (100, 1, '1234', '00001234', 'CORRENTE', 1500.00);  -- 3) Inserir transação na conta INSERT INTO transacao (id_transacao, id_conta, data_hora, tipo, valor, descricao) VALUES (1000, 100, CURRENT_TIMESTAMP, 'CREDITO', 500.00, 'Depósito');

Erros comuns: inserir conta com id_cliente inexistente (violação de FK), inserir transação com valor negativo (violação de CHECK), duplicar CPF (violação de UNIQUE).

UPDATE (atualização) e filtros

Passo a passo prático: sempre teste o WHERE com SELECT antes de atualizar.

-- Conferir antes SELECT id_conta, saldo FROM conta WHERE id_conta = 100;  -- Atualizar saldo (exemplo didático; em sistemas reais, saldo costuma ser derivado de lançamentos) UPDATE conta SET saldo = saldo + 200.00 WHERE id_conta = 100;

Erro comum crítico: esquecer o WHERE e atualizar todas as linhas.

-- PERIGOSO: atualiza todas as contas UPDATE conta SET status = 'BLOQUEADA';

DELETE (exclusão) e integridade

Se houver transações vinculadas a uma conta, o DELETE pode falhar por FK (dependendo da regra). Em dados bancários, normalmente evita-se apagar transações.

-- Tentativa de excluir conta (pode falhar se houver transações) DELETE FROM conta WHERE id_conta = 100;

Alternativa comum: “exclusão lógica” (status):

UPDATE conta SET status = 'ENCERRADA' WHERE id_conta = 100;

7) Transações: COMMIT e ROLLBACK (consistência)

Conceito e quando usar

Transação agrupa operações para que sejam aplicadas juntas. Se algo der errado, você desfaz tudo com ROLLBACK. Se estiver tudo certo, confirma com COMMIT. Isso é essencial para operações como transferência entre contas.

Passo a passo: transferência entre contas (exemplo didático)

-- Exemplo conceitual de transferência: debitar uma conta e creditar outra BEGIN;  -- 1) Registrar débito INSERT INTO transacao (id_transacao, id_conta, data_hora, tipo, valor, descricao) VALUES (2001, 100, CURRENT_TIMESTAMP, 'DEBITO', 100.00, 'Transferência enviada');  -- 2) Registrar crédito INSERT INTO transacao (id_transacao, id_conta, data_hora, tipo, valor, descricao) VALUES (2002, 101, CURRENT_TIMESTAMP, 'CREDITO', 100.00, 'Transferência recebida');  -- 3) Confirmar COMMIT;  -- Se ocorrer erro em qualquer etapa: ROLLBACK;

Erros comuns: confirmar parcialmente (sem transação), esquecer COMMIT (mudanças não persistem em alguns ambientes), ou tratar saldo com UPDATE sem garantir consistência com os lançamentos.

8) Exercícios (com interpretação e erros comuns)

Exercício 1: SELECT com filtro e ordenação

Enunciado: Liste as contas ativas da agência 1234 com saldo acima de 1000, ordenando do maior para o menor saldo.

SELECT id_conta, agencia, numero, saldo FROM conta WHERE status = 'ATIVA'   AND agencia = '1234'   AND saldo > 1000 ORDER BY saldo DESC;

Erros comuns: comparar agencia numérica sem aspas quando o tipo é CHAR; esquecer ORDER BY.

Exercício 2: agregação com GROUP BY/HAVING

Enunciado: Encontre contas com mais de 5 transações registradas.

SELECT id_conta, COUNT(*) AS qtd FROM transacao GROUP BY id_conta HAVING COUNT(*) > 5;

Erro comum: usar WHERE COUNT(*) > 5.

Exercício 3: JOIN para relatório cliente-conta

Enunciado: Liste nome do cliente, agência, número e saldo das contas.

SELECT cl.nome, c.agencia, c.numero, c.saldo FROM conta c INNER JOIN cliente cl ON cl.id_cliente = c.id_cliente;

Erro comum: fazer JOIN com coluna errada (ex.: cl.cpf = c.id_cliente), o que gera resultado vazio ou incorreto.

Exercício 4: LEFT JOIN e contagem de cartões por cliente

Enunciado: Liste todos os clientes e a quantidade de cartões (incluindo quem tem zero).

SELECT cl.id_cliente, cl.nome, COUNT(ca.id_cartao) AS qtd_cartoes FROM cliente cl LEFT JOIN cartao ca ON ca.id_cliente = cl.id_cliente GROUP BY cl.id_cliente, cl.nome ORDER BY qtd_cartoes DESC;

Erros comuns: usar COUNT(*) (contaria linhas do cliente mesmo sem cartão, inflando para 1); esquecer colunas do GROUP BY.

Exercício 5: subconsulta para “acima da média”

Enunciado: Liste contas com saldo acima da média de todas as contas.

SELECT id_conta, saldo FROM conta WHERE saldo > (SELECT AVG(saldo) FROM conta) ORDER BY saldo DESC;

Erro comum: tentar usar AVG(saldo) diretamente no WHERE sem subconsulta.

Exercício 6: identificar erro de integridade referencial

Enunciado: Por que o comando abaixo pode falhar?

INSERT INTO transacao (id_transacao, id_conta, data_hora, tipo, valor) VALUES (3000, 9999, CURRENT_TIMESTAMP, 'DEBITO', 50.00);

Resposta esperada: falha por violação de FK se não existir conta.id_conta = 9999.

Exercício 7: identificar erro de lógica em LEFT JOIN

Enunciado: A consulta abaixo deveria listar todos os clientes e seus cartões ativos, incluindo clientes sem cartão. Ela está correta?

SELECT cl.id_cliente, cl.nome, ca.id_cartao FROM cliente cl LEFT JOIN cartao ca ON ca.id_cliente = cl.id_cliente WHERE ca.status = 'ATIVO';

Resposta esperada: não. O WHERE ca.status = 'ATIVO' elimina linhas onde ca é NULL, removendo clientes sem cartão. Correção: mover a condição para o ON.

SELECT cl.id_cliente, cl.nome, ca.id_cartao FROM cliente cl LEFT JOIN cartao ca ON ca.id_cliente = cl.id_cliente AND ca.status = 'ATIVO';

Exercício 8: transação com COMMIT/ROLLBACK

Enunciado: Você precisa registrar duas transações (débito e crédito). O que acontece se a segunda inserção falhar e você não estiver usando transação?

Resposta esperada: pode ficar registrado apenas o débito (inconsistência). Com transação, você executa ROLLBACK e nenhuma das duas operações é persistida.

Agora responda o exercício sobre o conteúdo:

Em uma consulta que usa LEFT JOIN para listar todos os clientes e seus cartões ativos (incluindo clientes sem cartão), qual ajuste mantém os clientes sem cartão no resultado?

Você acertou! Parabéns, agora siga para a próxima página

Você errou! Tente novamente.

No LEFT JOIN, filtrar colunas da tabela da direita no WHERE elimina linhas com NULL, removendo clientes sem cartão. Ao colocar a condição (ex.: status = 'ATIVO') no ON, o join preserva todos os clientes e traz cartões ativos quando existirem.

Próximo capitúlo

Bancos de Dados: índices, transações, concorrência e desempenho para o Escriturário do Banco do Brasil – Agente de Tecnologia

Arrow Right Icon
Baixe o app para ganhar Certificação grátis e ouvir os cursos em background, mesmo com a tela desligada.