Início / Trilha 1 / Conteúdo / Tópico 4
4

A Linguagem SQL: DQL, DML, DDL e DCL

Categorias de comandos SQL e seus usos

📖

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:

  1. SELECT * FROM employees
  2. UPDATE departments SET location_id = 1800
  3. CREATE INDEX idx_salary ON employees(salary)
  4. GRANT SELECT ON orders TO analyst
  5. ROLLBACK TO SAVEPOINT sp1
  6. TRUNCATE TABLE logs
  7. MERGE INTO ... WHEN MATCHED THEN UPDATE
  8. ALTER TABLE employees ADD bonus NUMBER
Ver Solução
  1. DQL (Data Query Language)
  2. DML (Data Manipulation Language)
  3. DDL (Data Definition Language)
  4. DCL (Data Control Language)
  5. TCL (Transaction Control Language)
  6. DDL - apesar de remover dados, é DDL pois faz COMMIT automático
  7. DML (Data Manipulation Language)
  8. 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;
Anterior: SQL Developer e SQL*Plus Próximo: Comandos SQL na Prática