Definição
O que é SQL?
SQL (Structured Query Language) é a linguagem padrão para interagir com bancos de dados relacionais. Desenvolvida na IBM nos anos 1970, foi padronizada pelo ANSI em 1986 e ISO em 1987. Apesar de existir um padrão, cada SGBD (Oracle, SQL Server, MySQL) possui extensões próprias.
O SQL é dividido em subcategorias baseadas no tipo de operação:
DQL - Data Query Language
Consulta de dados
Comandos para recuperar dados do banco. Na prática, representa cerca de 80% das operações executadas.
SELECT
DML - Data Manipulation Language
Manipulação de dados
Comandos para modificar dados nas tabelas. Requerem COMMIT para persistir ou ROLLBACK para desfazer.
INSERT, UPDATE, DELETE, MERGE
DDL - Data Definition Language
Definição de estrutura
Comandos para criar, alterar e remover objetos do banco. Executam COMMIT automático (implícito).
CREATE, ALTER, DROP, TRUNCATE
DCL - Data Control Language
Controle de acesso
Comandos para gerenciar permissões e controle de acesso. Fundamentais para segurança do banco.
GRANT, REVOKE
TCL - Transaction Control Language
Além das 4 categorias principais, existe o TCL para controle de transações:
COMMIT
Confirma as alterações permanentemente
ROLLBACK
Desfaz alterações desde o último COMMIT
SAVEPOINT
Cria ponto de salvamento intermediário
Aplicação Prática
DQL - Exemplos de SELECT
-- SELECT básico
SELECT * FROM employees;
-- SELECT com colunas específicas
SELECT employee_id, first_name, last_name, salary
FROM employees;
-- SELECT com filtro (WHERE)
SELECT first_name, last_name, salary
FROM employees
WHERE department_id = 50
AND salary > 5000;
-- SELECT com ordenação
SELECT first_name, last_name, hire_date
FROM employees
ORDER BY hire_date DESC;
-- SELECT com alias
SELECT first_name AS "Nome",
last_name AS "Sobrenome",
salary * 12 AS "Salário Anual"
FROM employees;
-- SELECT com DISTINCT (valores únicos)
SELECT DISTINCT department_id
FROM employees
WHERE department_id IS NOT NULL;
-- SELECT com ROWNUM (limitar resultados)
SELECT * FROM employees
WHERE ROWNUM <= 10;
-- Oracle 12c+: FETCH FIRST
SELECT * FROM employees
ORDER BY salary DESC
FETCH FIRST 5 ROWS ONLY;
DML - INSERT, UPDATE, DELETE
-- INSERT: Adicionar novo registro
INSERT INTO departments (department_id, department_name, location_id)
VALUES (280, 'Data Science', 1700);
-- INSERT com subconsulta
INSERT INTO employees_backup
SELECT * FROM employees WHERE department_id = 50;
-- INSERT multi-row (Oracle)
INSERT ALL
INTO regions (region_id, region_name) VALUES (5, 'Oceania')
INTO regions (region_id, region_name) VALUES (6, 'Antarctica')
SELECT * FROM dual;
-- UPDATE: Modificar registros existentes
UPDATE employees
SET salary = salary * 1.10
WHERE department_id = 50;
-- UPDATE com subconsulta
UPDATE employees e
SET salary = (
SELECT AVG(salary) * 1.05
FROM employees
WHERE department_id = e.department_id
)
WHERE performance_rating = 'A';
-- DELETE: Remover registros
DELETE FROM employees
WHERE employee_id = 999;
-- DELETE com subconsulta
DELETE FROM employees
WHERE department_id IN (
SELECT department_id FROM departments WHERE location_id = 1700
);
-- MERGE: Combina INSERT e UPDATE (UPSERT)
MERGE INTO employees_target t
USING employees_source s
ON (t.employee_id = s.employee_id)
WHEN MATCHED THEN
UPDATE SET t.salary = s.salary, t.last_update = SYSDATE
WHEN NOT MATCHED THEN
INSERT (employee_id, first_name, last_name, salary)
VALUES (s.employee_id, s.first_name, s.last_name, s.salary);
DDL - CREATE, ALTER, DROP
-- CREATE TABLE
CREATE TABLE projects (
project_id NUMBER(10) PRIMARY KEY,
project_name VARCHAR2(100) NOT NULL,
start_date DATE DEFAULT SYSDATE,
end_date DATE,
budget NUMBER(12,2),
status VARCHAR2(20) DEFAULT 'ACTIVE'
CHECK (status IN ('ACTIVE', 'COMPLETED', 'CANCELLED'))
);
-- CREATE INDEX
CREATE INDEX idx_projects_status ON projects(status);
CREATE UNIQUE INDEX idx_projects_name ON projects(project_name);
-- CREATE VIEW
CREATE OR REPLACE VIEW vw_active_projects AS
SELECT project_id, project_name, budget
FROM projects
WHERE status = 'ACTIVE';
-- CREATE SEQUENCE
CREATE SEQUENCE seq_project_id
START WITH 1
INCREMENT BY 1
NOCACHE;
-- ALTER TABLE: Adicionar coluna
ALTER TABLE projects ADD (manager_id NUMBER(10));
-- ALTER TABLE: Modificar coluna
ALTER TABLE projects MODIFY (project_name VARCHAR2(200));
-- ALTER TABLE: Renomear coluna
ALTER TABLE projects RENAME COLUMN budget TO total_budget;
-- ALTER TABLE: Adicionar constraint
ALTER TABLE projects ADD CONSTRAINT fk_project_manager
FOREIGN KEY (manager_id) REFERENCES employees(employee_id);
-- DROP: Remover objetos (CUIDADO!)
DROP INDEX idx_projects_status;
DROP VIEW vw_active_projects;
DROP SEQUENCE seq_project_id;
DROP TABLE projects CASCADE CONSTRAINTS; -- Remove com dependências
-- TRUNCATE: Apaga todos os dados (mais rápido que DELETE)
TRUNCATE TABLE logs; -- Não pode ser revertido com ROLLBACK!
⚠️ Atenção: DDL faz COMMIT automático!
Comandos DDL executam um COMMIT implícito antes E depois da execução. Isso significa que você não pode fazer ROLLBACK de um DROP TABLE ou TRUNCATE!
DCL - GRANT e REVOKE
-- GRANT: Conceder privilégios
-- Privilégios de sistema
GRANT CREATE SESSION TO novo_usuario;
GRANT CREATE TABLE, CREATE VIEW TO desenvolvedor;
GRANT DBA TO admin_user; -- Privilégio poderoso!
-- Privilégios de objeto
GRANT SELECT ON hr.employees TO relatorios_user;
GRANT SELECT, INSERT, UPDATE ON hr.departments TO app_user;
GRANT ALL ON hr.locations TO admin_user;
-- GRANT com WITH GRANT OPTION (pode repassar)
GRANT SELECT ON hr.employees TO gerente WITH GRANT OPTION;
-- GRANT para roles (grupos de privilégios)
CREATE ROLE readonly_role;
GRANT SELECT ON hr.employees TO readonly_role;
GRANT SELECT ON hr.departments TO readonly_role;
GRANT readonly_role TO analista1, analista2;
-- GRANT para PUBLIC (todos os usuários)
GRANT SELECT ON v_public_info TO PUBLIC;
-- REVOKE: Revogar privilégios
REVOKE CREATE TABLE FROM desenvolvedor;
REVOKE SELECT ON hr.employees FROM relatorios_user;
REVOKE readonly_role FROM analista1;
-- Verificar privilégios concedidos
SELECT * FROM user_tab_privs WHERE table_name = 'EMPLOYEES';
SELECT * FROM user_sys_privs;
SELECT * FROM user_role_privs;
TCL - Controle de Transações
-- Cenário: Transferência bancária
-- Debitar de uma conta e creditar em outra
-- Início da transação (implícito ao primeiro DML)
UPDATE contas SET saldo = saldo - 1000 WHERE conta_id = 123;
UPDATE contas SET saldo = saldo + 1000 WHERE conta_id = 456;
-- Se tudo OK, confirma
COMMIT;
-- Se algo errado, desfaz tudo
ROLLBACK;
-- Usando SAVEPOINT para pontos intermediários
SAVEPOINT antes_bonus;
UPDATE employees SET salary = salary * 1.05 WHERE department_id = 50;
SAVEPOINT antes_promocao;
UPDATE employees SET job_id = 'IT_PROG' WHERE employee_id = 107;
-- Ops! Erro na promoção, mas bonus está OK
ROLLBACK TO SAVEPOINT antes_promocao;
-- Confirma apenas o bonus
COMMIT;
-- SET TRANSACTION: Configurar propriedades da transação
SET TRANSACTION READ ONLY; -- Apenas leitura
SET TRANSACTION READ WRITE; -- Leitura e escrita (padrão)
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- Máximo isolamento
Resumo: Comportamento de COMMIT
| DML (INSERT, UPDATE, DELETE) | Requer COMMIT explícito |
| DDL (CREATE, ALTER, DROP) | COMMIT automático (não pode desfazer) |
| DCL (GRANT, REVOKE) | COMMIT automático |
| DQL (SELECT) | Não afeta (apenas leitura) |
Resultado Esperado
O que você deve dominar após este tópico:
Classificar comandos SQL
Identificar se é DQL, DML, DDL, DCL ou TCL
Entender COMMIT/ROLLBACK
Saber quando mudanças são permanentes
Evitar erros críticos
Conhecer impacto de DDL e TRUNCATE
Gerenciar permissões
Usar GRANT e REVOKE adequadamente
Usar transações
Aplicar SAVEPOINT para operações complexas
Escolher comando certo
DELETE vs TRUNCATE, etc.
Exercícios Práticos
Exercício 1: Classificação de Comandos
Classifique cada comando abaixo em DQL, DML, DDL, DCL ou TCL:
- SELECT * FROM employees
- UPDATE departments SET location_id = 1800
- CREATE INDEX idx_salary ON employees(salary)
- GRANT SELECT ON orders TO analyst
- ROLLBACK TO SAVEPOINT sp1
- TRUNCATE TABLE logs
- MERGE INTO ... WHEN MATCHED THEN UPDATE
- ALTER TABLE employees ADD bonus NUMBER
Ver Solução
- DQL (Data Query Language)
- DML (Data Manipulation Language)
- DDL (Data Definition Language)
- DCL (Data Control Language)
- TCL (Transaction Control Language)
- DDL - apesar de remover dados, é DDL pois faz COMMIT automático
- DML (Data Manipulation Language)
- DDL (Data Definition Language)
Exercício 2: Cenário de Transação
Analise a sequência de comandos e responda: quais dados foram realmente salvos no banco?
INSERT INTO products VALUES (1, 'Produto A', 100);
SAVEPOINT sp1;
INSERT INTO products VALUES (2, 'Produto B', 200);
INSERT INTO products VALUES (3, 'Produto C', 300);
ROLLBACK TO sp1;
INSERT INTO products VALUES (4, 'Produto D', 400);
COMMIT;
INSERT INTO products VALUES (5, 'Produto E', 500);
ROLLBACK;
Ver Solução
Produtos salvos: 1 e 4
- Produto A (1): Inserido antes do SAVEPOINT, mantido após ROLLBACK TO sp1
- Produtos B e C (2, 3): Inseridos após sp1, removidos pelo ROLLBACK TO sp1
- Produto D (4): Inserido após ROLLBACK, confirmado pelo COMMIT
- Produto E (5): Inserido após COMMIT, removido pelo ROLLBACK final
Exercício 3: Permissões
Crie os comandos para: (a) criar um usuário "reports_user", (b) permitir que ele apenas consulte as tabelas EMPLOYEES e DEPARTMENTS, (c) criar uma role para esse tipo de acesso que possa ser reutilizada.
Ver Solução
-- (a) Criar usuário
CREATE USER reports_user IDENTIFIED BY senha123
DEFAULT TABLESPACE users
QUOTA 10M ON users;
-- Permitir conexão
GRANT CREATE SESSION TO reports_user;
-- (b) Conceder acesso de leitura
GRANT SELECT ON hr.employees TO reports_user;
GRANT SELECT ON hr.departments TO reports_user;
-- (c) Criar role reutilizável
CREATE ROLE hr_readonly;
GRANT SELECT ON hr.employees TO hr_readonly;
GRANT SELECT ON hr.departments TO hr_readonly;
GRANT SELECT ON hr.jobs TO hr_readonly;
GRANT SELECT ON hr.locations TO hr_readonly;
-- Atribuir role ao usuário (ao invés de grants individuais)
GRANT hr_readonly TO reports_user;
-- Outros usuários podem receber a mesma role
GRANT hr_readonly TO outro_usuario;