▶ Slides ← MĂłdulo
Módulo 2 · Ciclo Comum · IN02

Banco de Dados I

Aula 2 — Material de Leitura Aprofundado

1. O que Ă© um banco de dados?

Um banco de dados Ă© uma coleção organizada de informaçÔes relacionadas, estruturadas de forma que possam ser facilmente acessadas, gerenciadas e atualizadas. A palavra-chave aqui Ă© organização: um arquivo de texto com mil linhas de dados pode conter informação, mas nĂŁo Ă© um banco de dados — falta a estrutura que permite recuperar exatamente o que vocĂȘ precisa em milissegundos.

Pense no Instagram: cada foto que vocĂȘ posta precisa ser associada ao seu perfil, ter uma lista de curtidas, comentĂĄrios, tags e metadados como data e localização. Quando alguĂ©m abre o feed, o aplicativo busca em fraçÔes de segundo as publicaçÔes mais recentes de centenas de pessoas que vocĂȘ segue, classifica por relevĂąncia e exibe com imagens em alta resolução. Isso sĂł Ă© possĂ­vel porque todos esses dados estĂŁo armazenados em bancos de dados cuidadosamente projetados. O mesmo raciocĂ­nio vale para um banco financeiro que precisa garantir que uma transferĂȘncia debite de uma conta e credite em outra de forma atĂŽmica — sem que nenhuma das duas operaçÔes fique pela metade — ou para um e-commerce que precisa checar em tempo real se um produto estĂĄ disponĂ­vel em estoque antes de confirmar um pedido.

Antes dos bancos de dados, as aplicaçÔes armazenavam dados em arquivos no sistema de arquivos do sistema operacional. Esse modelo causava problemas sĂ©rios: redundĂąncia (os mesmos dados duplicados em mĂșltiplos arquivos), inconsistĂȘncia (versĂ”es diferentes do mesmo dado), dificuldade de acesso concorrente (dois programas tentando escrever no mesmo arquivo ao mesmo tempo) e ausĂȘncia de segurança granular. Os bancos de dados foram criados exatamente para resolver esses problemas, fornecendo uma camada de abstração entre os dados e as aplicaçÔes que os consomem.

Definição formal

Segundo Ramakrishnan e Gehrke (Database Management Systems, 3ÂȘ ed.), um banco de dados Ă© "uma coleção de dados que descrevem os fatos de um minimundo" — ou seja, um recorte do mundo real relevante para uma determinada organização ou aplicação.

Bancos de dados no cotidiano

Vale listar concretamente os tipos de dados que sistemas conhecidos armazenam em bancos de dados para que a abstração fique palpåvel:

SistemaDados persistidosOperaçÔes críticas
InstagramPerfis, fotos, seguidores, curtidas, stories, mensagensFeed personalizado, busca por hashtag, notificaçÔes em tempo real
Banco digitalContas, transaçÔes, saldos, limites, extratos, investimentosTransferĂȘncia atĂŽmica, detecção de fraude, extrato por perĂ­odo
E-commerceProdutos, estoque, pedidos, clientes, endereços, pagamentosReserva de estoque, cålculo de frete, histórico de pedidos
SpotifyMĂșsicas, artistas, playlists, histĂłrico de escuta, preferĂȘnciasRecomendação personalizada, busca full-text, streaming adaptativo

Evolução do armazenamento de dados

Para entender por que precisamos de bancos de dados, Ă© instrutivo olhar para a evolução das formas de armazenar informação em sistemas computacionais. Cada salto resolveu uma limitação concreta da geração anterior — e cada solução trouxe trade-offs prĂłprios. Compreender esse histĂłrico ajuda a escolher a ferramenta certa para o problema atual e a evitar a tentação de "improvisar com arquivos" quando o caso pede um SGBD de verdade.

EtapaTecnologiaLimitação superadaLimitação remanescente
📄 Arquivo de texto.txt, .csv, logs em discoPersistĂȘncia simples — os dados sobrevivem ao desligamentoSem estrutura, sem Ă­ndices, sem concorrĂȘncia, sem integridade
📊 PlanilhaExcel, Google SheetsEstrutura tabular, fĂłrmulas, filtros, ordenaçãoLimite prĂĄtico de ~1M linhas, edição manual, sem concorrĂȘncia confiĂĄvel, sem garantias ACID
🐘 BD relacionalPostgreSQL, MySQL, OracleSQL declarativo, transaçÔes ACID, integridade, milhĂ”es de linhas, mĂșltiplos usuĂĄrios simultĂąneosEscala vertical, esquema rĂ­gido, custo de JOINs em escala extrema
☁ Banco em cloudSupabase, RDS, Cloud SQL, AuroraEscala horizontal, alta disponibilidade, replicação geogrĂĄfica, backups automĂĄticosCusto proporcional ao uso, dependĂȘncia do provedor, latĂȘncia por regiĂŁo
Quando ainda faz sentido um arquivo .txt ou .csv?

Para dados imutĂĄveis, pequenos e processados em lote (logs histĂłricos, exports semanais, configuraçÔes estĂĄticas), arquivos ainda sĂŁo apropriados. O ponto de virada Ă© quando vocĂȘ precisa de consultas concorrentes, integridade referencial ou consultas seletivas eficientes. Nesse momento, mover para um SGBD economiza muito mais cĂłdigo de validação do que custa em complexidade operacional.

2. SGBD — Sistema Gerenciador de Banco de Dados

É fundamental distinguir duas coisas que frequentemente se confundem: o banco de dados (os dados em si, os arquivos fĂ­sicos em disco) e o SGBD — Sistema Gerenciador de Banco de Dados. O SGBD Ă© o software que gerencia o banco: ele recebe comandos, verifica permissĂ”es, garante a integridade dos dados, controla o acesso concorrente de mĂșltiplos usuĂĄrios ou aplicaçÔes, gerencia memĂłria e cache, faz backups e recuperação em caso de falha. O banco de dados em si sĂŁo os arquivos fĂ­sicos no disco — sem o SGBD, vocĂȘ nĂŁo tem como interagir com eles de forma segura e eficiente.

Um SGBD cumpre quatro funçÔes essenciais: definição de dados (permite criar e alterar a estrutura das tabelas via DDL), manipulação de dados (permite inserir, atualizar, deletar e consultar via DML e DQL), controle de dados (gerencia permissÔes de acesso via DCL) e controle de transaçÔes (garante as propriedades ACID via TCL). Essas quatro funçÔes correspondem exatamente às cinco sublinguagens do SQL, que estudaremos mais adiante neste material.

O mercado oferece vĂĄrios SGBDs, cada um com caracterĂ­sticas distintas. PostgreSQL Ă© o mais robusto e completo entre os open-source, com suporte a tipos avançados (JSON nativo, arrays, geometria), extensĂ”es e conformidade rigorosa com o padrĂŁo SQL — serĂĄ nossa ferramenta principal neste mĂłdulo. MySQL (e seu fork MariaDB) Ă© amplamente usado em aplicaçÔes web de mĂ©dio porte. SQLite Ă© uma biblioteca embarcada, sem servidor separado, ideal para apps mobile e desktop. MongoDB Ă© um banco de dados NoSQL orientado a documentos JSON, Ăștil quando o esquema Ă© altamente variĂĄvel. A escolha do SGBD Ă© um RNF da categoria RestriçÔes de Design e deve ser justificada, nĂŁo aleatĂłria.

Por que PostgreSQL neste mĂłdulo?

PostgreSQL Ă© open-source, gratuito, tem uma comunidade enorme, segue fielmente o padrĂŁo SQL ANSI, suporta JSON nativamente, possui tipos avançados e extensĂ”es como PostGIS para dados geogrĂĄficos. Aprender PostgreSQL prepara vocĂȘ para migrar facilmente para MySQL ou qualquer outro banco relacional — e para entender o que diferencia os bancos NoSQL dos relacionais.

Como o SGBD garante integridade

Uma das responsabilidades mais importantes do SGBD Ă© garantir que os dados permaneçam Ă­ntegros — consistentes com as regras do negĂłcio. Isso Ă© feito por meio de constraints (restriçÔes) definidas no esquema, que o SGBD verifica a cada operação de escrita. Se uma constraint for violada, a operação Ă© rejeitada com um erro antes de qualquer dado ser persistido. Esse mecanismo evita que a responsabilidade de validação fique 100% na camada da aplicação — que pode ter bugs ou ser bypassada diretamente via SQL por alguĂ©m com acesso ao banco.

Pipeline interno: o que acontece quando vocĂȘ executa uma query

Quando sua aplicação envia SELECT * FROM usuarios WHERE id = 1; ao banco, o SGBD nĂŁo interpreta o texto literalmente — ele passa a query por uma sequĂȘncia de estĂĄgios bem definidos. Compreender esse pipeline torna explicĂĄvel por que algumas queries sĂŁo rĂĄpidas e outras nĂŁo, e o que tuning de banco realmente significa.

EstĂĄgioO que fazSaĂ­da
1. ParserLĂȘ o texto SQL, valida sintaxe e converte em uma ĂĄrvore de anĂĄlise (AST).Erro de sintaxe ou ĂĄrvore vĂĄlida
2. Analyzer / RewriterResolve nomes de tabelas e colunas, aplica regras (views, RLS), checa permissÔes DCL.Plano lógico
3. Planner / OptimizerAvalia mĂșltiplos planos de execução (sequential scan, index scan, hash join, nested loop) e escolhe o de menor custo estimado com base em estatĂ­sticas das tabelas.Plano fĂ­sico
4. ExecutorExecuta o plano fĂ­sico em pipeline, lendo pĂĄginas do disco (ou do cache em memĂłria), aplicando filtros e devolvendo linhas.Resultado para o cliente
5. Storage layerLĂȘ e escreve pĂĄginas de 8 KB (no PostgreSQL) em arquivos no disco. O WAL (Write-Ahead Log) registra cada alteração antes de tocar a tabela.Dados persistidos com durabilidade

Ao escrever (INSERT, UPDATE, DELETE), o SGBD primeiro grava a operação no WAL — Write-Ahead Log e sĂł depois aplica a mudança nas pĂĄginas de dados. Esse log sequencial Ă© o que garante a Durabilidade do ACID: se a mĂĄquina cair logo apĂłs o COMMIT, ao reiniciar o SGBD relĂȘ o WAL e reaplica as operaçÔes que ainda nĂŁo tinham chegado Ă s pĂĄginas em disco. Backups incrementais e replicação fĂ­sica tambĂ©m usam o WAL como fonte da verdade — por isso ele Ă© central tanto para confiabilidade quanto para alta disponibilidade.

Investigando o plano: EXPLAIN

No PostgreSQL, o comando EXPLAIN ANALYZE SELECT ... mostra o plano fĂ­sico escolhido pelo planner e o tempo real de cada operação. É a primeira ferramenta de tuning de query: se vocĂȘ ver Seq Scan em uma tabela grande sendo filtrada por uma coluna, falta um Ă­ndice ali.

3. Modelo Entidade-Relacionamento (ER)

Antes de escrever uma linha de SQL, precisamos modelar o problema. O Modelo Entidade-Relacionamento (ER), proposto por Peter Chen em 1976, é a linguagem gråfica padrão para representar a estrutura de informação de um sistema. Ele é independente de tecnologia: um diagrama ER pode ser implementado em PostgreSQL, MySQL, Oracle ou qualquer outro banco relacional. O modelo ER nos força a pensar sobre o que armazenar antes de pensar como.

Um diagrama ER tem trĂȘs elementos fundamentais. Entidades sĂŁo os "substantivos" do sistema — as coisas sobre as quais precisamos armazenar informação. Exemplos: Cliente, Produto, Pedido, FuncionĂĄrio. Cada entidade tem atributos — as propriedades que descrevem cada instĂąncia dessa entidade. Um Cliente pode ter nome, email e telefone. Um Produto pode ter nome, preço e estoque. Um atributo especial Ă© a chave primĂĄria (PK) — um atributo (ou conjunto de atributos) cujo valor identifica unicamente cada instĂąncia da entidade. Finalmente, relacionamentos sĂŁo as associaçÔes entre entidades — os "verbos" do sistema. Um Cliente realiza Pedidos. Um Pedido contĂ©m Produtos.

A cardinalidade especifica quantas instĂąncias de uma entidade podem se relacionar com instĂąncias de outra. Os trĂȘs tipos fundamentais sĂŁo: 1:1 (um para um) — cada pessoa tem exatamente um CPF; 1:N (um para muitos) — um cliente pode ter vĂĄrios pedidos, mas cada pedido pertence a um Ășnico cliente; e N:M (muitos para muitos) — um pedido pode conter vĂĄrios produtos, e um produto pode aparecer em vĂĄrios pedidos. Relacionamentos N:M exigem uma tabela intermediĂĄria (tabela associativa ou junction table) para serem implementados no modelo relacional.

Diagrama ER — Loja Universitária

Veja um diagrama simplificado para o sistema de loja universitĂĄria iniciado na Aula 1:

Cliente
id (PK)
nome
email
criado_em
realiza
1 : N
Pedido
id (PK)
cliente_id (FK)
status
criado_em
contém
N : M
Produto
id (PK)
nome
preco
estoque
Cuidado com N:M

O relacionamento N:M entre Pedido e Produto nĂŁo pode ser implementado diretamente com duas tabelas. É necessĂĄrio criar uma tabela associativa item_pedido com as chaves estrangeiras de ambos os lados, mais atributos do relacionamento como quantidade e preco_unit. Esquecer essa tabela Ă© um dos erros mais comuns de modelagem.

Notação de Chen — símbolos gráficos formais

A notação proposta por Peter Chen no artigo original de 1976 estabelece uma gramĂĄtica visual simples e ainda hoje a referĂȘncia didĂĄtica para diagramas ER. Cada elemento do modelo tem uma forma geomĂ©trica especĂ­fica, e linhas conectam essas formas com rĂłtulos de cardinalidade. Conhecer a notação canĂŽnica torna vocĂȘ capaz de ler qualquer diagrama ER em livros, papers acadĂȘmicos e documentação corporativa — independentemente da ferramenta usada para desenhĂĄ-lo.

SĂ­mboloRepresentaCategoria gramaticalExemplo
▭ RetñnguloEntidadeSubstantivoUSUARIO, PEDIDO, PRODUTO
◇ LosangoRelacionamentoVerbofaz, contĂ©m, pertence a
◯ Elipse / ovalAtributoAdjetivo / propriedadenome, email, preço
◯ sublinhadaAtributo identificador (PK)Identificador Ășnicoid
— linhaConexão entre entidade e relacionamento, ou entidade e atributoPredicaçãorotulada com cardinalidade 1, N ou M
A regra do "quadrado em volta do losango" — relacionamentos N:M

Quando o relacionamento Ă© muitos-para-muitos (N:M) e carrega atributos prĂłprios — por exemplo, quantidade e preco_unit em "PEDIDO contĂ©m PRODUTO" —, a notação de Chen desenha um retĂąngulo tracejado em volta do losango. Isso sinaliza que esse relacionamento, ao ser implementado no modelo lĂłgico, vai virar uma tabela associativa com chave primĂĄria composta. Atributos do relacionamento (como quantidade) sĂŁo desenhados como elipses ligadas ao losango.

Modelagem em 3 etapas: Conceitual, LĂłgico, FĂ­sico

Modelar um banco de dados nĂŁo Ă© uma atividade Ășnica — Ă© um processo de refinamento progressivo do O QUE existe no domĂ­nio atĂ© o COMO implementar em um SGBD especĂ­fico. A literatura clĂĄssica organiza esse processo em trĂȘs nĂ­veis sucessivos, cada um com um artefato prĂłprio e uma audiĂȘncia distinta.

📩 1. Modelo Conceitual — O QUE

Artefato: diagrama ER (notação de Chen ou Crow's Foot).
Foco: entidades, atributos e relacionamentos do domínio. Independente de SGBD, linguagem de programação ou tecnologia.
AudiĂȘncia: stakeholders de negĂłcio, product owners, especialistas do domĂ­nio.
Pergunta-chave: "Quais sĂŁo as coisas que o sistema precisa lembrar e como elas se relacionam?"

đŸ—‚ïž 2. Modelo LĂłgico — COMO

Artefato: esquema relacional com tabelas, colunas, tipos genéricos, PKs e FKs.
Foco: tradução das entidades em tabelas, dos relacionamentos 1:N em FKs e dos N:M em tabelas associativas. Ainda independente do SGBD escolhido.
AudiĂȘncia: engenheiros de software, DBAs, arquitetos de dados.
Pergunta-chave: "Como organizo essas informaçÔes em tabelas para que sejam consistentes e consultåveis?"

⚙ 3. Modelo FĂ­sico — EM QUAL BANCO

Artefato: SQL DDL especĂ­fico do SGBD — CREATE TABLE, Ă­ndices, partiçÔes, tablespaces.
Foco: tipos concretos do SGBD (SERIAL vs AUTO_INCREMENT vs IDENTITY), JSONB, Ă­ndices, particionamento, tuning especĂ­fico.
AudiĂȘncia: desenvolvedores que vĂŁo escrever migrations e DBAs.
Pergunta-chave: "Que código SQL exato vou rodar no PostgreSQL 16 (ou no banco de produção)?"

Por que separar as 3 etapas?

A separação evita acoplar decisĂ”es de domĂ­nio (que sĂŁo duradouras) com decisĂ”es de tecnologia (que mudam). Se amanhĂŁ vocĂȘ precisar migrar de PostgreSQL para Oracle, o modelo conceitual e o lĂłgico permanecem vĂĄlidos — sĂł o fĂ­sico precisa ser reescrito. Inverter a ordem (codar primeiro o SQL, "modelar" depois) Ă© um anti-padrĂŁo clĂĄssico que produz esquemas tortos e migrations dolorosas.

Por que modelar antes de criar tabelas?

Modelar em ER antes de escrever DDL tem dois benefĂ­cios principais. Primeiro, permite identificar problemas de design — entidades esquecidas, relacionamentos ambĂ­guos, atributos mal posicionados — antes que qualquer cĂłdigo seja escrito. Corrigir um diagrama leva minutos; corrigir um banco de dados em produção com dados reais pode levar horas e exigir migraçÔes complexas. Segundo, o diagrama ER Ă© uma linguagem comum entre tĂ©cnicos e nĂŁo tĂ©cnicos: um gerente de produto consegue entender e validar um diagrama ER mesmo sem saber SQL.

4. Modelo Relacional — Tabelas, PK e FK

O modelo relacional, proposto por Edgar F. Codd em 1970, Ă© o modelo de dados mais amplamente usado no mundo. Toda informação Ă© organizada em tabelas (tambĂ©m chamadas de relaçÔes, em homenagem ao modelo matemĂĄtico de ĂĄlgebra relacional). Cada tabela tem um nome Ășnico no banco, um conjunto fixo de colunas (atributos) com tipos de dados definidos, e um conjunto de linhas (tuplas), onde cada linha representa uma instĂąncia da entidade.

A chave primĂĄria (Primary Key, PK) Ă© uma coluna (ou conjunto de colunas) que identifica unicamente cada linha da tabela. Toda tabela deve ter uma PK. O SGBD cria automaticamente um Ă­ndice na PK, tornando buscas por esse campo extremamente rĂĄpidas. Em PostgreSQL, o tipo SERIAL (ou BIGSERIAL para tabelas maiores) Ă© a forma mais comum de criar PKs numĂ©ricas auto-incrementais. Para sistemas que precisam de IDs globalmente Ășnicos sem coordenação central, usa-se UUID.

A chave estrangeira (Foreign Key, FK) Ă© uma coluna que referencia a PK de outra tabela, estabelecendo o relacionamento entre elas no nĂ­vel fĂ­sico. Quando vocĂȘ define uma FK no SGBD, ele passa a verificar automaticamente a integridade referencial: vocĂȘ nĂŁo pode inserir uma linha com cliente_id = 99 em pedidos se nĂŁo existir um cliente com id = 99 na tabela clientes. TambĂ©m nĂŁo pode deletar um cliente que ainda tem pedidos associados — a menos que configure um comportamento de cascata (ON DELETE CASCADE).

Da ER às tabelas — regras formais de tradução

A passagem do modelo conceitual (ER) para o modelo lógico (relacional) segue um conjunto compacto de regras mecñnicas. Aplicá-las disciplinadamente evita os dois erros mais comuns de iniciantes: (1) esquecer a tabela associativa em N:M e (2) colocar a FK do lado errado em 1:N. Memorize essas quatro regras — elas resolvem 95% dos casos práticos.

Construção ERTradução para o modelo relacionalExemplo
EntidadeVira uma tabela com mesmo nome (no plural, em snake_case).USUARIO → tabela usuarios
AtributoVira uma coluna com tipo apropriado. O atributo identificador vira PRIMARY KEY.email → coluna email VARCHAR(200)
Relacionamento 1:1Vira uma FK em uma das duas tabelas (geralmente na obrigatória), marcada com UNIQUE para impedir duplicação.Pessoa ↔ CPF: pessoas.cpf_id INTEGER UNIQUE REFERENCES cpfs(id)
Relacionamento 1:NVira uma FK no lado N (o "muitos") apontando para a PK do lado 1.USUARIO 1—N PEDIDO: pedidos.usuario_id INTEGER REFERENCES usuarios(id)
Relacionamento N:MVira uma tabela associativa com PK composta (FK_lado_a, FK_lado_b) e absorve atributos do relacionamento.PEDIDO N—M PRODUTO: tabela pedido_produto(pedido_id, produto_id, quantidade) com PRIMARY KEY (pedido_id, produto_id)
SQL — exemplo completo: as 4 tabelas do diagrama ER USUARIO/PEDIDO/PRODUTO
-- Entidade USUARIO → tabela usuarios
CREATE TABLE usuarios (
  id     SERIAL       PRIMARY KEY,
  nome   VARCHAR(100) NOT NULL,
  email  VARCHAR(200) UNIQUE NOT NULL
);

-- Entidade PRODUTO → tabela produtos
CREATE TABLE produtos (
  id     SERIAL          PRIMARY KEY,
  nome   VARCHAR(100)    NOT NULL,
  preco  NUMERIC(10,2)    NOT NULL
);

-- Relacionamento 1:N "USUARIO faz PEDIDO" → FK no lado N (pedidos)
CREATE TABLE pedidos (
  id          SERIAL    PRIMARY KEY,
  data        TIMESTAMP DEFAULT NOW(),
  usuario_id  INTEGER   NOT NULL REFERENCES usuarios(id)
);

-- Relacionamento N:M "PEDIDO contĂ©m PRODUTO" → tabela associativa
-- PK composta = (pedido_id, produto_id) — ambas FKs
CREATE TABLE pedido_produto (
  pedido_id   INTEGER NOT NULL REFERENCES pedidos(id),
  produto_id  INTEGER NOT NULL REFERENCES produtos(id),
  quantidade  INTEGER NOT NULL CHECK (quantidade > 0),
  PRIMARY KEY (pedido_id, produto_id)
);
Por que a PK composta na tabela associativa?

A combinação (pedido_id, produto_id) Ă© Ășnica por definição: o pedido 42 sĂł pode conter o produto 7 uma vez — se quiser duas unidades, isso vira quantidade = 2. Marcar a PK como composta impede acidentalmente inserir a mesma combinação duplicada e ainda cria o Ă­ndice composto que acelera buscas em ambas as direçÔes.

Normalização — organizando para evitar redundñncia

A normalização Ă© um processo de organizar as tabelas de um banco relacional para eliminar redundĂąncia e dependĂȘncias anĂŽmalas. Cada forma normal estabelece um conjunto de regras que a tabela deve obedecer. As trĂȘs primeiras sĂŁo as mais importantes na prĂĄtica:

1FN — Primeira Forma Normal

Regra: todos os atributos devem ser atĂŽmicos (sem listas ou grupos repetidos numa mesma coluna) e deve haver uma PK.
Exemplo de violação: coluna telefones com o valor "(11)9999-0001, (11)9999-0002" — dois valores numa coluna só.
Solução: criar uma tabela separada telefones(id, cliente_id, numero).

2FN — Segunda Forma Normal

Regra: a tabela deve estar em 1FN e todos os atributos nĂŁo-chave devem depender funcionalmente de toda a PK. Relevante quando a PK Ă© composta.
Exemplo de violação: tabela item_pedido(pedido_id, produto_id, nome_produto) — nome_produto depende só de produto_id, não de pedido_id.
Solução: mover nome_produto para a tabela produtos.

3FN — Terceira Forma Normal

Regra: a tabela deve estar em 2FN e nĂŁo deve haver dependĂȘncias transitivas (atributo nĂŁo-chave dependendo de outro atributo nĂŁo-chave).
Exemplo de violação: tabela pedidos(id, cliente_id, cidade_cliente, estado_cliente) — estado_cliente depende de cidade_cliente, que depende de cliente_id.
Solução: mover dados do cliente para a tabela clientes e referenciar por FK.

Desnormalização controlada

Em alguns casos de alta performance (relatĂłrios analĂ­ticos, data warehouses), intencionalmente desnormalizamos — repetimos dados — para evitar JOINs custosos em consultas de leitura. Essa Ă© uma decisĂŁo de trade-off consciente, documentada como RNF de Desempenho, e nĂŁo um erro de design. Normalize primeiro; desnormalize com evidĂȘncia de necessidade.

5. SQL — As 5 Sublinguagens

SQL (Structured Query Language) nĂŁo Ă© uma linguagem monolĂ­tica — ela Ă© composta por cinco sublinguagens, cada uma com um propĂłsito distinto. Essa organização existe porque diferentes papĂ©is interagem com o banco de maneiras diferentes: um DBA gerencia estrutura e permissĂ”es; um desenvolvedor escreve DML e DQL; um sistema de monitoramento opera transaçÔes via TCL. Entender as sublinguagens Ă© entender a separação de responsabilidades no SQL.

Cada sublinguagem opera em um nĂ­vel diferente de abstração. DDL opera no nĂ­vel do esquema — a estrutura que contĂ©m os dados. DML e DQL operam no nĂ­vel dos dados em si — as linhas dentro das tabelas. DCL opera no nĂ­vel das permissĂ”es — quem pode fazer o quĂȘ. TCL opera no nĂ­vel das transaçÔes — garantindo que grupos de operaçÔes sejam executados de forma atĂŽmica. Um profissional de banco de dados competente domina todas as cinco sublinguagens e sabe quando usar cada uma.

É importante notar que alguns comandos DDL (como TRUNCATE) e os comandos DCL tĂȘm efeito imediato e implĂ­cito de COMMIT em muitos SGBDs — ou seja, nĂŁo podem ser revertidos com ROLLBACK. JĂĄ os comandos DML fazem parte de transaçÔes e podem ser revertidos atĂ© o COMMIT ser executado. Essa diferença tem implicaçÔes prĂĄticas importantes: vocĂȘ pode corrigir um UPDATE errado com ROLLBACK, mas nĂŁo pode desfazer um DROP TABLE da mesma forma.

DDL
Data Definition Language
Define e altera a estrutura do banco: cria, modifica e remove tabelas, Ă­ndices e outros objetos. Comandos DDL tĂȘm efeito imediato e implicitamente fazem COMMIT.
CREATE · ALTER · DROP · TRUNCATE
DML
Data Manipulation Language
Manipula os dados dentro das estruturas existentes: insere, atualiza e deleta linhas. Faz parte de transaçÔes e pode ser revertido com ROLLBACK.
INSERT · UPDATE · DELETE · MERGE
DQL
Data Query Language
Consulta dados sem modificĂĄ-los. Alguns autores incluem SELECT dentro do DML, mas a separação Ă© didaticamente Ăștil: SELECT tem sintaxe prĂłpria e riquĂ­ssima.
SELECT
DCL
Data Control Language
Controla permissĂ”es de acesso: concede e revoga privilĂ©gios a usuĂĄrios e roles. Garante que cada usuĂĄrio acesse apenas o que precisa — princĂ­pio do menor privilĂ©gio.
GRANT · REVOKE
TCL
Transaction Control Language
Gerencia transaçÔes: delimita blocos de operaçÔes que devem ser executados de forma atÎmica. Se qualquer operação falhar, todas são revertidas.
BEGIN · COMMIT · ROLLBACK · SAVEPOINT

6. DDL — Criando e Alterando Estruturas

Os comandos DDL definem o esquema do banco de dados — a estrutura que contĂ©m os dados. O mais fundamental Ă© o CREATE TABLE, que cria uma nova tabela com suas colunas, tipos e constraints. Em PostgreSQL, cada coluna precisa de um tipo de dado que define o que pode ser armazenado nela: VARCHAR(n) para texto com limite, TEXT para texto sem limite, INTEGER e BIGINT para nĂșmeros inteiros, NUMERIC(p,s) para decimais precisos (use para dinheiro, nunca FLOAT), BOOLEAN para verdadeiro/falso, TIMESTAMP para datas e horas, e UUID para identificadores Ășnicos.

O comando ALTER TABLE modifica a estrutura de uma tabela existente — adiciona ou remove colunas, altera tipos, adiciona ou remove constraints. Em produção, operaçÔes de ALTER em tabelas grandes podem travar a tabela por longos perĂ­odos (lock), por isso existem estratĂ©gias como adicionar a nova coluna como nullable primeiro, popular os dados em background e depois adicionar a constraint NOT NULL. Compreender o impacto de um ALTER Ă© parte essencial do trabalho de um desenvolvedor de backend.

O comando DROP TABLE elimina uma tabela e todos os seus dados permanentemente. Em PostgreSQL, se a tabela tiver FKs referenciando ela de outras tabelas, vocĂȘ precisarĂĄ usar DROP TABLE nome CASCADE (que tambĂ©m deleta as FKs das tabelas dependentes) ou primeiro remover as FKs manualmente. TRUNCATE Ă© diferente: remove todas as linhas da tabela mas mantĂ©m a estrutura — e Ă© muito mais rĂĄpido que DELETE sem WHERE porque nĂŁo gera registros de undo linha a linha.

SQL — DDL: CREATE TABLE, ALTER TABLE, DROP TABLE
-- Cria a tabela de usuĂĄrios com tipos e constraints
CREATE TABLE usuarios (
  id         SERIAL       PRIMARY KEY,
  nome       VARCHAR(100) NOT NULL,
  email      VARCHAR(200) UNIQUE NOT NULL,
  ativo      BOOLEAN      DEFAULT TRUE,
  criado_em  TIMESTAMP    DEFAULT NOW()
);

-- Cria a tabela de pedidos referenciando usuarios
CREATE TABLE pedidos (
  id          SERIAL      PRIMARY KEY,
  cliente_id  INTEGER     NOT NULL REFERENCES usuarios(id),
  status      VARCHAR(20) NOT NULL DEFAULT 'pendente',
  criado_em   TIMESTAMP   DEFAULT NOW()
);

-- Adiciona coluna a tabela existente
ALTER TABLE usuarios ADD COLUMN telefone VARCHAR(20);

-- Remove tabela (irreversĂ­vel!)
DROP TABLE IF EXISTS pedidos;

7. Constraints — Garantindo a Integridade dos Dados

As constraints (restriçÔes) sĂŁo regras que o SGBD aplica automaticamente a cada operação de escrita para garantir que os dados permaneçam vĂĄlidos. Elas sĂŁo a primeira linha de defesa contra dados invĂĄlidos — anteriores Ă  validação na camada de aplicação. Se o SGBD rejeitar uma operação por violação de constraint, isso Ă© um comportamento correto: Ă© preferĂ­vel um erro explĂ­cito a dados silenciosamente incorretos no banco.

As constraints mais comuns em PostgreSQL sĂŁo: NOT NULL — a coluna nĂŁo pode ter valor nulo; UNIQUE — nenhuma duplicata Ă© permitida na coluna (ou combinação de colunas); DEFAULT — valor padrĂŁo caso nenhum seja fornecido na inserção; CHECK — expressĂŁo booleana que deve ser verdadeira para a linha ser aceita; PRIMARY KEY — combinação de NOT NULL e UNIQUE, define a PK da tabela; FOREIGN KEY — referĂȘncia Ă  PK de outra tabela, garante integridade referencial. Constraints podem ser definidas inline (junto Ă  coluna) ou como constraints de tabela (ao final do CREATE TABLE), o que permite constraints sobre mĂșltiplas colunas ao mesmo tempo.

Um detalhe importante: NULL Ă© diferente de zero ou string vazia — NULL significa ausĂȘncia de valor. Dois NULLs nĂŁo sĂŁo iguais entre si (NULL diferente de NULL em SQL). Isso tem implicaçÔes em consultas com WHERE coluna = NULL (que nunca retorna resultados — use WHERE coluna IS NULL) e no comportamento de constraints UNIQUE (em muitos SGBDs, mĂșltiplos NULLs sĂŁo permitidos mesmo com UNIQUE, porque NULL Ă© considerado diferente de NULL). PostgreSQL segue esse comportamento padrĂŁo do SQL ANSI.

SQL — Constraints em ação
CREATE TABLE produtos (
  id          SERIAL          PRIMARY KEY,
  nome        VARCHAR(150)     NOT NULL,
  sku         VARCHAR(50)      UNIQUE NOT NULL,
  preco       NUMERIC(10,2)    NOT NULL CHECK (preco > 0),
  estoque     INTEGER          NOT NULL DEFAULT 0
                                 CHECK (estoque >= 0),
  categoria   VARCHAR(50)      CHECK (categoria IN (
                                   'eletronico',
                                   'vestuario',
                                   'alimento'
                                 )),
  ativo       BOOLEAN          NOT NULL DEFAULT TRUE
);

-- Constraint de tabela: PK composta (tabela associativa N:M)
CREATE TABLE item_pedido (
  pedido_id   INTEGER NOT NULL REFERENCES pedidos(id) ON DELETE CASCADE,
  produto_id  INTEGER NOT NULL REFERENCES produtos(id),
  quantidade  INTEGER NOT NULL CHECK (quantidade > 0),
  preco_unit  NUMERIC(10,2) NOT NULL,
  PRIMARY KEY (pedido_id, produto_id)
);
Nunca use FLOAT para dinheiro

Tipos de ponto flutuante (FLOAT, DOUBLE PRECISION, REAL) tĂȘm representação binĂĄria que introduz erros de arredondamento. Para valores monetĂĄrios, use sempre NUMERIC(precision, scale) — por exemplo NUMERIC(15,2) para valores em reais com centavos. Esse Ă© um erro clĂĄssico que causa prejuĂ­zo real em sistemas financeiros.

8. DML — Manipulando Dados

Com a estrutura criada pelo DDL, passamos a manipular os dados com os comandos DML: INSERT, UPDATE e DELETE. Ao contrĂĄrio dos comandos DDL, os comandos DML fazem parte de transaçÔes e podem ser revertidos com ROLLBACK se algo der errado. Isso Ă© especialmente importante em operaçÔes que modificam mĂșltiplas tabelas relacionadas, como uma transferĂȘncia bancĂĄria ou um checkout de e-commerce.

O comando INSERT adiciona novas linhas a uma tabela. A forma bĂĄsica insere uma linha por vez; a forma multi-linha insere vĂĄrias linhas num Ășnico comando, o que Ă© muito mais eficiente porque reduz o nĂșmero de round-trips ao banco. PostgreSQL oferece a clĂĄusula RETURNING, que retorna os valores das colunas inseridas — incluindo o id gerado pelo SERIAL — sem precisar de uma segunda consulta. Isso elimina a necessidade de um SELECT MAX(id) (que seria incorreto em ambiente concorrente) ou uma segunda busca apĂłs o INSERT.

Os comandos UPDATE e DELETE sĂŁo poderosos e, portanto, perigosos sem a clĂĄusula WHERE. Um UPDATE usuarios SET ativo = FALSE sem WHERE desativa todos os usuĂĄrios. Um DELETE FROM pedidos sem WHERE apaga todos os pedidos permanentemente. Em PostgreSQL, vocĂȘ pode configurar a sessĂŁo para exigir WHERE em operaçÔes destrutivas, e muitas ferramentas como DBeaver e psql avisam antes de executar tais comandos. A regra prĂĄtica: antes de executar qualquer UPDATE ou DELETE, primeiro rode um SELECT com o mesmo WHERE para verificar quantas e quais linhas serĂŁo afetadas.

SQL — DML: INSERT, UPDATE, DELETE
-- INSERT bĂĄsico (uma linha)
INSERT INTO usuarios (nome, email)
VALUES ('Ana Silva', 'ana@email.com');

-- INSERT mĂșltiplo (mais eficiente)
INSERT INTO produtos (nome, sku, preco)
VALUES
  ('Camiseta Inteli', 'CAM-001', 59.90),
  ('Caderno A4',      'CAD-001', 24.90),
  ('Caneca Preta',    'CAN-001', 39.90);

-- INSERT com RETURNING (retorna o id gerado)
INSERT INTO pedidos (cliente_id, status)
VALUES (1, 'pendente')
RETURNING id, criado_em;

-- UPDATE com WHERE (sempre use WHERE!)
UPDATE usuarios
SET nome = 'Ana Costa', ativo = TRUE
WHERE id = 1;

-- DELETE com WHERE (sempre use WHERE!)
DELETE FROM usuarios
WHERE id = 1;
Nunca execute UPDATE ou DELETE sem WHERE em produção

Antes de qualquer UPDATE ou DELETE, rode primeiro o SELECT correspondente: SELECT * FROM usuarios WHERE id = 1. Confirme que as linhas retornadas sĂŁo exatamente as que vocĂȘ quer modificar. SĂł entĂŁo converta para UPDATE ou DELETE. Muitos acidentes em produção poderiam ser evitados com esse hĂĄbito simples.

9. DQL — Consultando Dados

O comando SELECT Ă©, de longe, o mais utilizado em um banco de dados — aplicaçÔes leem dados muito mais frequentemente do que escrevem. O SELECT tem uma sintaxe rica e um motor de execução sofisticado que permite desde buscas simples atĂ© anĂĄlises complexas com mĂșltiplas agregaçÔes, filtros e ordenaçÔes. Dominar o SELECT Ă© essencial para qualquer desenvolvedor backend.

A estrutura bĂĄsica de um SELECT Ă©: SELECT colunas FROM tabela WHERE condição ORDER BY coluna LIMIT n. O WHERE filtra linhas com base em condiçÔes booleanas — vocĂȘ pode combinar condiçÔes com AND, OR e NOT, usar operadores de comparação (=, <, >, <>), BETWEEN para intervalos, IN para listas de valores, LIKE para padrĂ”es de texto e IS NULL / IS NOT NULL para valores ausentes. O ORDER BY ordena o resultado por uma ou mais colunas em ordem ascendente (ASC, padrĂŁo) ou descendente (DESC). O LIMIT restringe o nĂșmero de linhas retornadas — crucial para paginação e para evitar retornar milhĂ”es de linhas acidentalmente em tabelas grandes.

As funçÔes de agregação calculam um Ășnico valor a partir de mĂșltiplas linhas: COUNT(*) conta o total de linhas, COUNT(coluna) conta linhas onde a coluna nĂŁo Ă© NULL, SUM soma valores numĂ©ricos, AVG calcula a mĂ©dia aritmĂ©tica, MIN e MAX retornam o menor e o maior valor. FunçÔes de agregação normalmente sĂŁo usadas junto com GROUP BY, que agrupa as linhas por uma ou mais colunas antes de aplicar a função. O HAVING filtra grupos (assim como WHERE filtra linhas individuais — HAVING sĂł pode ser usado com GROUP BY).

SQL — DQL: SELECT com filtros, ordenação e agregaçÔes
-- SELECT bĂĄsico com WHERE, ORDER BY e LIMIT
SELECT nome, email
FROM usuarios
WHERE ativo = TRUE
  AND criado_em > '2024-01-01'
ORDER BY nome ASC
LIMIT 10;

-- DISTINCT: remove duplicatas no resultado
SELECT DISTINCT status
FROM pedidos;

-- FunçÔes de agregação
SELECT
  COUNT(*) AS total_pedidos,
  SUM(preco_unit * quantidade) AS receita_total,
  AVG(preco_unit) AS ticket_medio,
  MIN(criado_em) AS primeiro_pedido,
  MAX(criado_em) AS ultimo_pedido
FROM pedidos
WHERE status = 'confirmado';

-- GROUP BY com HAVING: agrupa e filtra grupos
SELECT status, COUNT(*) AS qtd
FROM pedidos
GROUP BY status
HAVING COUNT(*) > 5
ORDER BY qtd DESC;

Aprofundamento: LIKE, ILIKE e padrÔes de texto

O operador LIKE realiza busca por padrĂŁo em strings. O caractere % representa qualquer sequĂȘncia de caracteres (incluindo nenhum), e _ representa exatamente um caractere. Exemplos:

  • WHERE nome LIKE 'Ana%' — começa com "Ana"
  • WHERE email LIKE '%@inteli.edu.br' — termina com o domĂ­nio
  • WHERE nome LIKE '%Silva%' — contĂ©m "Silva" em qualquer posição
  • WHERE nome LIKE 'A__' — começa com A e tem exatamente 3 caracteres

Para busca case-insensitive, use ILIKE (especĂ­fico do PostgreSQL). Para buscas mais sofisticadas de texto completo (full-text search), PostgreSQL possui o operador @@ com vetores tsvector e queries tsquery — muito mais poderoso que LIKE para conteĂșdo extenso.

LIMIT e paginação

Para paginação, combine LIMIT e OFFSET: LIMIT 20 OFFSET 40 retorna as linhas 41 a 60 (pĂĄgina 3 com 20 itens por pĂĄgina). Mas em tabelas muito grandes, OFFSET alto Ă© lento — o banco ainda precisa processar e descartar as primeiras N linhas. Para paginação de alta performance, prefira a tĂ©cnica de "keyset pagination" (cursor pagination) usando a PK como referĂȘncia da Ășltima linha vista.

10. DCL e TCL — Controle de Acesso e TransaçÔes

Os comandos DCL controlam quem pode fazer o quĂȘ no banco de dados. GRANT concede privilĂ©gios a usuĂĄrios ou roles; REVOKE remove privilĂ©gios. Os privilĂ©gios podem ser granulares: SELECT, INSERT, UPDATE, DELETE, REFERENCES (para criar FKs). O princĂ­pio do menor privilĂ©gio diz que cada usuĂĄrio ou aplicação deve ter apenas os privilĂ©gios mĂ­nimos necessĂĄrios para sua função. Uma API que sĂł lĂȘ dados deve ter apenas SELECT; uma API que escreve deve ter SELECT, INSERT, UPDATE, DELETE nas tabelas relevantes — mas nunca DROP TABLE ou acesso ao schema de sistema.

Os comandos TCL controlam transaçÔes. Uma transação Ă© um grupo de operaçÔes que deve ser executado de forma atĂŽmica: ou todas tĂȘm sucesso, ou nenhuma Ă© persistida. BEGIN inicia a transação; COMMIT persiste todas as mudanças; ROLLBACK desfaz tudo desde o BEGIN. O exemplo clĂĄssico Ă© a transferĂȘncia bancĂĄria: vocĂȘ precisa debitar de uma conta E creditar em outra — se o crĂ©dito falhar apĂłs o dĂ©bito ter sido realizado, o dinheiro simplesmente desapareceria. A transação garante que isso nĂŁo aconteça.

As transaçÔes em bancos relacionais seguem as propriedades ACID: Atomicidade — a transação Ă© indivisĂ­vel (tudo ou nada); ConsistĂȘncia — a transação leva o banco de um estado vĂĄlido a outro estado vĂĄlido, respeitando todas as constraints; Isolamento — transaçÔes concorrentes nĂŁo interferem entre si (o nĂ­vel de isolamento pode ser configurado); Durabilidade — apĂłs o COMMIT, os dados sĂŁo persistidos mesmo em caso de falha de hardware (o SGBD escreve em um WAL — Write-Ahead Log — antes de qualquer outra coisa).

SQL — DCL: GRANT/REVOKE e TCL: BEGIN/COMMIT/ROLLBACK
-- DCL: conceder e revogar privilégios
GRANT SELECT ON usuarios TO leitor;
GRANT SELECT, INSERT, UPDATE, DELETE ON pedidos TO api_app;
REVOKE DELETE ON usuarios FROM api_app;

-- TCL: transferĂȘncia bancĂĄria atĂŽmica
BEGIN;

UPDATE contas
SET saldo = saldo - 100.00
WHERE id = 1 AND saldo >= 100.00;

UPDATE contas
SET saldo = saldo + 100.00
WHERE id = 2;

-- Se tudo correu bem, persiste as mudanças:
COMMIT;

-- Se algo deu errado, desfaz tudo:
-- ROLLBACK;
Propriedade ACIDO que garanteMecanismo no PostgreSQL
AtomicidadeTudo ou nada — sem estados parciaisWrite-Ahead Log (WAL) + ROLLBACK automático em erro
ConsistĂȘnciaConstraints sempre respeitadasVerificação de constraints em cada operação de escrita
IsolamentoTransaçÔes nĂŁo se veem mutuamente atĂ© COMMITMVCC — Multi-Version Concurrency Control
DurabilidadeCOMMIT persiste mesmo apĂłs falha de hardwareWAL escrito em disco antes do COMMIT retornar

11. Comparativo entre SGBDs Relacionais

Embora todos os SGBDs relacionais sigam o padrĂŁo SQL ANSI, cada um implementa extensĂ”es e dialetos prĂłprios. Quando vocĂȘ se acostuma com um SGBD e migra para outro, os primeiros tropeços sĂŁo quase sempre nos detalhes de DDL: como declarar uma chave auto-incremental, como tipar texto Unicode, como armazenar JSON. Esta seção lado a lado existe para deixar claro que o conceito (PK auto-incremental, texto, booleano, data) Ă© universal, mas a sintaxe muda. Reconhecer essas diferenças torna vocĂȘ capaz de ler cĂłdigo de qualquer projeto sem entrar em pĂąnico.

RecursoPostgreSQLMySQL / MariaDBSQLiteSQL Server (T-SQL)Oracle
PK auto-incremental SERIAL ou GENERATED AS IDENTITY INT AUTO_INCREMENT INTEGER PRIMARY KEY AUTOINCREMENT INT IDENTITY(1,1) NUMBER GENERATED ALWAYS AS IDENTITY
Texto curto VARCHAR(n) / TEXT VARCHAR(n) TEXT (tipagem dinĂąmica) NVARCHAR(n) (Unicode) VARCHAR2(n)
Booleano BOOLEAN TINYINT(1) INTEGER (0/1) BIT não tem — usa NUMBER(1)
Data & hora padrĂŁo TIMESTAMP DEFAULT NOW() DATETIME DEFAULT CURRENT_TIMESTAMP TEXT DEFAULT CURRENT_TIMESTAMP DATETIME2 DEFAULT GETDATE() TIMESTAMP DEFAULT SYSTIMESTAMP
JSON JSONB (binårio, indexåvel) JSON TEXT + extensão JSON1 NVARCHAR(MAX) + funçÔes JSON_VALUE CLOB CHECK (... IS JSON)
Engine de armazenamento Único (heap + WAL + MVCC) InnoDB (FK, transaçÔes) ou MyISAM (sem FK) B-tree Ășnico embutido Único (rowstore + columnstore opcional) Único (multi-tenant CDB/PDB)
Quando escolher SaaS modernos, dados complexos, måxima conformidade SQL Web apps clåssicos, hospedagem PHP, ecossistema WordPress Apps mobile/desktop, protótipos, banco embarcado Empresas Microsoft, Power BI, integração com .NET Bancos, telecom, sistemas legados de missão crítica
Comparativo prĂĄtico: o "mesmo" CREATE TABLE em 5 SGBDs
-- ═══ PostgreSQL 16 ═══
CREATE TABLE usuarios (
  id         SERIAL       PRIMARY KEY,
  nome       VARCHAR(100) NOT NULL,
  email      VARCHAR(200) UNIQUE NOT NULL,
  ativo      BOOLEAN      DEFAULT TRUE,
  metadata   JSONB,
  criado_em  TIMESTAMP    DEFAULT NOW()
);

-- ═══ MySQL 8 / MariaDB ═══
CREATE TABLE usuarios (
  id         INT           AUTO_INCREMENT PRIMARY KEY,
  nome       VARCHAR(100)  NOT NULL,
  email      VARCHAR(200)  NOT NULL UNIQUE,
  ativo      TINYINT(1)    DEFAULT 1,
  metadata   JSON,
  criado_em  DATETIME      DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ═══ SQLite 3 ═══
CREATE TABLE usuarios (
  id         INTEGER       PRIMARY KEY AUTOINCREMENT,
  nome       TEXT          NOT NULL,
  email      TEXT          NOT NULL UNIQUE,
  ativo      INTEGER       DEFAULT 1,
  metadata   TEXT,                       -- JSON via JSON1
  criado_em  TEXT          DEFAULT CURRENT_TIMESTAMP
);

-- ═══ SQL Server 2022 (T-SQL) ═══
CREATE TABLE usuarios (
  id         INT            IDENTITY(1,1) PRIMARY KEY,
  nome       NVARCHAR(100) NOT NULL,
  email      NVARCHAR(200) NOT NULL UNIQUE,
  ativo      BIT            DEFAULT 1,
  metadata   NVARCHAR(MAX),
  criado_em  DATETIME2      DEFAULT GETDATE()
);

-- ═══ Oracle 23ai ═══
CREATE TABLE usuarios (
  id         NUMBER         GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  nome       VARCHAR2(100) NOT NULL,
  email      VARCHAR2(200) NOT NULL UNIQUE,
  ativo      NUMBER(1)      DEFAULT 1,
  metadata   CLOB           CHECK (metadata IS JSON),
  criado_em  TIMESTAMP      DEFAULT SYSTIMESTAMP
);
Padronizar com camadas de abstração?

Frameworks ORM (Sequelize, TypeORM, Prisma, Hibernate) e query builders (Knex.js, jOOQ) escondem essas diferenças sintĂĄticas. Eles sĂŁo Ășteis em projetos que precisam ser portĂĄveis entre SGBDs — mas custam em performance e em controle fino. Em projetos onde o SGBD Ă© uma decisĂŁo de arquitetura estĂĄvel, escrever SQL puro do dialeto escolhido costuma ser mais legĂ­vel e mais auditĂĄvel. NĂŁo hĂĄ resposta universal: avalie seu contexto.

12. RM-ODP — Viewpoint Information

O RM-ODP (Reference Model for Open Distributed Processing, ISO/IEC 10746) estrutura a descrição de sistemas distribuídos em cinco viewpoints (visÔes). Cada visão captura os interesses de um grupo específico de stakeholders, usando uma linguagem e nível de abstração adequados a esses interesses. As cinco visÔes são: Enterprise (propósito e regras de negócio), Information (estrutura e fluxo de dados), Computational (decomposição funcional em componentes), Engineering (distribuição e comunicação) e Technology (escolhas concretas de tecnologia).

Esta aula foca no Viewpoint Information — a visĂŁo de informação. Esse viewpoint descreve como a informação Ă© estruturada, como muda ao longo do tempo e quais invariantes (regras permanentes) ela deve obedecer. No contexto de banco de dados, o viewpoint de informação se traduz diretamente no modelo ER e no esquema relacional: as entidades sĂŁo os objetos de informação, os atributos sĂŁo suas propriedades, os relacionamentos sĂŁo as associaçÔes entre eles, e as constraints sĂŁo os invariantes que o sistema deve preservar em toda operação.

Quando vocĂȘ escreve um diagrama ER, vocĂȘ estĂĄ produzindo a visĂŁo de informação do sistema. Quando vocĂȘ define as constraints na DDL (NOT NULL, UNIQUE, CHECK, FOREIGN KEY), vocĂȘ estĂĄ codificando os invariantes de informação diretamente no SGBD. Isso Ă© poderoso: as regras de negĂłcio relacionadas Ă  estrutura de dados ficam centralizadas no banco, nĂŁo espalhadas pela lĂłgica da aplicação onde podem ser esquecidas ou inconsistentes entre diferentes endpoints da API.

🏢
Enterprise (Empresarial)
PropĂłsito, escopo e regras de negĂłcio. Quem sĂŁo os stakeholders? Qual o objetivo do sistema? Quais processos de negĂłcio ele suporta?
Aula 1 — Minimundo, RF e RNF iniciais
📋
Information (Informação) — FOCO DESTA AULA
Estrutura, invariantes e fluxo da informação. Entidades, atributos, relacionamentos, cardinalidades e constraints. O modelo ER e o esquema SQL pertencem a esta visão.
Aulas 2, 3, 4 — Modelagem ER, SQL, JOINs
⚙️
Computational (Computacional)
Decomposição em componentes com interfaces: Models, Controllers, Services, rotas. Arquitetura MVC e contratos de API.
Aulas 5, 6 — Back-end, MVC, Endpoints
🔧
Engineering (Engenharia)
Distribuição física: nós, canais, protocolos, binding. Como cliente, servidor e banco se comunicam em tempo de execução.
Aulas 7, 8, 10 — Front-end, fetch, Testes
💻
Technology (Tecnologia)
Escolhas concretas: PostgreSQL 16, Node.js 20, Express 4. VersĂ”es, padrĂ”es de interoperabilidade e dependĂȘncias explĂ­citas.
Aulas 9, 11 — CSS, Redes, Deploy
Viewpoint Information na documentação do projeto

Na documentação do seu projeto Inteli, a seção de viewpoint Information deve conter: o diagrama ER completo, a descrição de cada entidade e seus atributos, a justificativa das cardinalidades dos relacionamentos, e a listagem de invariantes (constraints) críticos. Isso demonstra que a modelagem foi pensada antes da implementação — e não descoberta durante o código.

13. RF, RN e RNF aplicados a Banco de Dados

Toda funcionalidade que precisa persistir dados possui Requisitos Funcionais (RF) que dependem do banco de dados. Identificar essa dependĂȘncia Ă© o primeiro passo para modelar corretamente. Um RF como "o usuĂĄrio deve poder visualizar seu histĂłrico de pedidos" implica que os pedidos precisam ser armazenados com referĂȘncia ao usuĂĄrio, com data, status e itens — e que a consulta deve ser eficiente o suficiente para retornar em tempo aceitĂĄvel mesmo com milhares de pedidos por usuĂĄrio. Esse RF, ao ser implementado, exige decisĂ”es de modelagem (quais tabelas, quais colunas), de DDL (tipos e constraints) e de DQL (qual SELECT e quais Ă­ndices).

As Regras de NegĂłcio (RN) que envolvem dados frequentemente se traduzem em constraints no banco. "Um produto nĂŁo pode ter estoque negativo" vira CHECK (estoque >= 0). "Um email de usuĂĄrio deve ser Ășnico no sistema" vira UNIQUE NOT NULL. "Um pedido sĂł pode ter status 'confirmado', 'pendente' ou 'cancelado'" vira um CHECK (status IN (...)). Quando a RN Ă© simples o suficiente para ser expressa como constraint SQL, prefira o banco Ă  aplicação — o banco a aplicarĂĄ em todo acesso, de qualquer origem, incluindo scripts de manutenção e migraçÔes.

Os Requisitos Não Funcionais (RNF) mais diretamente impactados pelo banco de dados são os de Confiabilidade, Desempenho, Segurança e Suportabilidade. A escolha de usar transaçÔes ACID (TCL) é uma decisão de RNF de Confiabilidade. A criação de índices para acelerar consultas frequentes é um RNF de Desempenho. O uso de roles com menor privilégio (DCL) é um RNF de Segurança. A estruturação das migraçÔes de banco com ferramentas como Flyway ou Knex é um RNF de Suportabilidade que garante que o esquema possa evoluir de forma controlada e rastreåvel.

Os 8 eixos de RNF relevantes para Banco de Dados

CONF
Confiabilidade
O banco garante consistĂȘncia e durabilidade dos dados?
"Toda transferĂȘncia financeira ocorre em transação ACID com rollback automĂĄtico em caso de erro."
DESEMP
Desempenho
Consultas retornam dentro do tempo aceitĂĄvel sob carga real?
"Busca de pedidos por cliente_id retorna em menos de 50ms com até 1 milhão de linhas (índice em cliente_id)."
SEG
Segurança
Apenas usuĂĄrios autorizados acessam dados sensĂ­veis?
"API usa role db_api com SELECT/INSERT/UPDATE apenas; nenhum acesso a tabelas de auditoria ou schema pg_catalog."
SUPORT
Suportabilidade
O banco pode ser evoluĂ­do sem downtime ou perda de dados?
"AlteraçÔes de schema são feitas via migrations versionadas com rollback. Zero downtime com adição de colunas nullable."
INT
Integridade de Dados
O banco rejeita dados invĂĄlidos antes de persistir?
"Todas as FKs tĂȘm constraint declarada. Campos obrigatĂłrios tĂȘm NOT NULL. Valores monetĂĄrios usam NUMERIC(15,2)."
ESCAL
Escalabilidade
O banco suporta crescimento de dados e usuårios sem refatoração?
"Esquema normalizado em 3FN. Índices compostos para as queries mais frequentes. Particionamento planejado para logs."
DISP
Disponibilidade
O banco fica disponível mesmo sob manutenção ou falha?
"Backup automåtico diårio com retenção de 7 dias. Réplica de leitura para relatórios. RTO de 1h documentado."
AUDIT
Auditabilidade
É possĂ­vel rastrear quem fez o quĂȘ e quando?
"Tabela de auditoria registra INSERT/UPDATE/DELETE via triggers. Campos criado_em e atualizado_em em todas as entidades."

14. Prática Hands-on — Crie sua primeira tabela no Supabase

Toda a teoria deste material sĂł vira competĂȘncia real quando vocĂȘ executa SQL contra um banco de dados de verdade. Esta seção propĂ”e uma prĂĄtica curta (~10 min) usando o Supabase — uma plataforma cloud que oferece PostgreSQL gerenciado com SQL Editor embutido no navegador. VocĂȘ vai modelar uma entidade pequena do projeto e ver, no Table Editor, a tabela aparecer com os tipos e constraints que escreveu.

Por que Supabase?

Supabase Ă© PostgreSQL puro, sem dialeto prĂłprio. Tudo que vocĂȘ aprende lĂĄ funciona em qualquer PostgreSQL self-hosted, RDS ou Cloud SQL. A interface elimina o atrito de instalação local — basta um login com GitHub/Google e vocĂȘ estĂĄ dentro de um SQL Editor totalmente funcional, com autocomplete, execução por Ctrl+Enter e o resultado aparecendo lado a lado.

Passo a passo

  1. Acesse supabase.com e faça login (GitHub, Google ou e-mail).
  2. Crie um projeto novo ou abra o projeto da sua squad. Anote a senha do banco de dados — Supabase só mostra uma vez.
  3. Abra o SQL Editor no menu lateral (Ă­cone </>).
  4. Identifique uma entidade pequena do problema que sua dupla está modelando — algo como cliente, agendamento, tarefa ou produto. Não precisa modelar o domínio inteiro.
  5. Modele 3 a 5 colunas: uma PK, dois ou trĂȘs campos descritivos e ao menos uma constraint Ăștil (UNIQUE, NOT NULL ou CHECK).
  6. Escreva o CREATE TABLE em PostgreSQL no editor.
  7. Execute com Ctrl+Enter (ou clique em Run). VocĂȘ deve ver "Success. No rows returned." se tudo deu certo.
  8. Confirme em Table Editor (Ă­cone de tabela no menu lateral) que a tabela apareceu com as colunas e tipos corretos.
  9. BĂŽnus: insira uma linha com INSERT INTO ... e rode SELECT * FROM ... para ver o registro aparecer.
SQL — exemplo de referĂȘncia (ajuste para a entidade do seu projeto)
-- Exemplo: tabela de clientes para uma loja universitĂĄria
CREATE TABLE clientes (
  id         SERIAL       PRIMARY KEY,
  nome       VARCHAR(120) NOT NULL,
  email      VARCHAR(200) UNIQUE NOT NULL,
  curso      VARCHAR(50)  CHECK (curso IN ('CC', 'EC', 'SI', 'ES', 'AT')),
  criado_em  TIMESTAMP    DEFAULT NOW()
);

-- BĂŽnus: insere uma linha e consulta o resultado
INSERT INTO clientes (nome, email, curso)
VALUES ('Ana Lima', 'ana@inteli.edu.br', 'SI')
RETURNING id, nome, criado_em;

SELECT * FROM clientes;

Critério de sucesso

  • ✅ A tabela aparece no Table Editor com as colunas e tipos esperados.
  • ✅ A constraint UNIQUE bloqueia uma segunda inserção com o mesmo email (teste e veja o erro do PostgreSQL).
  • ✅ A constraint CHECK rejeita um valor de curso fora da lista permitida.
  • ✅ VocĂȘ consegue explicar para sua dupla, em uma frase, por que cada constraint foi escolhida.
Erros mais comuns

Senha do banco esquecida: dá para resetar em Project Settings → Database, mas isso desconecta clientes existentes — fique atento.
Tabela duplicada: use CREATE TABLE IF NOT EXISTS ou rode DROP TABLE clientes; antes do CREATE para reexecutar o script sem erro.
Schema "public": Supabase coloca tudo em public por padrĂŁo — nĂŁo Ă© problema, mas em produção real vocĂȘ organizaria por schema (auth, billing, etc.).

15. Checklist de Estudo

Clique nos itens Ă  medida que vocĂȘ dominar cada conceito:

  • Consigo explicar a diferença entre banco de dados e SGBD, e citar exemplos de cada categoria.
  • Consigo desenhar um diagrama ER com entidades, atributos, relacionamentos e cardinalidades.
  • Consigo identificar quando um relacionamento Ă© 1:1, 1:N ou N:M e o que cada um implica em termos de tabelas.
  • Consigo explicar o papel da PK e da FK e o que Ă© integridade referencial.
  • Consigo descrever as 3 primeiras formas normais com exemplos de violação e de solução para cada uma.
  • Consigo nomear as 5 sublinguagens SQL e citar ao menos um comando de cada.
  • Consigo escrever um CREATE TABLE com tipos corretos e ao menos 4 tipos de constraint diferentes.
  • Consigo escrever INSERT (simples e mĂșltiplo com RETURNING), UPDATE e DELETE com WHERE corretos.
  • Consigo escrever um SELECT com WHERE, ORDER BY, LIMIT e pelo menos uma função de agregação com GROUP BY.
  • Consigo explicar as 4 propriedades ACID e dar um exemplo concreto de por que cada uma Ă© necessĂĄria.
  • Consigo escrever um bloco BEGIN/COMMIT/ROLLBACK para uma operação atĂŽmica envolvendo duas tabelas.
  • Consigo relacionar o Viewpoint Information do RM-ODP com o diagrama ER e as constraints SQL.
  • Consigo mapear RFs do sistema para entidades de banco e RNs para constraints SQL.
  • Consigo redigir RNFs de Confiabilidade, Desempenho e Segurança especĂ­ficos para banco de dados, com mĂ©tricas mensurĂĄveis.
  • Consigo aplicar as 4 regras de tradução ER → tabelas (entidade → tabela; 1:1 → FK Ășnica; 1:N → FK no lado N; N:M → tabela associativa com PK composta).
  • Consigo desenhar um diagrama ER usando a notação de Chen (retĂąngulo, losango, oval) e identificar quando o losango precisa do retĂąngulo tracejado em volta para sinalizar N:M com atributos.
  • Consigo reconhecer pelo menos 3 diferenças sintĂĄticas entre PostgreSQL, MySQL, SQLite, SQL Server e Oracle (PK auto-incremental, booleano, JSON).
  • Criei uma tabela no Supabase com PK, ao menos uma constraint Ăștil, e validei o resultado no Table Editor.

ReferĂȘncias

Inteli Logo