Pular para o conteúdo principal

As 20 principais perguntas e respostas para entrevistas sobre PL/SQL em 2026

Prepare-se para entrevistas sobre PL/SQL com tópicos importantes como funções, gatilhos, SQL dinâmico, tratamento de erros, melhores práticas e perguntas baseadas em cenários reais.
Atualizado 22 de dez. de 2025  · 10 min lido

PL/SQL, que é a extensão da linguagem procedural SQL da Oracle, é algo que você precisa saber se vai trabalhar com bancos de dados Oracle. Isso vale para funções importantes, como administrador de banco de dados, desenvolvedor e analista de dados, que precisam lidar com lógicas de negócios complexas dentro do banco de dados.

Acho que os entrevistadores avaliam os candidatos em três pontos principais:

  • Compreensão conceitual: Princípios básicos, tipos de dados, estruturas de controle e tratamento de exceções.
  • Habilidade prática de codificação: Escrever procedimentos armazenados, funções, gatilhos e pacotes eficientes.
  • Considerações sobre desempenho: Otimizar o código PL/SQL pra melhorar o tempo de execução, minimizar o consumo de recursos e evitar erros como a troca excessiva de contexto entre SQL e PL/SQL.

Pra ajudar, tô mandando um guia com perguntas pra entrevista sobre PL/SQL. Vou começar com os conceitos básicos e depois passar para assuntos mais avançados, como processamento em massa, SQL dinâmico e ajuste de desempenho.

Se você quer entender os conceitos básicos do banco de dados Oracle, recomendo fazer nosso curso Introdução ao Oracle SQL, que é um recurso super importante pra aprender a interagir com o banco de dados Oracle e como ele usa PL/SQL pra processar consultas.

Perguntas para entrevistas para iniciantes em PL/SQL

Na fase inicial da entrevista, o entrevistador pode fazer perguntas básicas para avaliar seus conhecimentos sobre conceitos básicos de banco de dados e PL/SQL. Tenta estudar essas perguntas e respostas pra se preparar pra fase inicial da entrevista.

1. O que é PL/SQL?

PL/SQL é a extensão procedural da Oracle para SQL. Diferente do SQL, que é declarativo e foca na recuperação e manipulação de dados, o PL/SQL permite que os desenvolvedores implementem lógica procedural, tornando-o uma ferramenta poderosa para escrever regras de negócios complexas dentro do banco de dados. Ele suporta variáveis, loops, condicionais, tratamento de exceções e programação modular por meio de procedimentos, funções e pacotes.

2. Qual é a estrutura básica de um bloco PL/SQL?

Um bloco PL/SQL é a unidade básica de execução no PL/SQL e tem quatro partes principais:

  • DECLARE (Opcional): Usado para definir variáveis, constantes, cursores e tipos definidos pelo usuário.

  • BEGIN: A parte executável onde as consultas SQL e as instruções procedimentais são escritas.

  • EXCEPTION (Opcional): Lida com erros de tempo de execução e exceções para garantir uma recuperação suave dos erros.

  • END;: Marca o fim do bloco.

3. Quais são os tipos de dados essenciais do PL/SQL?

O PL/SQL suporta vários tipos de dados, categorizados da seguinte forma:

  • Tipos escalares: Tipos de valor único como NUMBER, VARCHAR2, DATE, BOOLEAN.

  • Tipos compostos: Coleções como RECORD (estruturas personalizadas) e TABLE/VARRAY (matrizes).

  • Tipos de referência: Ponteiros para objetos de banco de dados, como REF CURSOR para processamento dinâmico de consultas.

4. Quais são as estruturas de controle básicas em PL/SQL?

O PL/SQL tem várias estruturas de controle que ajudam a gerenciar o fluxo de um programa:

  • Loops: Isso inclui LOOP, FOR LOOP e WHILE LOOP, que permitem a execução repetitiva de instruções.

  • Declarações condicionais: Isso inclui as instruções ` IF ` e ` CASE `, que executam diferentes blocos de código com base em condições. A função DECODE() é outro bom exemplo de uma condição que vale a pena estudar. 

Perguntas intermediárias sobre PL/SQL para entrevistas

Depois de falar das perguntas básicas, vamos passar para algumas perguntas de nível intermediário sobre estrutura de dados. Depois de testar seus conhecimentos básicos, os entrevistadores vão agora testar sua proficiência técnica na implementação e utilização dos conceitos PL/SQL.

5. Qual é a diferença entre procedimentos armazenados e funções?

Os procedimentos armazenados e as funções são blocos de código PL/SQL reutilizáveis, mas têm finalidades bem diferentes.

Os procedimentos armazenados são usados para fazer operações que não devolvem um valor, como inserir, atualizar ou excluir dados. São usadas para tarefas que modificam dados ou fazem operações complexas sem devolver um resultado.

Por exemplo, o procedimento abaixo atualiza o salary do funcionário com o employee_id fornecido, adicionando o p_increment especificado, de modo que o salário seja atualizado dinamicamente com base nos parâmetros de entrada.

CREATE PROCEDURE update_salary(p_emp_id NUMBER, p_increment NUMBER) AS  
BEGIN  
    -- Update the salary of the employee with the given ID  
    UPDATE employees  
    SET salary = salary + p_increment  
    WHERE employee_id = p_emp_id;  
END;

Já as funções devolvem um valor depois de fazerem as operações. São bons para cálculos ou recuperação de dados que precisam dar um resultado.

A função abaixo simplifica a obtenção do salário de um funcionário, tornando-a reutilizável em consultas SQL ou outros procedimentos.

CREATE FUNCTION get_employee_salary(p_emp_id NUMBER) RETURN NUMBER AS  
    v_salary NUMBER;  
BEGIN  
    -- Retrieve the salary for the given employee ID  
    SELECT salary INTO v_salary  
    FROM employees  
    WHERE employee_id = p_emp_id;  
    
    -- Return the retrieved salary  
    RETURN v_salary;  
END;

6. O que são pacotes PL/SQL?

Os pacotes PL/SQL são conjuntos de procedimentos, funções e variáveis relacionados que juntam o código para facilitar a organização e reutilização. Eles têm duas partes:

  • Especificações da embalagem: Declara elementos públicos (procedimentos, funções, variáveis).
  • Corpo da embalagem: Tem os detalhes de como implementar os procedimentos e funções declarados na especificação.

Por exemplo, a consulta abaixo cria um pacote employee_pkg que define um procedimento para aumentar o salário de um funcionário e uma função para recuperar o número total de funcionários, com suas implementações a serem fornecidas no corpo do pacote.

-- Create a package named 'employee_pkg'
CREATE PACKAGE employee_pkg AS  

    -- Procedure to increase an employee's salary by a percentage  
    PROCEDURE raise_salary(p_emp_id NUMBER, p_percent NUMBER);  

    -- Function to return the total number of employees  
    FUNCTION get_total_employees RETURN NUMBER;  

END employee_pkg;

7. O que são gatilhos PL/SQL?

Os gatilhos são blocos PL/SQL que funcionam automaticamente quando acontecem certas coisas no banco de dados, tipo inserir, atualizar ou apagar dados. Os gatilhos são usados para fazer valer as regras de negócio. Eles também são comumente usados para realizar auditorias. Eles são divididos em:

  • Gatilhos no nível da linha: Execute uma vez para cada linha afetada.
  • Gatilhos no nível da instrução: Execute uma vez por instrução SQL, independentemente do número de linhas afetadas.

A consulta abaixo cria um gatilho AFTER UPDATE trg_salary_audit na tabela employees que registra as alterações salariais no salary_audit table, capturando o ID do funcionário, o salário antigo e o novo, e o carimbo de data/hora da atualização.

-- Create or replace a trigger 'trg_salary_audit'
CREATE OR REPLACE TRIGGER trg_salary_audit  
AFTER UPDATE OF salary ON employees  -- Fires after salary updates in 'employees' table
FOR EACH ROW  -- Executes for each updated row
BEGIN  
    -- Inserts old and new salary details into 'salary_audit' table
    INSERT INTO salary_audit (employee_id, old_salary, new_salary, change_date)  
    VALUES (:OLD.employee_id, :OLD.salary, :NEW.salary, SYSDATE);  
END;

Dá uma olhada no nosso tutorial sobre Triggers SQL pra você estar pronto caso eles apareçam na entrevista. 

8. Quais são os métodos de tratamento de exceções no PL/SQL?

O PL/SQL oferece mecanismos de tratamento de erros para garantir a estabilidade e evitar falhas. Os tipos de exceções incluem o seguinte:

  • Exceções pré-definidas: Exceções integradas como NO_DATA_FOUND, TOO_MANY_ROWS e ZERO_DIVIDE.

  • Exceções definidas pelo usuário: As exceções personalizadas são declaradas usando EXCEPTION e levantadas usando RAISE.

Por exemplo, o bloco PL/SQL a seguir pega o salário de um funcionário com ID 100, gera uma exceção personalizada se o salário for menor que 1000 e lida com possíveis erros, incluindo registros de funcionários ausentes e exceções inesperadas.

DECLARE  
    v_salary NUMBER;  -- Variable to store the employee's salary  
    e_low_salary EXCEPTION;  -- Custom exception for low salary  

BEGIN  
    -- Retrieve salary of employee with ID 100  
    SELECT salary INTO v_salary FROM employees WHERE employee_id = 100;  

    -- Raise exception if salary is below 1000  
    IF v_salary < 1000 THEN  
        RAISE e_low_salary;  
    END IF;  

EXCEPTION  
    WHEN NO_DATA_FOUND THEN  -- Handle case where employee ID is not found  
        DBMS_OUTPUT.PUT_LINE('Employee not found.');  
    WHEN e_low_salary THEN  -- Handle custom low salary exception  
        DBMS_OUTPUT.PUT_LINE('Salary is below the allowed threshold.');  
    WHEN OTHERS THEN  -- Handle any other unexpected errors  
        DBMS_OUTPUT.PUT_LINE('An unexpected error occurred: ' || SQLERRM);  

END;

As melhores práticas para o tratamento de exceções incluem o seguinte:

  • Esteja sempre atento a possíveis exceções.
  • Use mensagens de erro que façam sentido.
  • Registre exceções para auditoria.
  • Mantenha o código de tratamento de exceções conciso e focado na recuperação.

9. Como você pode verificar se uma instrução UPDATE foi executada ou não?

O atributo SQL %NOTFOUND pode ser usado para ver se a instrução UPDATE conseguiu alterar algum registro. Se a última instrução SQL executada não afetou nenhuma linha, essa variável retorna um TRUE.

Por exemplo, a consulta abaixo atualiza o salário dos funcionários do departamento 10, aumentando-o em 10%, e depois verifica se alguma linha foi afetada pela instrução ` UPDATE ` usando o atributo ` %NOTFOUND `. Se nenhuma linha foi atualizada, aparece uma mensagem dizendo: “Nenhuma linha foi atualizada”. Se as linhas foram atualizadas, ele mostra o número de linhas que foram afetadas usando o atributo “ SQL%ROWCOUNT ”.

DECLARE
    -- Declare a variable to store the number of rows updated
    rows_updated INTEGER;
BEGIN
    -- Perform an UPDATE statement on the 'employees' table
    UPDATE employees
    SET salary = salary * 1.1
    WHERE department_id = 10;

    -- Check if any rows were updated by using %NOTFOUND
    IF SQL%NOTFOUND THEN
        -- If no rows were updated, print a message
        DBMS_OUTPUT.PUT_LINE('No rows were updated.');
    ELSE
        -- If rows were updated, print how many rows were affected
        rows_updated := SQL%ROWCOUNT;  -- Store the number of rows updated
        DBMS_OUTPUT.PUT_LINE(rows_updated || ' rows were updated.');
    END IF;
END;
/

Perguntas avançadas sobre PL/SQL para entrevistas

Vamos agora explorar algumas perguntas avançadas para entrevistas, caso você esteja se candidatando a um cargo mais sênior que exija mais experiência.

10. Quais são os métodos para otimizar o desempenho em PL/SQL?

Minimizar as trocas de contexto entre SQL e PL/SQL é essencial para otimizar o desempenho. Cada mudança gera uma sobrecarga, que pode deixar a execução mais lenta, principalmente quando tem muitas transições entre as duas.

11. Como você usa operações em massa pra minimizar as trocas de contexto?

O PL/SQL oferece técnicas de processamento em massa para otimizar a interação entre SQL e PL/SQL, buscando ou modificando várias linhas de uma vez só.

Por exemplo, o bloco PL/SQL abaixo pega todos os funcionários do departamento 10 usando um BULK COLLECT e em uma coleção e faz uma iteração por ela para imprimir o nome de cada funcionário, melhorando o desempenho ao minimizar as trocas de contexto entre SQL e PL/SQL.

DECLARE  
    -- Define a table-type collection based on the 'employees' table structure  
    TYPE emp_table IS TABLE OF employees%ROWTYPE;  
    v_emps emp_table;  -- Declare a variable of this type  

BEGIN  
    -- Bulk fetch employees from department 10 into the collection  
    SELECT * BULK COLLECT INTO v_emps FROM employees WHERE department_id = 10;  

    -- Loop through the collection and print employee names  
    FOR i IN 1..v_emps.COUNT LOOP  
        DBMS_OUTPUT.PUT_LINE('Employee: ' || v_emps(i).employee_name);  
    END LOOP;  

END;

Além disso, esse bloco PL/SQL usa FORALL para atualização em massa, aumentando o salário em 10% para os funcionários com os IDs 101, 102 e 103.

DECLARE  
    -- Define a table-type collection for employee IDs  
    TYPE t_emp_ids IS TABLE OF employees.employee_id%TYPE;  
    -- Initialize collection with specific employee IDs  
    v_emp_ids t_emp_ids := t_emp_ids(101, 102, 103);  

BEGIN  
    -- Bulk update salaries by 10% for specified employee IDs  
    FORALL i IN 1..v_emp_ids.COUNT  
        UPDATE employees SET salary = salary * 1.10 WHERE employee_id = v_emp_ids(i);  

END;

12. O que são SQL dinâmico e cursores de referência?

O SQL dinâmico permite executar instruções SQL de forma dinâmica em tempo de execução, o que é útil quando se lida com nomes de tabelas, colunas ou estruturas de consulta variáveis.

O bloco PL/SQL a seguir usa SQL dinâmico para contar o número de linhas na tabela ` employees ` e imprime o resultado. Gosto desse tipo de abordagem porque permite flexibilidade.

DECLARE  
    v_table_name VARCHAR2(50) := 'employees';  -- Store table name  
    v_count NUMBER;  -- Variable to hold row count  

BEGIN  
    -- Dynamically count rows in the specified table  
    EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || v_table_name INTO v_count;  

    -- Print the total count  
    DBMS_OUTPUT.PUT_LINE('Total Employees: ' || v_count);  

END;  

Os cursores de referência são cursores dinâmicos que podem ser abertos, buscados e fechados em tempo de execução, permitindo a passagem de resultados de consultas entre unidades de programa.

O bloco PL/SQL abaixo usa uma instrução ` REF CURSOR ` para buscar e imprimir os nomes dos funcionários do departamento 20. O cursor é aberto de forma dinâmica, iterado usando um loop e fechado após o processamento.

DECLARE  
    -- Define a REF CURSOR type  
    TYPE emp_ref_cursor IS REF CURSOR;  
    v_cursor emp_ref_cursor;  -- Declare a cursor variable  
    v_name employees.employee_name%TYPE;  -- Variable to store employee name  

BEGIN  
    -- Open the cursor for employees in department 20  
    OPEN v_cursor FOR SELECT employee_name FROM employees WHERE department_id = 20;  

    -- Fetch and print employee names in a loop  
    LOOP  
        FETCH v_cursor INTO v_name;  
        EXIT WHEN v_cursor%NOTFOUND;  
        DBMS_OUTPUT.PUT_LINE('Employee: ' || v_name);  
    END LOOP;  

    -- Close the cursor  
    CLOSE v_cursor;  

END;

13. Como você lida com erros de mutação de tabelas?

Erros de mutação de tabela acontecem quando um gatilho tenta mexer na tabela em que ele foi acionado. Um gatilho composto permite dividir a execução do gatilho em várias fases, como BEFORE, AFTER e FOR EACH ROW, para evitar problemas de modificação direta.

O gatilho composto abaixo registra as alterações salariais na tabela salary_audit de forma eficiente, coletando dados antes de cada atualização de linha e fazendo uma inserção em massa após a instrução, reduzindo as trocas de contexto e melhorando o desempenho.

CREATE OR REPLACE TRIGGER trg_salary_audit  
FOR UPDATE OF salary ON employees  -- Trigger fires on salary updates  
COMPOUND TRIGGER  

    -- Declare an associative array to store audit records  
    TYPE t_salary_audit IS TABLE OF salary_audit%ROWTYPE INDEX BY PLS_INTEGER;  
    v_audit_data t_salary_audit;  
    v_idx PLS_INTEGER := 0;  

    -- Before updating each row, store old and new salary details  
    BEFORE EACH ROW IS  
    BEGIN  
        v_idx := v_idx + 1;  
        v_audit_data(v_idx).employee_id := :OLD.employee_id;  
        v_audit_data(v_idx).old_salary := :OLD.salary;  
        v_audit_data(v_idx).new_salary := :NEW.salary;  
        v_audit_data(v_idx).change_date := SYSDATE;  
    END BEFORE EACH ROW;  

    -- After the statement, insert all audit records in bulk  
    AFTER STATEMENT IS  
    BEGIN  
        FORALL i IN 1..v_idx  
            INSERT INTO salary_audit VALUES v_audit_data(i);  
    END AFTER STATEMENT;  

END trg_salary_audit;

14. O que é sobrecarga em PL/SQL?

A sobrecarga permite que vários procedimentos ou funções com o mesmo nome, mas parâmetros diferentes, sejam definidos dentro de um pacote. Isso melhora a legibilidade e a manutenção do código, oferecendo várias maneiras de fazer operações parecidas.

Na consulta abaixo, o corpo do pacote implementa dois procedimentos sobrecarregados chamados ` update_salary`: Um aumenta o salário de um funcionário em um valor específico, enquanto o outro define um novo salário com uma data de vigência, atualizando a tabela employees de acordo.

-- Create the package specification
CREATE OR REPLACE PACKAGE emp_pkg AS  
    -- Procedure to increment salary by a specified amount  
    PROCEDURE update_salary(p_emp_id NUMBER, p_increment NUMBER);

    -- Overloaded procedure to set a new salary with an effective date  
    PROCEDURE update_salary(p_emp_id NUMBER, p_new_salary NUMBER, p_effective_date DATE);
END emp_pkg;
/
-- Create the package body
CREATE OR REPLACE PACKAGE BODY emp_pkg AS  

    -- Procedure to increment salary by a specified amount  
    PROCEDURE update_salary(p_emp_id NUMBER, p_increment NUMBER) AS  
    BEGIN  
        UPDATE employees  
        SET salary = salary + p_increment  
        WHERE employee_id = p_emp_id;  
    END update_salary;  

    -- Overloaded procedure to set a new salary with an effective date  
    PROCEDURE update_salary(p_emp_id NUMBER, p_new_salary NUMBER, p_effective_date DATE) AS  
    BEGIN  
        UPDATE employees  
        SET salary = p_new_salary, last_update = p_effective_date  
        WHERE employee_id = p_emp_id;  
    END update_salary;  

END emp_pkg;
/

15. O que são as diretivas do compilador e pragmas em PL/SQL?

O PL/SQL tem diretivas de compilador (PRAGMA) pra otimizar o código e lidar com exceções. Os pragmas comuns incluem:

  • PRAGMA EXCEPTION_INIT: Associa uma exceção definida pelo usuário a um código de erro Oracle.

  • PRAGMA SERIALLY_REUSABLE: Otimiza o uso da memória do pacote para escalabilidade.

O bloco PL/SQL abaixo lida com a inserção de um funcionário com um salário inválido usando uma exceção personalizada e_invalid_salary mapeada para o código de erro -20001. Se a exceção for levantada, ela vai mostrar uma mensagem de erro.

DECLARE  
    e_invalid_salary EXCEPTION;  -- Declare custom exception for invalid salary  
    PRAGMA EXCEPTION_INIT(e_invalid_salary, -20001);  -- Associate exception with error code -20001  
BEGIN  
    -- Attempt to insert an employee with invalid salary  
    INSERT INTO employees (employee_id, salary) VALUES (999, -1000);  
EXCEPTION  
    -- Handle the custom exception and print a message  
    WHEN e_invalid_salary THEN  
        DBMS_OUTPUT.PUT_LINE('Invalid salary detected!');  
END;  

16. Quais são os diferentes métodos para rastrear e depurar código PL/SQL?

O PL/SQL oferece vários pacotes integrados para rastrear e depurar o desempenho do código. Os métodos comuns incluem o uso de DBMS_TRACE para rastrear o fluxo de execução, DBMS_APPLICATION_INFO para monitorar a atividade da sessão e DBMS_SESSION para coletar informações de diagnóstico no nível da sessão.

A consulta abaixo primeiro habilita o rastreamento SQL usando DBMS_SESSION.set_sql_trace(TRUE) e, em seguida, define informações de sessão específicas do cliente com DBMS_APPLICATION_INFO.set_client_info() para monitoramento. O bloco PL/SQL é executado, simulando uma operação de UPDATE. Por fim, desativa o rastreamento após a execução usando DBMS_SESSION.set_sql_trace(FALSE).

-- Enable tracing for the current session using DBMS_SESSION
BEGIN
   -- Start session-level tracing
   DBMS_SESSION.set_sql_trace(TRUE);
END;
/

-- Set application information using DBMS_APPLICATION_INFO
BEGIN
   -- Set the application name and action for session monitoring
   DBMS_APPLICATION_INFO.set_client_info('Trace Debug Session');
   DBMS_APPLICATION_INFO.set_action('Debugging PL/SQL Code');
END;
/

-- Example PL/SQL block that simulates a process for debugging
DECLARE
   v_employee_id NUMBER := 100;
BEGIN
   -- Example query to fetch employee details
   FOR rec IN (SELECT first_name, last_name FROM employees WHERE employee_id = v_employee_id) LOOP
      DBMS_OUTPUT.put_line('Employee: ' || rec.first_name || ' ' || rec.last_name);
   END LOOP;
   
   -- Simulate some logic that could be traced
   IF v_employee_id = 100 THEN
      DBMS_OUTPUT.put_line('Employee ID is 100');
   END IF;
END;
/

-- Disable tracing after the session is complete
BEGIN
   -- Stop session-level tracing
   DBMS_SESSION.set_sql_trace(FALSE);
END;
/

Perguntas de entrevista sobre PL/SQL baseadas em cenários

Em aplicações empresariais reais, o PL/SQL é usado para lidar com lógicas de negócios complexas. Os entrevistadores costumam avaliar a capacidade do candidato de usar PL/SQL em situações reais. Abaixo estão alguns dos principais desafios, junto com estratégias para resolvê-los.

Nesta próxima e última seção, se você estiver em uma entrevista, recomendo que pense em como responder às perguntas seguindo este modelo, mas tente, é claro, reorientar sua resposta para o seu setor específico ou para refletir sua própria experiência. O mesmo vale se você estiver entrevistando um candidato e quiser ideias sobre como fazer uma pergunta e avaliar a profundidade da resposta. Nesse caso, espero que esta seção sirva de inspiração tanto para suas perguntas quanto para seus critérios de avaliação.

Aumente a proficiência em SQL da sua equipe

Treine sua equipe em SQL com o DataCamp for Business. Treinamento abrangente, projetos práticos e métricas de desempenho detalhadas para sua organização.

Solicite uma demonstração hoje mesmo!
business-homepage-hero.png

17. Como você cria gatilhos em ambientes com muita concorrência?

Imagina uma situação em que você precisa aplicar uma regra de negócios que diz que o salário de um funcionário não pode ser atualizado mais de uma vez por dia. Mas, o banco de dados tem muitas transações ao mesmo tempo, e um gatilho simples pode causar problemas de desempenho ou disputa.

Em vez de usar um gatilho no nível da linha que dispara para cada atualização e pode diminuir o desempenho, use um gatilho no nível da instrução com uma tabela de log para evitar várias atualizações salariais no mesmo dia.

Por exemplo, o gatilho abaixo evita várias atualizações salariais para um funcionário no mesmo dia, verificando a tabela salary_update_log antes de permitir uma atualização. Se o salário já tiver sido atualizado hoje, aparece um erro; caso contrário, a data de atualização é registrada.

-- Create a table to log the last salary update for each employee
CREATE TABLE salary_update_log (
    employee_id NUMBER PRIMARY KEY,  -- Employee ID as primary key
    last_update DATE  -- Date of the last salary update
);

-- Create or replace a compound trigger to prevent multiple salary updates on the same day
CREATE OR REPLACE TRIGGER trg_prevent_multiple_salary_update  
FOR UPDATE OF salary ON employees  
COMPOUND TRIGGER  

    -- Declare a variable to store last salary update date per row
    TYPE emp_log_type IS TABLE OF DATE INDEX BY PLS_INTEGER;
    emp_log emp_log_type;

    BEFORE STATEMENT IS  
    BEGIN  
        -- Load existing salary update logs into memory for reference
        FOR rec IN (SELECT employee_id, last_update FROM salary_update_log) LOOP  
            emp_log(rec.employee_id) := rec.last_update;  
        END LOOP;  
    END BEFORE STATEMENT;  

    BEFORE EACH ROW IS  
    BEGIN  
        -- Check if an entry exists for this employee
        IF emp_log.EXISTS(:NEW.employee_id) THEN  
            -- Validate if salary was updated today
            IF emp_log(:NEW.employee_id) = TRUNC(SYSDATE) THEN  
                RAISE_APPLICATION_ERROR(-20010, 'Salary can only be updated once per day');  
            ELSE  
                -- Update log in memory
                emp_log(:NEW.employee_id) := TRUNC(SYSDATE);  
            END IF;  
        ELSE  
            -- Insert a new log entry into memory
            emp_log(:NEW.employee_id) := TRUNC(SYSDATE);  
        END IF;  
    END BEFORE EACH ROW;  

    AFTER STATEMENT IS  
    BEGIN  
        -- Apply changes to the log table after all row updates
        FOR i IN emp_log.FIRST .. emp_log.LAST LOOP  
            MERGE INTO salary_update_log l  
            USING (SELECT i AS employee_id, emp_log(i) AS last_update FROM DUAL) s  
            ON (l.employee_id = s.employee_id)  
            WHEN MATCHED THEN  
                UPDATE SET l.last_update = s.last_update  
            WHEN NOT MATCHED THEN  
                INSERT (employee_id, last_update) VALUES (s.employee_id, s.last_update);  
        END LOOP;  
    END AFTER STATEMENT;  

END trg_prevent_multiple_salary_update;

O exemplo acima reduziria o bloqueio no nível da linha e minimizaria os conflitos de transação durante atualizações em massa.

18. Como você divide transações grandes em partes menores para garantir a confiabilidade?

Imagina um cenário em que um sistema bancário precisa fazer uma atualização em massa para ajustar as taxas de juros de milhões de contas de clientes. Fazer uma única transação grande pode travar as tabelas por muito tempo ou causar falhas na reversão.

Nesse caso, use o processamento em massa com COMMIT em lotes para processar os dados de forma incremental e evitar conflitos.

O bloco PL/SQL abaixo implementa a solução usando um BULK COLLECT o para buscar IDs de conta e, em seguida, itera por elas para atualizar a taxa de juros em 5%. Ele faz o commit das alterações a cada 1000 atualizações para melhorar o desempenho e reduzir o uso de recursos. Um commit final garante que todas as atualizações restantes sejam salvas.

DECLARE  
    -- Define a collection type for account IDs  
    TYPE t_accounts IS TABLE OF NUMBER;  -- Use NUMBER instead of referencing accounts.account_id
    v_account_ids t_accounts;  -- Variable to store account IDs  
    v_batch_size CONSTANT NUMBER := 1000;  -- Batch size for commits  

BEGIN  
    -- Bulk collect all account IDs into the collection  
    SELECT account_id BULK COLLECT INTO v_account_ids FROM accounts;  

    -- Loop through each account ID to update the interest rate  
    FOR i IN 1 .. v_account_ids.COUNT LOOP  
        UPDATE accounts  
        SET interest_rate = interest_rate * 1.05  -- Increase interest rate by 5%  
        WHERE account_id = v_account_ids(i);  

        -- Commit after every 1000 updates  
        IF MOD(i, v_batch_size) = 0 THEN  
            COMMIT;  
        END IF;  
    END LOOP;  

    COMMIT; -- Final commit for any remaining updates  
END;
/

Essa solução garantiria a confiabilidade em sistemas financeiros, como folha de pagamento, evitando falhas nas transações.

19. Como você organiza uma lógica complexa em pacotes para facilitar a manutenção?

Uma empresa de varejo precisa implementar um sistema de processamento de pedidos que envolve várias etapas: Verificar a disponibilidade do estoque, reservar produtos, calcular descontos e registrar o histórico de transações.

Em vez de escrever procedimentos independentes separados, você precisa organizar essa lógica de uma maneira estruturada e fácil de manter. Então, use pacotes PL/SQL para juntar procedimentos e funções relacionados, melhorando a reutilização e a manutenção do código.

A especificação do pacote abaixo define funções e procedimentos para o processamento de pedidos, incluindo verificação de estoque, reserva de estoque, cálculo de descontos e registro do status das transações. Ele oferece uma abordagem modular para lidar com tarefas relacionadas a pedidos.

-- Create a package specification for order processing functions and procedures
CREATE PACKAGE order_processing_pkg AS  

    -- Function to check if enough inventory is available for the product
    FUNCTION check_inventory(p_product_id NUMBER, p_quantity NUMBER) RETURN BOOLEAN;  

    -- Procedure to reserve stock for a specific order
    PROCEDURE reserve_stock(p_order_id NUMBER, p_product_id NUMBER, p_quantity NUMBER);  

    -- Function to calculate discount based on customer and total amount
    FUNCTION calculate_discount(p_customer_id NUMBER, p_total_amount NUMBER) RETURN NUMBER;  

    -- Procedure to log the status of a transaction
    PROCEDURE log_transaction(p_order_id NUMBER, p_status VARCHAR2);  

END order_processing_pkg;

Depois, usamos o seguinte corpo do pacote para implementar as funções e procedimentos definidos na especificação do pacote. Ele cuida de tarefas importantes, como verificar a disponibilidade do estoque, reservar produtos, calcular descontos e registrar o status das transações, garantindo que o processamento dos pedidos seja tranquilo.

-- Create the package body implementing the functions and procedures for order processing
CREATE PACKAGE BODY order_processing_pkg AS  

    -- Function to check if sufficient inventory is available for the product
    FUNCTION check_inventory(p_product_id NUMBER, p_quantity NUMBER) RETURN BOOLEAN AS  
        v_available_qty NUMBER;  -- Variable to store available quantity  
    BEGIN  
        -- Retrieve the available quantity from inventory
        SELECT stock_quantity INTO v_available_qty FROM inventory WHERE product_id = p_product_id;  
        -- Return true if enough stock is available, otherwise false
        RETURN v_available_qty >= p_quantity;  
    END check_inventory;  

    -- Procedure to reserve stock for a specific order
    PROCEDURE reserve_stock(p_order_id NUMBER, p_product_id NUMBER, p_quantity NUMBER) AS  
    BEGIN  
        -- Deduct the ordered quantity from the inventory
        UPDATE inventory SET stock_quantity = stock_quantity - p_quantity WHERE product_id = p_product_id;  
    END reserve_stock;  

    -- Function to calculate a discount based on the total order amount
    FUNCTION calculate_discount(p_customer_id NUMBER, p_total_amount NUMBER) RETURN NUMBER AS  
        v_discount NUMBER := 0;  -- Initialize discount to 0  
    BEGIN  
        -- Apply 10% discount if the total amount is greater than 500
        IF p_total_amount > 500 THEN  
            v_discount := p_total_amount * 0.10;  
        END IF;  
        -- Return the calculated discount
        RETURN v_discount;  
    END calculate_discount;  

    -- Procedure to log the transaction status
    PROCEDURE log_transaction(p_order_id NUMBER, p_status VARCHAR2) AS  
    BEGIN  
        -- Insert a log entry for the order status
        INSERT INTO order_log (order_id, status, log_date) VALUES (p_order_id, p_status, SYSDATE);  
    END log_transaction;  

END order_processing_pkg;

20. Como você lida com impasses em sistemas de alta transação?

Imagina um cenário em que um sistema financeiro atualiza várias tabelas relacionadas ao mesmo tempo. Os impasses acontecem quando duas transações ficam esperando pelos recursos bloqueados uma da outra, causando gargalos de desempenho.

Para resolver esse problema, sempre bloqueie as linhas em uma ordem consistente entre as transações. Além disso, use a cláusula ` NOWAIT ` ou ` SKIP LOCKED ` para evitar uma espera indefinida.

Por exemplo, o bloco PL/SQL abaixo tenta bloquear uma linha específica na tabela de contas para a atualização usando a cláusula ` FOR UPDATE NOWAIT `, o que faz com que a transação falhe imediatamente se outra sessão já tiver bloqueado a linha. Depois de bloquear, ele atualiza o status da transação e confirma as alterações. Se rolar algum erro, ele pega a exceção e mostra uma mensagem de erro.

DECLARE  
    v_balance NUMBER(15,2);  -- Declare variable to store the account balance  
BEGIN  
    -- Lock the account row for update to prevent other sessions from modifying it  
    SELECT balance INTO v_balance FROM accounts  
    WHERE account_id = 101 FOR UPDATE NOWAIT;  

    -- Update the transaction status to 'Processed' for all transactions related to this account  
    UPDATE transactions  
    SET status = 'Processed'  
    WHERE account_id = 101 AND status = 'Pending';  -- Update only pending transactions  

    COMMIT;  -- Commit the changes  

EXCEPTION  
    -- Handle errors, such as locking issues or unexpected exceptions  
    WHEN OTHERS THEN  
        DBMS_OUTPUT.PUT_LINE('Transaction failed: ' || SQLERRM);  
        ROLLBACK;  -- Ensure rollback in case of failure  
END;
/

Da mesma forma, esse bloco PL/SQL processa transações pendentes bloqueando-as para atualização com um FOR UPDATE SKIP LOCKED, permitindo que ele pule as linhas que já estão bloqueadas por outras sessões. Ele atualiza o status de cada transação para “Processando” e confirma as alterações no final.

DECLARE  
    -- Declare a cursor to select pending transactions and lock rows for update
    CURSOR c_pending_txns IS  
        SELECT transaction_id FROM transactions WHERE status = 'Pending' FOR UPDATE SKIP LOCKED;  -- Skip locked rows  

BEGIN  
    -- Loop through the pending transactions
    FOR txn IN c_pending_txns LOOP  
        -- Update the status of each transaction to 'Processing'
        UPDATE transactions SET status = 'Processing' WHERE transaction_id = txn.transaction_id;  
    END LOOP;  
    COMMIT;  -- Commit the changes to finalize the transaction updates  
END;

Conclusão e recursos adicionais

Para funções centradas em Oracle, os empregadores procuram candidatos que saibam escrever código PL/SQL correto, lidar com desafios da vida real e otimizar o desempenho do banco de dados. Recomendo dar uma olhada na documentação oficial da Oracle sobre Referência da Linguagem PL/SQL para um guia detalhado e as melhores práticas sobre PL/SQL. O Oracle Live SQL (Interactive PL/SQL Playground) dá acesso à plataforma baseada em nuvem da Oracle para rodar consultas PL/SQL online. Também recomendo que você entre na Comunidade Oracle pra interagir com especialistas e desenvolvedores da Oracle e no fórum Stack Overflow pra encontrar respostas pra suas dúvidas sobre PL/SQL.

Mas, nada supera um caminho de aprendizagem bem estruturado. Por isso, recomendo muito fazer nosso curso Introdução ao Oracle SQL, que, na minha opinião, é a melhor maneira de realmente se tornar um especialista. Além disso, se você quiser aprofundar seus conhecimentos sobre como trabalhar com bancos de dados, recomendo também fazer nosso curso de Design de Bancos de Dados, onde você aprenderá a criar e gerenciar bancos de dados e a selecionar o DBMS adequado às suas necessidades. Por fim, experimente nosso programa de Engenheiro de Dados Associado em SQL para aprender os fundamentos da engenharia de dados e do warehouse. 

Por último, mas não menos importante, se você estiver entrevistando candidatos e também quiser aprimorar as habilidades de outras pessoas, entre em contato com nossa equipe do DataCamp for Business. DataCamp pode aprimorar as habilidades de equipes inteiras com projetos práticos e trilhas de aprendizagem personalizadas. Essa é uma ótima maneira de os empregadores preencherem lacunas de habilidades e aumentarem a confiança e a credibilidade de uma equipe. Então, entre em contato com a nossa equipe hoje mesmo.


Allan Ouko's photo
Author
Allan Ouko
LinkedIn
Eu crio artigos que simplificam a ciência e a análise de dados, tornando-as fáceis de entender e acessíveis.

Perguntas frequentes sobre PL SQL

O que é PL/SQL e como ele é diferente do SQL?

PL/SQL é uma linguagem procedural desenvolvida pela Oracle, que permite estruturas de controle e tratamento de erros, enquanto SQL é declarativa e lida com recuperação/manipulação de dados.

O que é um pacote PL/SQL?

Um conjunto de procedimentos, funções, variáveis e cursores relacionados para programação modular e reutilização.

Qual é a diferença entre um procedimento e uma função?

Os procedimentos fazem uma ação que não devolve um valor, enquanto as funções devolvem um valor que pode ser usado em consultas.

O que são gatilhos em PL/SQL?

Ações automatizadas feitas antes ou depois das operações INSERT, UPDATE, DELETE.

O que é processamento em massa no PL/SQL?

O processamento em massa (BULK COLLECT, FORALL) melhora o desempenho, reduzindo as trocas de contexto entre os mecanismos PL/SQL e SQL ao lidar com grandes conjuntos de dados.

Tópicos

Aprenda SQL com o DataCamp

Curso

Manipulação de dados em SQL

4 h
306.9K
Domine consultas SQL complexas no PostgreSQL para responder várias perguntas de ciência de dados e preparar conjuntos de dados robustos.
Ver detalhesRight Arrow
Iniciar curso
Ver maisRight Arrow
Relacionado

blog

20 principais perguntas da entrevista sobre junções de SQL

Prepare-se para sua entrevista sobre SQL com esta lista das perguntas mais comuns sobre SQL Joins
Javier Canales Luna's photo

Javier Canales Luna

15 min

blog

As 45 principais perguntas da entrevista sobre PostgreSQL para todos os níveis

Está se candidatando a um emprego que exige fluência em PostgreSQL? Prepare-se para o processo de entrevista com esta lista abrangente de perguntas sobre o PostgreSQL
Javier Canales Luna's photo

Javier Canales Luna

15 min

blog

As 30 principais perguntas da entrevista sobre o Excel para todos os níveis

Um guia para as perguntas mais comuns em entrevistas sobre o Excel para usuários iniciantes, intermediários e avançados, para que você seja aprovado na entrevista técnica.
Chloe Lubin's photo

Chloe Lubin

15 min

blog

40 perguntas e respostas de entrevistas sobre programação em R para todos os níveis

Saiba quais são as 40 perguntas fundamentais de entrevistas sobre programação em R e suas respostas para todos os níveis de experiência: perguntas de nível básico, intermediário e avançado.
Elena Kosourova's photo

Elena Kosourova

15 min

blog

As 20 principais perguntas e respostas da entrevista sobre AWS Lambda para 2026

O AWS Lambda é um serviço de computação sem servidor e um assunto cada vez mais comum em entrevistas técnicas. Seja você um novato em nuvem ou um profissional experiente, entender o AWS Lambda é essencial.
Zoumana Keita 's photo

Zoumana Keita

12 min

Ver maisVer mais