curso
As 20 principais perguntas e respostas da entrevista sobre PL/SQL em 2025
O PL/SQL, que é a extensão da linguagem procedural do SQL da Oracle, é algo que você precisa saber se for trabalhar com bancos de dados Oracle. Isso se aplica a funções importantes, como administrador de banco de dados, desenvolvedor e analista de dados, que precisam lidar com lógica comercial complexa no banco de dados.
Acredito que os entrevistadores avaliam os candidatos em três aspectos 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, acionadores e pacotes eficientes.
- Considerações sobre o desempenho: Otimização do código PL/SQL para 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.
Para ajudar, estou fornecendo a você um guia de perguntas para entrevistas sobre PL/SQL. Começarei com os conceitos fundamentais e avançarei para tópicos mais avançados, como processamento em massa, SQL dinâmico e ajuste de desempenho.
Se você quiser entender os conceitos básicos do banco de dados Oracle, recomendo que faça nosso curso Introdução ao Oracle SQL, que é um recurso muito importante para aprender a interagir com o banco de dados Oracle e como o banco de dados usa o PL/SQL para processar consultas.
Perguntas de entrevista para iniciantes em PL/SQL
Na fase inicial da entrevista, o entrevistador pode fazer perguntas fundamentais para avaliar o conhecimento que você tem dos conceitos básicos de banco de dados e PL/SQL. Tente estudar essas perguntas e respostas para se preparar para a fase inicial da entrevista.
1. O que é PL/SQL?
O PL/SQL é a extensão processual do Oracle para o SQL. Ao contrário do SQL, que é declarativo e se concentra na recuperação e na manipulação de dados, o PL/SQL permite que os desenvolvedores implementem a lógica processual, o que o torna uma ferramenta poderosa para escrever regras comerciais complexas no banco de dados. Ele oferece suporte a 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 fundamental de execução no PL/SQL e consiste em quatro seções principais:
-
DECLARE
(Opcional): Usado para definir variáveis, constantes, cursores e tipos definidos pelo usuário. -
BEGIN
: A seção executável em que as consultas SQL e as instruções de procedimento são escritas. -
EXCEPTION
(Opcional): Trata erros e exceções em tempo de execução para garantir a recuperação de erros. -
END;
: Marca o fim do bloco.
3. Quais são os tipos de dados PL/SQL essenciais?
O PL/SQL oferece suporte a vários tipos de dados, categorizados da seguinte forma:
-
Tipos de escalar: Tipos de valor único, como
NUMBER
,VARCHAR2
,DATE
,BOOLEAN
. -
Tipos de compostos: Coleções como
RECORD
(estruturas personalizadas) eTABLE
/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 no PL/SQL?
O PL/SQL inclui várias estruturas de controle que ajudam a gerenciar o fluxo de um programa:
-
Loops: Isso inclui
LOOP
,FOR LOOP
eWHILE LOOP
, permitindo a execução repetitiva de declarações. -
Declarações condicionais: Isso inclui as instruções
IF
eCASE
, que executam diferentes blocos de código com base em condições. A função DECODE() é outro bom exemplo de uma condicional que vale a pena estudar.
Perguntas da entrevista sobre PL/SQL intermediário
Depois de abordar as perguntas básicas, vamos passar para algumas perguntas de nível intermediário sobre estrutura de dados. Depois de testar seu conhecimento básico, os entrevistadores agora testarão sua proficiência técnica na implementação e no uso de conceitos de 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 bastante diferentes.
Os procedimentos armazenados são usados para executar operações que não retornam um valor, como inserção, atualização ou exclusão de dados. Eles são usados para tarefas que modificam dados ou realizam operações complexas sem retornar um resultado.
Por exemplo, o procedimento a seguir atualiza o site salary
do funcionário com o endereço employee_id
fornecido, adicionando o endereç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;
As funções, por outro lado, retornam um valor após a realização das operações. Eles são adequados para cálculos ou recuperação de dados que precisam retornar um resultado.
A função abaixo simplifica a busca 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 coleções de procedimentos, funções e variáveis relacionados que encapsulam o código para melhor organização e reutilização. Eles consistem em duas partes:
- Especificação da embalagem: Declara elementos públicos (procedimentos, funções, variáveis).
- Corpo da embalagem: Contém os detalhes de implementação dos 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 acionadores PL/SQL?
Os acionadores são blocos PL/SQL que são executados automaticamente em resposta a eventos específicos do banco de dados, como inserções, atualizações ou exclusões. Os acionadores são usados para impor regras de negócios. Eles também são comumente usados para realizar auditorias. Eles são categorizados em:
- Acionadores em nível de linha: Execute uma vez para cada linha afetada.
- Gatilhos em nível de declaração: Executar uma vez por instrução SQL, independentemente do número de linhas afetadas.
A consulta abaixo cria um acionador AFTER UPDATE
trg_salary_audit
na tabela employees
que registra as alterações salariais em 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;
Estude nosso tutorial sobre acionadores SQL para que você esteja preparado caso os acionadores sejam mencionados na entrevista.
8. Quais são os métodos de tratamento de exceções no PL/SQL?
O PL/SQL fornece mecanismos de tratamento de erros para estabilidade e para evitar falhas. Os tipos de exceções incluem o seguinte:
-
Exceções predefinidas: Exceções incorporadas, como
NO_DATA_FOUND
,TOO_MANY_ROWS
eZERO_DIVIDE
. -
Exceções definidas pelo usuário: As exceções personalizadas são declaradas usando
EXCEPTION
e aumentadas usandoRAISE
.
Por exemplo, o seguinte bloco PL/SQL recupera o salário de um funcionário com ID 100, gera uma exceção personalizada se o salário for inferior a 1.000 e trata 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 práticas recomendadas para o tratamento de exceções incluem o seguinte:
- Sempre preveja possíveis exceções.
- Use mensagens de erro significativas.
- Registre exceções para auditoria.
- Mantenha o código de tratamento de exceções conciso e concentrado na recuperação.
9. Como você pode verificar se um comando UPDATE foi executado ou não?
O atributo SQL %NOTFOUND
pode ser usado para determinar se a instrução UPDATE
alterou com sucesso algum registro. Se o último comando SQL executado não afetou nenhuma linha, essa variável retornará TRUE
.
Por exemplo, a consulta abaixo atualiza o salário dos funcionários do departamento 10 aumentando-o em 10% e, em seguida, verifica se alguma linha foi afetada pela instrução UPDATE
usando o atributo %NOTFOUND
. Se nenhuma linha for atualizada, você receberá uma mensagem dizendo: "Nenhuma linha foi atualizada". Se as linhas foram atualizadas, você verá 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 da entrevista sobre PL/SQL
Vamos agora explorar algumas perguntas avançadas da entrevista, caso você esteja se candidatando a uma função mais sênior que exija mais experiência.
10. Quais são os métodos de otimização de desempenho no PL/SQL?
Minimizar as alternâncias de contexto entre SQL e PL/SQL é fundamental para otimizar o desempenho. Cada switch incorre em sobrecarga, o que pode reduzir o tempo de execução, especialmente em situações que envolvem transições frequentes entre os dois.
11. Como você usa operações em massa para 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 só vez.
Por exemplo, o bloco PL/SQL abaixo recupera todos os funcionários do departamento 10 usando BULK COLLECT
em uma coleção e itera através dela 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 funcionários com 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 Dynamic SQL permite que você execute instruções SQL dinamicamente em tempo de execução, o que é útil ao lidar 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 ela 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;
Ref Cursors são cursores dinâmicos que podem ser abertos, obtidos e fechados em tempo de execução, permitindo a passagem de resultados de consultas entre unidades de programa.
O bloco PL/SQL abaixo usa o endereço REF CURSOR
para buscar e imprimir os nomes dos funcionários do departamento 20. O cursor é aberto dinamicamente, iterado por meio de 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 tabelas mutantes?
Os erros de tabela mutante ocorrem quando um acionador tenta modificar a tabela em que foi acionado. Um acionador composto permite dividir a execução do acionador em várias fases, como BEFORE
, AFTER
e FOR EACH ROW
, para evitar problemas de modificação direta.
O acionador composto abaixo registra as alterações de salário na tabela salary_audit
de forma eficiente, coletando dados antes de cada atualização de linha e realizando uma inserção em massa após a instrução, reduzindo as alternâncias 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 no PL/SQL?
A sobrecarga permite que vários procedimentos ou funções com o mesmo nome, mas com parâmetros diferentes, sejam definidos em um pacote. Isso aprimora a legibilidade e a manutenção do código, fornecendo várias maneiras de realizar operações semelhantes.
Na consulta abaixo, o corpo do pacote implementa dois procedimentos sobrecarregados denominados update_salary
: Um deles aumenta o salário de um funcionário em um valor específico, enquanto o outro define um novo salário com uma data efetiva, 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. Quais são as diretivas e os pragmas do compilador no PL/SQL?
O PL/SQL fornece diretivas do compilador (PRAGMA
) para otimizar o código e tratar exceções. Os pragmas comuns incluem:
-
PRAGMA EXCEPTION_INIT
: Associa uma exceção definida pelo usuário a um código de erro do Oracle. -
PRAGMA SERIALLY_REUSABLE
: Otimiza o uso da memória do pacote para aumentar a escalabilidade.
O bloco PL/SQL abaixo trata da 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, ele imprimirá 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 o 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 em nível de sessão.
A consulta abaixo primeiro ativa o rastreamento de SQL usando DBMS_SESSION.set_sql_trace(TRUE)
e, em seguida, define as informações de sessão específicas do cliente com DBMS_APPLICATION_INFO.set_client_info()
para monitoramento. O bloco PL/SQL é executado, o que simula uma operação UPDATE
. Por fim, ele 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 da entrevista sobre PL/SQL baseadas em cenários
Em aplicativos empresariais reais, o PL/SQL é usado para lidar com a lógica comercial complexa. Os entrevistadores geralmente avaliam a capacidade do candidato de aplicar PL/SQL em cenários práticos. Abaixo estão alguns dos principais desafios, juntamente com estratégias para solucioná-los.
Para esta próxima e última seção, se você estiver sendo entrevistado, eu o incentivaria a pensar em como responder às perguntas seguindo este modelo, mas tente, é claro, reorientar sua resposta para seu setor específico ou para refletir sua própria experiência. O mesmo se aplica se você estiver entrevistando um candidato e quiser ideias sobre como fazer uma pergunta e avaliar o grau de profundidade da resposta . Nesse caso, espero que esta seção sirva de inspiração para suas perguntas e 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.

17. Como você projeta acionadores em ambientes altamente simultâneos?
Suponha um cenário em que você precise aplicar uma regra comercial em que o salário de um funcionário não possa ser atualizado mais de uma vez por dia. No entanto, o banco de dados tem alta simultaneidade de transações, e um simples acionador pode levar a problemas de contenção ou desempenho.
Em vez de usar um acionador em nível de linha que dispara para cada atualização e pode reduzir o desempenho, use um acionador em nível de instrução com uma tabela de registro para evitar várias atualizações de salário no mesmo dia.
Por exemplo, o acionador abaixo impede várias atualizações de salário de 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, será gerado um erro; caso contrário, a data de atualização será 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 em nível de linha e minimizaria os conflitos de transação durante as atualizações em massa.
18. Como você divide grandes transações em partes menores para aumentar a confiabilidade?
Imagine um cenário em que um sistema bancário requer uma atualização em massa para ajustar as taxas de juros de milhões de contas de clientes. A execução de uma única transação grande pode bloquear tabelas por muito tempo ou levar a falhas de reversão.
Nesse caso, use o processamento em massa com COMMIT
em lotes para processar os dados de forma incremental e evitar a contenção.
O bloco PL/SQL abaixo implementa a solução usando BULK COLLECT
para buscar IDs de contas e, em seguida, itera através delas para atualizar a taxa de juros em 5%. Ele confirma as alterações após cada 1.000 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 dos sistemas financeiros, como a folha de pagamento, evitando falhas nas transações.
19. Como você organiza a lógica complexa em pacotes para facilitar a manutenção?
Uma empresa de varejo precisa implementar um sistema de processamento de pedidos que envolva várias etapas: Verificação da disponibilidade de estoque, reserva de estoque, cálculo de descontos e registro do histórico de transações.
Em vez de escrever procedimentos autônomos separados, você precisa organizar essa lógica de forma estruturada e passível de manutenção. Portanto, use pacotes PL/SQL para encapsular 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 a verificação do estoque, a reserva de estoque, o cálculo de descontos e o registro do status da transação. 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;
Em seguida, usamos o corpo do pacote a seguir para implementar as funções e os procedimentos definidos na especificação do pacote. Ele lida com tarefas importantes, como verificar a disponibilidade de estoque, reservar estoque, calcular descontos e registrar status de transações, garantindo operações de processamento de pedidos sem problemas.
-- 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 deadlocks em sistemas de alta transação?
Suponha um cenário em que um sistema financeiro atualiza com frequência várias tabelas relacionadas simultaneamente. Os deadlocks ocorrem quando duas transações esperam nos recursos bloqueados uma da outra, causando gargalos no 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 que você espere indefinidamente.
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á bloquear a linha. Após o bloqueio, ele atualiza o status da transação e confirma as alterações. Se ocorrer um erro, ele captura a exceção e imprime 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 FOR UPDATE SKIP LOCKED
, permitindo que você ignore 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 possam escrever código PL/SQL correto e lidar com desafios reais, além de otimizar o desempenho do banco de dados. Recomendo que você consulte a documentação oficial da Oracle sobre PL/SQL Language Reference para obter um guia detalhado e as práticas recomendadas sobre PL/SQL. O Oracle Live SQL (Interactive PL/SQL Playground) fornece acesso à plataforma baseada em nuvem da Oracle para a execução de consultas PL/SQL on-line. Também incentivo você a participar da Oracle Community para interagir com especialistas e desenvolvedores da Oracle e do fórum Stack Overflow para encontrar soluções para perguntas relacionadas a PL/SQL.
No entanto, nada supera um caminho de aprendizado estruturado. Por esse motivo, recomendo enfaticamente que você faça nosso curso Introdução ao Oracle SQL, que é, na minha opinião, a melhor maneira de se tornar um especialista. Além disso, se você quiser aprimorar seu conhecimento sobre como trabalhar com bancos de dados, também recomendo fazer nosso curso Database Design, no qual você aprenderá a criar e gerenciar bancos de dados e a selecionar o DBMS adequado às suas necessidades. Por fim, experimente nosso curso de carreira Associate Data Engineer in SQL para aprender os fundamentos da engenharia de dados e do armazenamento de dados.
Por último, mas não menos importante, se você estiver entrevistando candidatos e quiser também aprimorar as habilidades de outras pessoas, entre em contato com nossa equipe do DataCamp for Business. O DataCamp pode aprimorar as habilidades de equipes inteiras com projetos práticos e caminhos de aprendizagem personalizados. Essa é uma ótima maneira de os empregadores preencherem as lacunas de habilidades e aumentarem a confiança e a credibilidade de uma equipe.
Perguntas frequentes sobre PL SQL
O que é PL/SQL e como ele difere do SQL?
O PL/SQL é uma linguagem processual desenvolvida pela Oracle, que permite estruturas de controle e tratamento de erros, enquanto o SQL é declarativo e lida com a recuperação/manipulação de dados.
O que é um pacote PL/SQL?
Uma coleção de procedimentos, funções, variáveis e cursores relacionados para programação modular e reutilização.
Como um procedimento é diferente de uma função?
Os procedimentos executam uma ação que não retorna um valor, enquanto as funções retornam um valor que pode ser usado em consultas.
O que são acionadores no PL/SQL?
Ações automatizadas executadas 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 ao reduzir as alternâncias de contexto entre os mecanismos PL/SQL e SQL ao lidar com grandes conjuntos de dados.
Aprenda SQL com a DataCamp
curso
Data Manipulation in SQL
curso
Applying SQL to Real-World Problems

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

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

blog
As 30 principais perguntas da entrevista sobre o Excel para todos os níveis
blog
40 perguntas e respostas de entrevistas sobre programação em R para todos os níveis

blog
As 26 principais perguntas e respostas da entrevista sobre pandas em Python

Srujana Maddula
15 min

blog