Suporte a Banco de Dados - Guia de MySQL & PostgreSQL

Guia Completo de SQL — MySQL & PostgreSQL
Banco de Dados · Do Zero ao SQL

Guia Prático de MySQL & PostgreSQL

Do login no console até consultas avançadas com JOIN — um roteiro prático para quem está começando.

Instalação

Escolha o comando conforme seu sistema operacional:

# Windows — baixe o instalador em mysql.com/downloads

# Linux (Ubuntu/Debian)
sudo apt update && sudo apt install mysql-server

# Mac
brew install mysql

Iniciando o serviço

# Windows (PowerShell como administrador)
net start MySQL80

# Linux
sudo systemctl start mysql
sudo systemctl status mysql   # verifica se está rodando

# Mac
brew services start mysql

Conectando

# Forma básica
mysql -u root -p

# Já entrando em um banco específico
mysql -u root -p nome_do_banco

# Servidor remoto
mysql -h 192.168.1.100 -u root -p

# Porta diferente da padrão (3306)
mysql -u root -p -P 3307
💡 Após digitar o comando, o terminal pedirá a senha. É normal não aparecer nada enquanto você digita — isso é intencional por segurança.

Comandos essenciais dentro do console

-- Listar todos os bancos
SHOW DATABASES;

-- Selecionar um banco
USE nome_do_banco;

-- Listar tabelas do banco atual
SHOW TABLES;

-- Ver estrutura de uma tabela
DESCRIBE Cliente;

-- Ver qual banco está em uso
SELECT DATABASE();

-- Ver usuário conectado
SELECT USER();

-- Sair
EXIT;

Criando banco e usuário

-- Criando banco com suporte a caracteres especiais (acentos)
CREATE DATABASE loja
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

-- Criando usuário
CREATE USER 'elton'@'localhost' IDENTIFIED BY 'senha123';

-- Concedendo permissões
GRANT ALL PRIVILEGES ON loja.* TO 'elton'@'localhost';
FLUSH PRIVILEGES;

Executando um arquivo .sql

# Antes de conectar
mysql -u root -p loja < /projetos/criar_tabelas.sql

# Já dentro do console
source /projetos/criar_tabelas.sql

Instalação

# Windows — baixe em postgresql.org/download

# Linux (Ubuntu/Debian)
sudo apt update && sudo apt install postgresql postgresql-contrib

# Mac
brew install postgresql

Iniciando o serviço

# Windows (PowerShell como administrador)
net start postgresql-x64-15

# Linux
sudo systemctl start postgresql
sudo systemctl status postgresql

# Mac
brew services start postgresql

Conectando — o console se chama psql

# Forma básica
psql -U postgres

# Já entrando em um banco específico
psql -U postgres -d nome_do_banco

# Servidor remoto
psql -h 192.168.1.100 -U postgres -d nome_do_banco

# No Linux pode ser necessário usar o usuário do sistema
sudo -u postgres psql

Comandos essenciais — começam com \ (barra invertida)

-- Listar todos os bancos
\l

-- Conectar a um banco
\c nome_do_banco

-- Listar tabelas
\dt

-- Ver estrutura de uma tabela
\d Cliente

-- Listar usuários
\du

-- Limpar a tela
\! clear   (Linux/Mac)
\! cls     (Windows)

-- Sair
\q

Criando banco e usuário

CREATE DATABASE loja
    ENCODING 'UTF8';

CREATE USER elton WITH PASSWORD 'senha123';

GRANT ALL PRIVILEGES ON DATABASE loja TO elton;

-- Conectar ao banco recém criado
\c loja

Executando um arquivo .sql

# Antes de conectar
psql -U postgres -d loja -f /projetos/criar_tabelas.sql

# Já dentro do psql
\i /projetos/criar_tabelas.sql
🐬 MySQL
  • Mais simples de configurar
  • Muito popular em aplicações web
  • Amplamente usado com PHP/WordPress
  • Console: mysql
  • Porta padrão: 3306
  • Listar bancos: SHOW DATABASES
  • Listar tabelas: SHOW TABLES
  • Ver tabela: DESCRIBE tabela
  • Trocar banco: USE banco
  • Rodar arquivo: source arq.sql
🐘 PostgreSQL
  • Mais robusto e completo
  • Melhor para dados complexos
  • Preferido em sistemas corporativos
  • Console: psql
  • Porta padrão: 5432
  • Listar bancos: \l
  • Listar tabelas: \dt
  • Ver tabela: \d tabela
  • Trocar banco: \c banco
  • Rodar arquivo: \i arq.sql
Critério MySQL PostgreSQL
Facilidade inicial⭐⭐⭐⭐⭐⭐⭐⭐⭐
Recursos avançados⭐⭐⭐⭐⭐⭐⭐⭐
Velocidade em leituraMuito boaMuito boa
Suporte a JSONBásicoAvançado (JSONB)
Mercado de trabalhoMuito altoAlto
Gratuito✅ Sim✅ Sim
🎯 Para quem está aprendendo: os comandos SQL são praticamente os mesmos nos dois bancos. Aprenda um e você saberá o outro. As diferenças estão nos comandos do console e em recursos avançados.

Antes de criar qualquer tabela, precisamos planejar quais entidades existem no sistema e como elas se relacionam. Nosso projeto é um sistema de compras com quatro entidades:

👤 Cliente
  • idPK
  • nome
  • telefone
  • rua
  • numero
  • bairro
  • cidade
  • estado
  • cep
🛒 Compras
  • id_compraPK
  • data
  • id_clienteFK
  • total
  • status
  • forma_pagamento
📦 Produtos
  • id_produtoPK
  • nome
  • descricao
  • preco
  • estoque
  • categoria
📋 Itens
  • id_itemPK
  • id_compraFK
  • id_produtoFK
  • quantidade
  • preco_unitario

Relacionamentos

Cliente  (1) ────────< Compras  (N)
Compras  (1) ────────< Itens    (N)
Produtos (1) ────────< Itens    (N)

Itens resolve o relacionamento N:N entre Compras e Produtos
📌 Por que separar o endereço em vários campos? Um campo único como "Rua das Flores, 123, Centro, São Paulo" impede filtrar por cidade ou CEP. Campos separados permitem buscas, relatórios e futuras integrações com sistemas de entrega.
💡 Por que preco_unitario em Itens? O preço de um produto pode mudar ao longo do tempo. Esse campo "congela" o valor exato no momento da venda, preservando o histórico correto.

Tipos de dados mais usados

TipoUsoExemplo
INTNúmeros inteirosid, quantidade, estoque
DECIMAL(10,2)Números com casas decimaispreço, total
VARCHAR(n)Texto de tamanho variávelnome, email, status
TEXTTexto longodescrição, observações
CHAR(n)Texto de tamanho fixoestado (2), cep (9)
DATESó a data2024-01-15
DATETIMEData e hora2024-01-15 14:30:00
BOOLEANVerdadeiro ou falsoativo, aprovado

Constraints (Restrições)

ConstraintO que faz
PRIMARY KEYIdentifica unicamente cada linha. Não pode repetir nem ser nulo.
FOREIGN KEYGarante que o valor exista na tabela referenciada.
NOT NULLO campo não pode ficar vazio.
UNIQUEO valor não pode se repetir na tabela.
DEFAULTDefine um valor automático se nada for informado.
AUTO_INCREMENTGera um número sequencial automaticamente (MySQL). No PostgreSQL use SERIAL.

A ordem de criação importa: tabelas referenciadas por chaves estrangeiras devem existir antes.

1º Cliente
2º Produtos
3º Compras
4º Itens
-- ─── 1. Cliente (sem dependências) ───────────────
CREATE TABLE Cliente (
    id        INT AUTO_INCREMENT PRIMARY KEY,
    nome      VARCHAR(100) NOT NULL,
    telefone  VARCHAR(20),
    rua       VARCHAR(150),
    numero    VARCHAR(10),
    bairro    VARCHAR(80),
    cidade    VARCHAR(80),
    estado    CHAR(2),
    cep       CHAR(9)
);

-- ─── 2. Produtos (sem dependências) ──────────────
CREATE TABLE Produtos (
    id_produto  INT AUTO_INCREMENT PRIMARY KEY,
    nome        VARCHAR(100) NOT NULL,
    descricao   TEXT,
    preco       DECIMAL(10,2) NOT NULL,
    estoque     INT DEFAULT 0,
    categoria   VARCHAR(60)
);

-- ─── 3. Compras (depende de Cliente) ─────────────
CREATE TABLE Compras (
    id_compra       INT AUTO_INCREMENT PRIMARY KEY,
    data            DATETIME DEFAULT CURRENT_TIMESTAMP,
    id_cliente      INT NOT NULL,
    total           DECIMAL(10,2) DEFAULT 0,
    status          VARCHAR(20) DEFAULT 'pendente',
    forma_pagamento VARCHAR(30),
    FOREIGN KEY (id_cliente) REFERENCES Cliente(id)
);

-- ─── 4. Itens (depende de Compras e Produtos) ────
CREATE TABLE Itens (
    id_item        INT AUTO_INCREMENT PRIMARY KEY,
    id_compra      INT NOT NULL,
    id_produto     INT NOT NULL,
    quantidade     INT NOT NULL,
    preco_unitario DECIMAL(10,2) NOT NULL,
    FOREIGN KEY (id_compra)  REFERENCES Compras(id_compra),
    FOREIGN KEY (id_produto) REFERENCES Produtos(id_produto)
);
🐘 PostgreSQL: substitua INT AUTO_INCREMENT PRIMARY KEY por SERIAL PRIMARY KEY — o resto do script funciona igual.

Sintaxe básica

INSERT INTO nome_da_tabela (coluna1, coluna2)
VALUES (valor1, valor2);
⚠️ Respeite a ordem: insira primeiro as tabelas que não dependem de ninguém (Cliente e Produtos), depois Compras e por último Itens.

Inserindo Clientes

-- Vários registros de uma vez
INSERT INTO Cliente (nome, telefone, rua, numero, bairro, cidade, estado, cep)
VALUES
    ('João Silva',     '11 99999-0000', 'Rua das Flores',     '123', 'Centro',    'São Paulo', 'SP', '01001-000'),
    ('Maria Souza',    '11 98888-1111', 'Av. Paulista',        '456', 'Bela Vista', 'São Paulo', 'SP', '01310-000'),
    ('Carlos Oliveira','11 97777-2222', 'Rua XV de Novembro', '78',  'Centro',    'Curitiba',  'PR', '80020-310'),
    ('Ana Costa',     '19 96666-3333', 'Rua do Comércio',    '90',  'Centro',    'Campinas',  'SP', '13010-050');

Inserindo Produtos

INSERT INTO Produtos (nome, descricao, preco, estoque, categoria)
VALUES
    ('Notebook Dell',    'Intel i5, 8GB RAM, 256GB SSD', 3200.00, 15, 'Informática'),
    ('Mouse Logitech',   'Mouse sem fio, 1000 DPI',       89.90,   50, 'Periféricos'),
    ('Teclado Mecânico', 'Switch Blue, ABNT2',            250.00,  30, 'Periféricos'),
    ('Monitor 24"',      'Full HD, 75Hz, IPS',           1100.00, 10, 'Informática');

Inserindo Compras

-- id_cliente refere os ids gerados na tabela Cliente
INSERT INTO Compras (id_cliente, status, forma_pagamento)
VALUES
    (1, 'pago',     'cartão'),   -- João  → id_compra = 1
    (2, 'pendente', 'pix'),      -- Maria → id_compra = 2
    (1, 'pago',     'dinheiro'); -- João  → id_compra = 3 (segunda compra)

Inserindo Itens

-- Itens da compra 1 (João: notebook + 2 mouses)
INSERT INTO Itens (id_compra, id_produto, quantidade, preco_unitario)
VALUES
    (1, 1, 1, 3200.00),  -- 1 Notebook
    (1, 2, 2,   89.90);  -- 2 Mouses

-- Itens da compra 2 (Maria: teclado + monitor)
INSERT INTO Itens (id_compra, id_produto, quantidade, preco_unitario)
VALUES
    (2, 3, 1,  250.00),  -- 1 Teclado
    (2, 4, 1, 1100.00);  -- 1 Monitor

-- Itens da compra 3 (João: só um mouse)
INSERT INTO Itens (id_compra, id_produto, quantidade, preco_unitario)
VALUES
    (3, 2, 1, 89.90);

Erros comuns

Mensagem de erroCausaSolução
Cannot add or update a child rowid_cliente não existe em ClienteCadastre o cliente primeiro
Column cannot be nullCampo NOT NULL ficou vazioInforme um valor
Duplicate entryid repetidoNão informe o id, deixe AUTO_INCREMENT
Data too longTexto maior que o VARCHARAumente o tamanho do campo

O JOIN une tabelas para que você possa cruzar informações em uma única consulta. Sem ele, cada consulta retorna apenas os dados de uma tabela — com ids sem significado.

Tipos de JOIN

TipoO que retorna
INNER JOINSomente registros com correspondência nos dois lados
LEFT JOINTodos da esquerda + correspondências da direita (NULL se não houver)
RIGHT JOINTodos da direita + correspondências da esquerda

INNER JOIN — Compras com nome do cliente

SELECT
    c.id_compra,
    cl.nome       AS cliente,
    c.data,
    c.status,
    c.forma_pagamento
FROM Compras c
INNER JOIN Cliente cl ON cl.id = c.id_cliente;

JOIN com três tabelas — Nota fiscal completa

SELECT
    cl.nome                                          AS cliente,
    c.id_compra,
    c.data,
    c.forma_pagamento,
    p.nome                                          AS produto,
    i.quantidade,
    i.preco_unitario,
    (i.quantidade * i.preco_unitario)               AS subtotal
FROM Itens i
INNER JOIN Compras  c  ON c.id_compra  = i.id_compra
INNER JOIN Cliente  cl ON cl.id        = c.id_cliente
INNER JOIN Produtos p  ON p.id_produto = i.id_produto
ORDER BY c.id_compra, p.nome;

LEFT JOIN — Clientes que nunca compraram

SELECT
    cl.nome     AS cliente,
    c.id_compra,
    c.status
FROM Cliente cl
LEFT JOIN Compras c ON c.id_cliente = cl.id;
-- Carlos e Ana aparecerão com NULL em id_compra e status

GROUP BY — Total gasto por cliente

SELECT
    cl.nome                                    AS cliente,
    COUNT(c.id_compra)                         AS total_compras,
    SUM(i.quantidade * i.preco_unitario)        AS valor_total
FROM Cliente cl
LEFT JOIN Compras c ON c.id_cliente  = cl.id
LEFT JOIN Itens   i ON i.id_compra   = c.id_compra
GROUP BY cl.id, cl.nome
ORDER BY valor_total DESC;

Produtos mais vendidos

SELECT
    p.nome                                    AS produto,
    SUM(i.quantidade)                          AS qtd_vendida,
    SUM(i.quantidade * i.preco_unitario)       AS receita_total
FROM Itens i
INNER JOIN Produtos p ON p.id_produto = i.id_produto
GROUP BY p.id_produto, p.nome
ORDER BY qtd_vendida DESC;

WHERE + JOIN — Filtrando resultado

-- Apenas compras pagas
SELECT
    cl.nome     AS cliente,
    c.id_compra,
    c.forma_pagamento,
    SUM(i.quantidade * i.preco_unitario) AS total
FROM Compras c
INNER JOIN Cliente cl ON cl.id       = c.id_cliente
INNER JOIN Itens   i  ON i.id_compra = c.id_compra
WHERE c.status = 'pago'
GROUP BY c.id_compra, cl.nome, c.forma_pagamento;
🚨 Regra de ouro: SEMPRE use WHERE no UPDATE e no DELETE. Sem ele, você altera ou apaga todos os registros da tabela de uma vez.

UPDATE — Sintaxe básica

UPDATE nome_da_tabela
SET coluna1 = valor1, coluna2 = valor2
WHERE condição;

Exemplos de UPDATE

-- Atualizando um campo simples
UPDATE Cliente
SET telefone = '11 91111-2222'
WHERE id = 1;

-- Atualizando vários campos ao mesmo tempo
UPDATE Cliente
SET
    rua    = 'Rua Augusta',
    numero = '200',
    bairro = 'Consolação'
WHERE id = 2;

-- Mudando status de uma compra
UPDATE Compras
SET
    status          = 'pago',
    forma_pagamento = 'cartão'
WHERE id_compra = 2;

-- Aplicando 10% de desconto no Mouse Logitech
UPDATE Produtos
SET preco = preco * 0.90
WHERE id_produto = 2;

-- Recalculando total da compra a partir dos itens reais
UPDATE Compras
SET total = (
    SELECT SUM(quantidade * preco_unitario)
    FROM Itens
    WHERE id_compra = 1
)
WHERE id_compra = 1;

UPDATE com JOIN

-- Reduzindo estoque após a compra 1
UPDATE Produtos p
INNER JOIN Itens i ON i.id_produto = p.id_produto
SET p.estoque = p.estoque - i.quantidade
WHERE i.id_compra = 1;

DELETE — Sintaxe básica

DELETE FROM nome_da_tabela
WHERE condição;

A ordem importa no DELETE

Ao contrário do INSERT, no DELETE você deve apagar primeiro as tabelas dependentes:

1º Itens
2º Compras
3º Clientes / Produtos
-- ERRADO: dará erro pois Itens ainda referenciam a compra
DELETE FROM Compras WHERE id_compra = 1;

-- CERTO: apaga os itens primeiro, depois a compra
DELETE FROM Itens   WHERE id_compra = 1;
DELETE FROM Compras WHERE id_compra = 1;

TRUNCATE — apagando todos os registros

-- Apaga tudo e reinicia o AUTO_INCREMENT
TRUNCATE TABLE Itens;
DELETE sem WHERETRUNCATE
VelocidadeMais lentoMais rápido
AUTO_INCREMENTMantém o último idReinicia do 1
Pode usar WHERE✅ Sim❌ Não
Pode desfazer✅ Com transaction❌ Não

Transactions — sua rede de segurança

-- Inicia o rascunho
START TRANSACTION;

DELETE FROM Itens   WHERE id_compra = 3;
DELETE FROM Compras WHERE id_compra = 3;

-- Confirma — torna permanente
COMMIT;

-- Ou desfaz tudo se algo der errado
ROLLBACK;
Antes de qualquer UPDATE ou DELETE, faça primeiro um SELECT com o mesmo WHERE para confirmar quais registros serão afetados. Só depois execute a operação.

Comentários

Postagens mais visitadas deste blog

Introdução aos Sistemas de Gerenciamento de Banco de Dados

Introdução ao HTML, CSS e JavaScript - Guia para Iniciantes

Introdução ao Excel