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.
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:
| Sistema | Dados persistidos | OperaçÔes crĂticas |
|---|---|---|
| Perfis, fotos, seguidores, curtidas, stories, mensagens | Feed personalizado, busca por hashtag, notificaçÔes em tempo real | |
| Banco digital | Contas, transaçÔes, saldos, limites, extratos, investimentos | TransferĂȘncia atĂŽmica, detecção de fraude, extrato por perĂodo |
| E-commerce | Produtos, estoque, pedidos, clientes, endereços, pagamentos | Reserva de estoque, cålculo de frete, histórico de pedidos |
| Spotify | MĂșsicas, artistas, playlists, histĂłrico de escuta, preferĂȘncias | Recomendaçã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.
| Etapa | Tecnologia | Limitação superada | Limitação remanescente |
|---|---|---|---|
| đ Arquivo de texto | .txt, .csv, logs em disco | PersistĂȘncia simples â os dados sobrevivem ao desligamento | Sem estrutura, sem Ăndices, sem concorrĂȘncia, sem integridade |
| đ Planilha | Excel, Google Sheets | Estrutura tabular, fĂłrmulas, filtros, ordenação | Limite prĂĄtico de ~1M linhas, edição manual, sem concorrĂȘncia confiĂĄvel, sem garantias ACID |
| đ BD relacional | PostgreSQL, MySQL, Oracle | SQL declarativo, transaçÔes ACID, integridade, milhĂ”es de linhas, mĂșltiplos usuĂĄrios simultĂąneos | Escala vertical, esquema rĂgido, custo de JOINs em escala extrema |
| âïž Banco em cloud | Supabase, RDS, Cloud SQL, Aurora | Escala horizontal, alta disponibilidade, replicação geogrĂĄfica, backups automĂĄticos | Custo proporcional ao uso, dependĂȘncia do provedor, latĂȘncia por regiĂŁo |
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.
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ĂĄgio | O que faz | SaĂda |
|---|---|---|
| 1. Parser | LĂȘ o texto SQL, valida sintaxe e converte em uma ĂĄrvore de anĂĄlise (AST). | Erro de sintaxe ou ĂĄrvore vĂĄlida |
| 2. Analyzer / Rewriter | Resolve nomes de tabelas e colunas, aplica regras (views, RLS), checa permissÔes DCL. | Plano lógico |
| 3. Planner / Optimizer | Avalia 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. Executor | Executa 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 layer | LĂȘ 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.
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:
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Ămbolo | Representa | Categoria gramatical | Exemplo |
|---|---|---|---|
| â RetĂąngulo | Entidade | Substantivo | USUARIO, PEDIDO, PRODUTO |
| â Losango | Relacionamento | Verbo | faz, contĂ©m, pertence a |
| ⯠Elipse / oval | Atributo | Adjetivo / propriedade | nome, email, preço |
| ⯠sublinhada | Atributo identificador (PK) | Identificador Ășnico | id |
| â linha | ConexĂŁo entre entidade e relacionamento, ou entidade e atributo | Predicação | rotulada com cardinalidade 1, N ou 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.
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?"
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?"
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)?"
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 ER | Tradução para o modelo relacional | Exemplo |
|---|---|---|
| Entidade | Vira uma tabela com mesmo nome (no plural, em snake_case). | USUARIO â tabela usuarios |
| Atributo | Vira uma coluna com tipo apropriado. O atributo identificador vira PRIMARY KEY. | email â coluna email VARCHAR(200) |
| Relacionamento 1:1 | Vira 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:N | Vira 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:M | Vira 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) |
-- 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)
);
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:
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).
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.
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.
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.
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.
-- 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.
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)
);
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.
-- 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;
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).
-- 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ĂnioWHERE nome LIKE '%Silva%'â contĂ©m "Silva" em qualquer posiçãoWHERE 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.
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).
-- 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 ACID | O que garante | Mecanismo no PostgreSQL |
|---|---|---|
| Atomicidade | Tudo ou nada â sem estados parciais | Write-Ahead Log (WAL) + ROLLBACK automĂĄtico em erro |
| ConsistĂȘncia | Constraints sempre respeitadas | Verificação de constraints em cada operação de escrita |
| Isolamento | TransaçÔes nĂŁo se veem mutuamente atĂ© COMMIT | MVCC â Multi-Version Concurrency Control |
| Durabilidade | COMMIT persiste mesmo apĂłs falha de hardware | WAL 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.
| Recurso | PostgreSQL | MySQL / MariaDB | SQLite | SQL 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 |
-- âââ 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
);
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.
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
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.
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
- Acesse supabase.com e faça login (GitHub, Google ou e-mail).
- Crie um projeto novo ou abra o projeto da sua squad. Anote a senha do banco de dados â Supabase sĂł mostra uma vez.
- Abra o SQL Editor no menu lateral (Ăcone
</>). - Identifique uma entidade pequena do problema que sua dupla estĂĄ modelando â algo como
cliente,agendamento,tarefaouproduto. NĂŁo precisa modelar o domĂnio inteiro. - Modele 3 a 5 colunas: uma PK, dois ou trĂȘs campos descritivos e ao menos uma constraint Ăștil (
UNIQUE,NOT NULLouCHECK). - Escreva o
CREATE TABLEem PostgreSQL no editor. - Execute com Ctrl+Enter (ou clique em Run). VocĂȘ deve ver "Success. No rows returned." se tudo deu certo.
- Confirme em Table Editor (Ăcone de tabela no menu lateral) que a tabela apareceu com as colunas e tipos corretos.
- BĂŽnus: insira uma linha com
INSERT INTO ...e rodeSELECT * FROM ...para ver o registro aparecer.
-- 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
UNIQUEbloqueia uma segunda inserção com o mesmo email (teste e veja o erro do PostgreSQL). - â
A constraint
CHECKrejeita um valor de curso fora da lista permitida. - â VocĂȘ consegue explicar para sua dupla, em uma frase, por que cada constraint foi escolhida.
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
- PostgreSQL Documentation â documentação oficial completa do PostgreSQL
- PostgreSQL â CREATE TABLE â referĂȘncia completa de sintaxe DDL e constraints
- PostgreSQL â Transaction Isolation â nĂveis de isolamento e propriedades ACID
- ISO/IEC 10746 â RM-ODP â especificação do Reference Model for Open Distributed Processing
- ISO/IEC 25010 â SQuaRE Quality Model â modelo de qualidade com os eixos de RNF
- E.F. Codd â A Relational Model of Data for Large Shared Data Banks (1970) â artigo original do modelo relacional
- Peter Chen â The Entity-Relationship Model (1976) â artigo original do modelo ER
- Ramakrishnan & Gehrke â Database Management Systems, 3ÂȘ ed.