🏗️ CAPÍTULO 11: ECOSSISTEMA SQL E DDL
🎯 Objetivos de Aprendizagem
Ao final deste capítulo (estimativa: 2 horas de estudo autoguiado), você será capaz de:
- 🔹 Compreender as 5 famílias de comandos SQL: DDL (Definição), DML (Manipulação), DQL (Consulta), DCL (Controle) e TCL (Transação).
- 🔹 Dominar a criação e gestão de Schemas (Namespaces) e tabelas com
CREATE TABLE,ALTER TABLEeDROP TABLE. - 🔹 Diferenciar a execução declarativa do SQL (otimizador de consultas) da programação procedural tradicional.
- 🔹 Implementar inspeção e criação programática de schemas (metadados) com SQLAlchemy 2.0. (Migrações versionadas com Alembic são o foco do Capítulo 17.)
A primeira ideia que define um desenvolvedor experiente é entender que a SQL (Structured Query Language) não é apenas uma ferramenta, mas uma linguagem declarativa de escala global, capaz de gerenciar desde pequenos aplicativos até a bolsa de valores. 🛡️🧩
🏢 O Cenário Prático (Seu Desafio)
A TecProExpress decidiu criar um módulo de "Agenda de Contatos" para os fornecedores logísticos. Os analistas desenharam o MER, mas o banco de dados ainda está vazio.
"Seu desafio é abrir o terminal (ou a interface DBeaver/pgAdmin) e usar a linguagem SQL para construir as fundações do prédio: criar o espaço de trabalho (Schema) e a tabela que armazenará os fornecedores, com regras rígidas."
🧠 Fundamentos: As 5 Famílias da SQL
A SQL é dividida em 5 subconjuntos. Todo o nosso trabalho até agora na criação de tabelas pertenceu ao primeiro grupo.
| Sigla | Significado | Comandos Principais | O que faz? |
|---|---|---|---|
| DDL | Data Definition Language | CREATE, ALTER, DROP | Monta o "esqueleto" do banco. |
| DML | Data Manipulation Language | INSERT, UPDATE, DELETE | Manipula os "órgãos" (dados). |
| DQL | Data Query Language | SELECT | Faz as consultas e relatórios. |
| DCL | Data Control Language | GRANT, REVOKE | Segurança (Dá e tira permissão). |
| TCL | Transaction Control Language | COMMIT, ROLLBACK | Salva ou Cancela um lote de ações. |
📊 Fluxo de Processamento Declarativo
Diferente do Java ou Python (onde você diz como fazer o laço de repetição), a SQL é Declarativa. Você diz o que quer, e o SGBD se vira para otimizar.
flowchart LR
A["📜 Declaração SQL"] --> B{"⚙️ Otimizador SGBD"}
B -- "Calcula a Rota" --> C["🗺️ Plano de Execução"]
C --> D["📊 Resultado Final"]
📖 Exemplo Guiado: O DDL em Ação (Criando a Base)
Sempre organize seus projetos criando um SCHEMA. Ele funciona como uma "pasta" dentro do banco de dados, evitando que as tabelas da logística se misturem com as do RH.
🛠️ Código do Exemplo
-- PASSO 1: DDL (Criação do Namespace/Schema)
CREATE SCHEMA logistica;
-- PASSO 2: DDL (Criação da Tabela com Constraints Base)
CREATE TABLE logistica.fornecedor (
id INT PRIMARY KEY,
nome_fantasia VARCHAR(100) NOT NULL,
cnpj CHAR(14) UNIQUE
);
-- PASSO 3: DDL (Evoluindo a tabela - ALTER)
ALTER TABLE logistica.fornecedor ADD COLUMN email VARCHAR(100);
-- PASSO 4: DML (Carga Inicial)
INSERT INTO logistica.fornecedor (id, nome_fantasia, cnpj, email)
VALUES (1, 'Baterias Moura', '12345678901234', 'contato@moura.com');
🔍 Detalhamento do Código:
CREATE SCHEMA logistica;: Cria a área de trabalho. No Postgres, isso cria uma divisão lógica no mesmo banco. (Nota: No MySQL, Schema e Database são sinônimos).logistica.fornecedor: Boa prática! Sempre referenciamos a tabela pelo nome do schema seguido de um ponto.ALTER TABLE ... ADD COLUMN: A vida real muda! O comando ALTER permite colocar uma nova coluna (email) sem ter que apagar (DROP) a tabela e perder os dados.
🛠️ Prática Obrigatória: Construção e Destruição
Cenário: A base de teste para a equipe de desenvolvimento.
- Crie um schema chamado
treinamento. - Crie a tabela
teste_devdentro dele. - Insira 1 linha de dados.
- Destrua a tabela completamente usando o comando de aniquilação do DDL.
🚀 Script de Seed (Gabarito de Ciclo de Vida)
-- 1. Cria o ambiente
CREATE SCHEMA treinamento;
-- 2. Cria a estrutura (DDL)
CREATE TABLE treinamento.teste_dev (
id INT PRIMARY KEY,
descricao VARCHAR(50)
);
-- 3. Insere dados (DML)
INSERT INTO treinamento.teste_dev VALUES (1, 'Cobaia 01');
-- 4. Aniquila a estrutura (DDL Destrutivo)
-- CUIDADO! O DROP apaga a tabela e todos os dados dentro dela sem aviso!
DROP TABLE treinamento.teste_dev;
💻 Ponte Prática: Do SQL Manual ao SQLAlchemy 2.0 ORM
Como o ecossistema Python gerencia DDL (Criação, Alteração e Deleção de Estruturas) de forma segura e programática?
🔴 1. A Abordagem Manual (Scripts DDL Manuais e Risco de Erro)
No modelo manual, comandos CREATE TABLE e ALTER TABLE são rodados no terminal sem testes. Um erro de sintaxe pode quebrar o deploy em produção:
# ❌ ABORDAGEM COM SQL MANUAL: DDL vulnerável e sem controle de versão
cursor.execute("CREATE TABLE IF NOT EXISTS fornecedores (id INT, nome VARCHAR(100));")
# E se precisarmos adicionar uma nova coluna 'email' em produção sem perder os dados?
cursor.execute("ALTER TABLE fornecedores ADD COLUMN email VARCHAR(100);")
🟢 2. A Abordagem com SQLAlchemy 2.0 (Metadados e Schemas Declarativos)
Com o SQLAlchemy 2.0, os metadados das tabelas são objetos Python inspecionáveis. A criação e evolução de schemas é controlada por ferramentas de migração (como o Alembic):
# ✅ ABORDAGEM MODERNA: Gerenciador de Ciclo de Vida DDL com Metadados
from sqlalchemy import create_engine, String, Integer, inspect, select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class FornecedorLogisticaModel(Base):
"""Representa a tabela do Schema de Logística."""
__tablename__ = "fornecedores_logistica"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
nome_fantasia: Mapped[str] = mapped_column(String(100), nullable=False)
cnpj: Mapped[str] = mapped_column(String(14), unique=True, nullable=False)
email: Mapped[str] = mapped_column(String(100), nullable=True)
def __repr__(self) -> str:
return f"FornecedorLogistica(id={self.id}, nome='{self.nome_fantasia}', cnpj='{self.cnpj}')"
🛠️ Mini-Projeto 11 (BD): Gerenciador de Ciclo de Vida de Schemas DDL
Objetivo: Construir um script que inspeciona o catálogo de metadados, cria tabelas programaticamente e valida as colunas existentes no banco.
📋 Pré-requisitos e Instalação
No terminal do seu ambiente virtual (PowerShell ou Bash), instale a biblioteca necessária:
pip install sqlalchemy
💻 Código Completo e Autocontido (miniprojeto_11_ddl.py)
Crie o arquivo miniprojeto_11_ddl.py e insira o código abaixo integralmente:
"""
Mini-Projeto 11: Gerenciador de Ciclo de Vida de Schemas DDL
Curso: GTI - Banco de Dados Relacionais e Engenharia de Software
Stack: Python 3.11+ | SQLAlchemy 2.0 | SQLite
"""
import os
from sqlalchemy import create_engine, String, Integer, inspect
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
# 1. Definição Declarativa do Schema DDL
class Base(DeclarativeBase):
pass
class FornecedorLogisticaModel(Base):
"""Representa a tabela do Schema de Logística."""
__tablename__ = "fornecedores_logistica"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
nome_fantasia: Mapped[str] = mapped_column(String(100), nullable=False)
cnpj: Mapped[str] = mapped_column(String(14), unique=True, nullable=False)
email: Mapped[str] = mapped_column(String(100), nullable=True)
def __repr__(self) -> str:
return f"FornecedorLogistica(id={self.id}, nome='{self.nome_fantasia}', cnpj='{self.cnpj}')"
# 2. Ponto de Entrada Executável
if __name__ == "__main__":
DB_FILE = "tecpro_ddl_demo.db"
# Reset preventivo para garantir idempotência em testes repetidos
if os.path.exists(DB_FILE):
os.remove(DB_FILE)
engine = create_engine(f"sqlite:///{DB_FILE}", echo=False)
print("🏗️ CICLO DE VIDA DDL E METADADOS - TECPROEXPRESS")
print("=" * 65)
# 1. DDL: Criação das Tabelas
print("1. [DDL] Executando CREATE TABLE via Metadados...")
Base.metadata.create_all(bind=engine)
print(" ✅ Tabela 'fornecedores_logistica' criada com sucesso!")
# 2. Inspecionando o Catálogo do Banco de Dados
inspector = inspect(engine)
colunas = inspector.get_columns("fornecedores_logistica")
print("\n2. [METADADOS] Inspecionando colunas criadas no banco:")
for col in colunas:
print(f" • Coluna: {col['name']} | Tipo: {col['type']} | Aceita Null: {col['nullable']}")
# 3. DML: Inserindo e consultando dados
with Session(engine) as session:
f = FornecedorLogisticaModel(id=1, nome_fantasia="Baterias Moura S.A.", cnpj="12345678000199", email="contato@moura.com")
session.merge(f)
session.commit()
print(f"\n3. [DML] Registro persistido: {f}")
print("=" * 65)
🚀 Como Executar
Execute o script no terminal:
python miniprojeto_11_ddl.py
🖥️ Saída Esperada no Console
🏗️ CICLO DE VIDA DDL E METADADOS - TECPROEXPRESS
=================================================================
1. [DDL] Executando CREATE TABLE via Metadados...
✅ Tabela 'fornecedores_logistica' criada com sucesso!
2. [METADADOS] Inspecionando colunas criadas no banco:
• Coluna: id | Tipo: INTEGER | Aceita Null: False
• Coluna: nome_fantasia | Tipo: VARCHAR(100) | Aceita Null: False
• Coluna: cnpj | Tipo: VARCHAR(14) | Aceita Null: False
• Coluna: email | Tipo: VARCHAR(100) | Aceita Null: True
3. [DML] Registro persistido: FornecedorLogistica(id=1, nome='Baterias Moura S.A.', cnpj='12345678000199')
=================================================================
💡 Checkpoint de Lógica
Dica do Arquiteto:
Qual a diferença entre DELETE (DML) e DROP (DDL)?
O DELETE FROM tabela apaga apenas as linhas (os dados), mas o esqueleto da tabela continua existindo para receber novos registros. O DROP TABLE é uma bomba atômica: apaga a estrutura, as colunas, as regras e, por consequência, todos os dados de uma vez. Use com extrema cautela! 🚀🛡️
🧪 Quiz de Fixação e Autoavaliação — Capítulo 11
🧪 Quiz de Fixação e Autoavaliação — Capítulo 11
1. Qual das alternativas lista corretamente a família SQL correspondente ao comando CREATE TABLE?
- A) DML (Data Manipulation Language)
- B) DDL (Data Definition Language)
- C) DCL (Data Control Language)
- D) TCL (Transaction Control Language)
💡 Ver Resposta e Justificativa
Resposta Correta: B
Justificativa: DDL cuida do 'esqueleto' estrutural do banco: CREATE, ALTER, DROP e TRUNCATE.
2. Qual a diferença vital entre os comandos DELETE FROM tabela; (DML) e DROP TABLE tabela; (DDL)?
-
A)
DELETEapaga as linhas de dados preservando a estrutura da tabela para novos registros;DROPdestrói a tabela inteira, suas colunas, regras e metadados do disco. -
B)
DELETEapaga a tabela inteira eDROPapaga apenas uma linha. - C) São exatamente o mesmo comando com nomes diferentes.
-
D)
DROPsó funciona se o computador estiver conectado à internet.
💡 Ver Resposta e Justificativa
Resposta Correta: A
Justificativa: DELETE é DML (manipula dados). DROP é DDL (destrói o objeto no catálogo).
3. No PostgreSQL, qual é a vantagem de criar múltiplos SCHEMAS (ex: logistica.pedidos, rh.funcionarios) dentro do mesmo banco de dados?
- A) Acelerar o processador da máquina.
- B) Criar divisões lógicas (namespaces) para organizar tabelas por módulos corporativos, evitando conflitos de nomes e permitindo permissões de acesso granulares por setor.
- C) Economizar espaço na memória RAM.
- D) Permitir o uso de senhas curtas.
💡 Ver Resposta e Justificativa
Resposta Correta: B
Justificativa: Schemas funcionam como 'pastas' dentro do banco de dados, mantendo módulos corporativos organizados e com permissões de acesso isoladas.
Coloque este conhecimento em prática agora mesmo executando o roteiro autoguiado:
👉 ATIVIDADE 05: SQL DDL (ESTRUTURA)