📝

PL/SQL - Guia Prático

Linguagem procedural do Oracle para desenvolvimento de lógica de negócio no banco de dados.

📝

Fundamentos PL/SQL

Blocos PL/SQL, variáveis, tipos de dados e estrutura básica.

Blocos PL/SQL

Estrutura básica de um bloco PL/SQL (DECLARE, BEGIN, EXCEPTION, END)

Bloco Anônimo Básico
-- Bloco PL/SQL simples
DECLARE
    v_nome VARCHAR2(100);
    v_idade NUMBER := 30;
BEGIN
    v_nome := 'João Silva';
    DBMS_OUTPUT.PUT_LINE('Nome: ' || v_nome);
    DBMS_OUTPUT.PUT_LINE('Idade: ' || v_idade);
END;
/
Bloco com Exception
DECLARE
    v_salario NUMBER;
    v_media NUMBER;
BEGIN
    SELECT AVG(salario) INTO v_media
    FROM funcionarios;
    
    v_salario := 5000;
    
    IF v_salario > v_media THEN
        DBMS_OUTPUT.PUT_LINE('Acima da média');
    ELSE
        DBMS_OUTPUT.PUT_LINE('Abaixo da média');
    END IF;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('Nenhum dado encontrado');
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('Erro: ' || SQLERRM);
END;
/

Variáveis e Tipos

Declaração de variáveis e tipos de dados em PL/SQL

Tipos Básicos
DECLARE
    -- Tipos numéricos
    v_id NUMBER := 1;
    v_preco NUMBER(10,2) := 99.99;
    v_quantidade INTEGER := 100;
    
    -- Tipos de texto
    v_nome VARCHAR2(100) := 'João';
    v_descricao VARCHAR2(4000);
    v_observacao CHAR(10) := 'ATIVO    ';
    
    -- Tipos de data
    v_data DATE := SYSDATE;
    v_timestamp TIMESTAMP := CURRENT_TIMESTAMP;
    
    -- Boolean
    v_ativo BOOLEAN := TRUE;
    
BEGIN
    DBMS_OUTPUT.PUT_LINE('ID: ' || v_id);
    DBMS_OUTPUT.PUT_LINE('Nome: ' || v_nome);
    DBMS_OUTPUT.PUT_LINE('Data: ' || TO_CHAR(v_data, 'DD/MM/YYYY'));
END;
/
Ancoragem de Tipos
DECLARE
    -- Ancorar tipo à coluna de uma tabela
    v_nome_cliente clientes.nome%TYPE;
    v_email_cliente clientes.email%TYPE;
    
    -- Ancorar tipo a uma linha inteira
    v_cliente clientes%ROWTYPE;
    
BEGIN
    -- Usar %TYPE
    SELECT nome, email INTO v_nome_cliente, v_email_cliente
    FROM clientes WHERE cliente_id = 1;
    
    -- Usar %ROWTYPE
    SELECT * INTO v_cliente
    FROM clientes WHERE cliente_id = 1;
    
    DBMS_OUTPUT.PUT_LINE('Cliente: ' || v_cliente.nome);
    DBMS_OUTPUT.PUT_LINE('Email: ' || v_cliente.email);
END;
/
🔄

Estruturas de Controle

IF, CASE, LOOPs e estruturas condicionais para controle de fluxo.

IF / ELSIF / ELSE

Estruturas condicionais para tomada de decisão

IF Simples
DECLARE
    v_salario NUMBER := 5000;
    v_bonus NUMBER;
BEGIN
    IF v_salario > 3000 THEN
        v_bonus := v_salario * 0.10;
    END IF;
    
    DBMS_OUTPUT.PUT_LINE('Bônus: ' || v_bonus);
END;
/
IF / ELSE
DECLARE
    v_nota NUMBER := 7.5;
    v_status VARCHAR2(20);
BEGIN
    IF v_nota >= 7 THEN
        v_status := 'Aprovado';
    ELSE
        v_status := 'Reprovado';
    END IF;
    
    DBMS_OUTPUT.PUT_LINE('Status: ' || v_status);
END;
/

LOOPs

Estruturas de repetição: LOOP, WHILE, FOR

FOR LOOP
BEGIN
    -- FOR com números
    FOR i IN 1..10 LOOP
        DBMS_OUTPUT.PUT_LINE('Número: ' || i);
    END LOOP;
    
    -- FOR com cursor implícito
    FOR reg IN (SELECT nome, salario FROM funcionarios WHERE rownum <= 5) LOOP
        DBMS_OUTPUT.PUT_LINE(reg.nome || ' - R$ ' || reg.salario);
    END LOOP;
END;
/
🔍

Cursors

Cursors para processar múltiplas linhas de uma query.

Cursor Explícito

Cursor declarado explicitamente para controle total

Cursor Básico
DECLARE
    -- Declarar cursor
    CURSOR c_clientes IS
        SELECT cliente_id, nome, email
        FROM clientes
        WHERE ativo = 1;
    
    -- Variável para armazenar linha
    v_cliente c_clientes%ROWTYPE;
    
BEGIN
    -- Abrir cursor
    OPEN c_clientes;
    
    -- Loop para processar linhas
    LOOP
        FETCH c_clientes INTO v_cliente;
        EXIT WHEN c_clientes%NOTFOUND;
        
        DBMS_OUTPUT.PUT_LINE('Cliente: ' || v_cliente.nome);
    END LOOP;
    
    -- Fechar cursor
    CLOSE c_clientes;
END;
/
⚙️

Procedures e Functions

Criar procedures e functions reutilizáveis no banco de dados.

CREATE PROCEDURE

Criar procedures para executar lógica de negócio

Procedure Simples
-- Criar procedure
CREATE OR REPLACE PROCEDURE prc_atualizar_preco (
    p_produto_id IN NUMBER,
    p_novo_preco IN NUMBER
) AS
BEGIN
    UPDATE produtos
    SET preco = p_novo_preco,
        data_atualizacao = SYSDATE
    WHERE produto_id = p_produto_id;
    
    COMMIT;
    DBMS_OUTPUT.PUT_LINE('Preço atualizado com sucesso');
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('Produto não encontrado');
        ROLLBACK;
END;
/

-- Executar procedure
BEGIN
    prc_atualizar_preco(123, 99.90);
END;
/

CREATE FUNCTION

Criar functions que retornam valores

Function Simples
-- Criar function
CREATE OR REPLACE FUNCTION fnc_calcular_desconto (
    p_valor IN NUMBER,
    p_percentual IN NUMBER
) RETURN NUMBER AS
    v_desconto NUMBER;
BEGIN
    v_desconto := p_valor * (p_percentual / 100);
    RETURN v_desconto;
END;
/

-- Usar function em SELECT
SELECT 
    produto_id,
    nome,
    preco,
    fnc_calcular_desconto(preco, 10) AS desconto,
    preco - fnc_calcular_desconto(preco, 10) AS preco_final
FROM produtos;
/
📦

Packages

Agrupar procedures, functions e variáveis relacionadas em packages.

CREATE PACKAGE

Criar package para organizar código PL/SQL

Package Básico
-- Especificação do Package
CREATE OR REPLACE PACKAGE pkg_vendas AS
    CONSTANT c_taxa_imposto NUMBER := 0.10;
    
    PROCEDURE prc_processar_venda (
        p_cliente_id IN NUMBER,
        p_valor IN NUMBER
    );
    
    FUNCTION fnc_calcular_total (
        p_valor IN NUMBER
    ) RETURN NUMBER;
END pkg_vendas;
/

-- Corpo do Package
CREATE OR REPLACE PACKAGE BODY pkg_vendas AS
    
    PROCEDURE prc_processar_venda (
        p_cliente_id IN NUMBER,
        p_valor IN NUMBER
    ) AS
    BEGIN
        INSERT INTO vendas (cliente_id, valor, data_venda)
        VALUES (p_cliente_id, p_valor, SYSDATE);
        COMMIT;
    END prc_processar_venda;
    
    FUNCTION fnc_calcular_total (
        p_valor IN NUMBER
    ) RETURN NUMBER AS
    BEGIN
        RETURN p_valor + (p_valor * c_taxa_imposto);
    END fnc_calcular_total;
    
END pkg_vendas;
/

Triggers

Triggers para executar ações automaticamente em eventos DML.

CREATE TRIGGER

Criar triggers para automatizar ações

Trigger BEFORE INSERT
-- Trigger antes de inserir
CREATE OR REPLACE TRIGGER trg_clientes_before_insert
BEFORE INSERT ON clientes
FOR EACH ROW
BEGIN
    IF :NEW.cliente_id IS NULL THEN
        SELECT seq_clientes.NEXTVAL INTO :NEW.cliente_id FROM DUAL;
    END IF;
    
    :NEW.data_cadastro := SYSDATE;
END;
/
⚠️

Exception Handling

Tratamento de erros e exceções em PL/SQL.

Exceções Pré-definidas

Tratar exceções padrão do Oracle

Exception Handling
DECLARE
    v_salario NUMBER;
BEGIN
    SELECT salario INTO v_salario
    FROM funcionarios
    WHERE funcionario_id = 999;
    
    DBMS_OUTPUT.PUT_LINE('Salário: ' || v_salario);
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('Funcionário não encontrado');
    WHEN TOO_MANY_ROWS THEN
        DBMS_OUTPUT.PUT_LINE('Múltiplos registros encontrados');
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('Erro: ' || SQLERRM);
END;
/
← Voltar para Banco de Dados