curso
Las 20 mejores preguntas y respuestas de entrevistas PL/SQL en 2025
PL/SQL, que es la extensión del lenguaje procedimental SQL de Oracle, es algo que debes conocer si vas a trabajar con bases de datos Oracle. Esto es cierto para funciones importantes como administrador de base de datos, desarrollador y analista de datos, todos los cuales necesitan manejar una lógica empresarial compleja dentro de la base de datos.
Creo que los entrevistadores evalúan a los candidatos en tres aspectos clave:
- Comprensión conceptual: Principios básicos, tipos de datos, estructuras de control y tratamiento de excepciones.
- Habilidad Práctica de Codificación: Escribir procedimientos almacenados, funciones, desencadenadores y paquetes eficaces.
- Consideraciones sobre el rendimiento: Optimizar el código PL/SQL para mejorar el tiempo de ejecución, minimizar el consumo de recursos y evitar errores como el cambio excesivo de contexto entre SQL y PL/SQL.
Para ayudarte, te proporciono una guía sobre preguntas de entrevista PL/SQL. Empezaré con los conceptos fundamentales y avanzaré hacia temas más avanzados como el procesamiento masivo, el SQL dinámico y el ajuste del rendimiento.
Si quieres comprender los conceptos fundamentales de la base de datos Oracle, te recomiendo que sigas nuestro curso Introducción a Oracle SQL, que es un recurso realmente importante para aprender a interactuar con la base de datos Oracle y cómo la base de datos utiliza PL/SQL para procesar las consultas.
Preguntas de la entrevista PL/SQL para principiantes
En la fase inicial de la entrevista, el entrevistador puede hacerte preguntas fundamentales para evaluar tus conocimientos sobre conceptos básicos de bases de datos y PL/SQL. Intenta estudiar estas preguntas y respuestas para prepararte para la fase inicial de la entrevista.
1. ¿Qué es PL/SQL?
PL/SQL es la extensión procedimental de Oracle para SQL. A diferencia de SQL, que es declarativo y se centra en la recuperación y manipulación de datos, PL/SQL permite a los desarrolladores implementar lógica procedimental, lo que lo convierte en una potente herramienta para escribir reglas empresariales complejas dentro de la base de datos. Admite variables, bucles, condicionales, manejo de excepciones y programación modular mediante procedimientos, funciones y paquetes.
2. ¿Cuál es la estructura básica de un bloque PL/SQL?
Un bloque PL/SQL es la unidad fundamental de ejecución en PL/SQL, y consta de cuatro secciones principales:
-
DECLARE
(Opcional): Se utiliza para definir variables, constantes, cursores y tipos definidos por el usuario. -
BEGIN
: La sección ejecutable donde se escriben las consultas SQL y las sentencias procedimentales. -
EXCEPTION
(Opcional): Gestiona los errores y excepciones en tiempo de ejecución para garantizar una recuperación de errores ágil. -
END;
: Marca el final del bloque.
3. ¿Cuáles son los tipos de datos PL/SQL esenciales?
PL/SQL admite varios tipos de datos, clasificados como sigue:
-
Tipos escalares: Tipos de valor único como
NUMBER
,VARCHAR2
,DATE
,BOOLEAN
. -
Tipos de compuestos: Colecciones como
RECORD
(estructuras personalizadas) yTABLE
/VARRAY
(matrices). -
Tipos de referencia: Punteros a objetos de la base de datos, como
REF CURSOR
para el procesamiento dinámico de consultas.
4. ¿Cuáles son las estructuras de control básicas en PL/SQL?
PL/SQL incluye varias estructuras de control que ayudan a gestionar el flujo de un programa:
-
Bucles: Entre ellas están
LOOP
,FOR LOOP
, yWHILE LOOP
, que permiten la ejecución repetitiva de sentencias. -
Declaraciones condicionales: Entre ellas están las sentencias
IF
yCASE
, que ejecutan diferentes bloques de código en función de las condiciones. La función DECODE( ) es otro buen ejemplo de condicional que merece la pena estudiar.
Preguntas de la entrevista PL/SQL intermedio
Una vez cubiertas las preguntas básicas, pasemos ahora a algunas preguntas de nivel intermedio de la entrevista sobre estructura de datos. Después de comprobar tus conocimientos básicos, los entrevistadores van a comprobar ahora tu competencia técnica en la aplicación y el uso de conceptos PL/SQL.
5. ¿Cuál es la diferencia entre procedimientos almacenados y funciones?
Tanto los procedimientos almacenados como las funciones son bloques de código PL/SQL reutilizables, pero tienen finalidades bastante distintas.
Los procedimientos almacenados se utilizan para realizar operaciones que no devuelven un valor, como insertar, actualizar o eliminar datos. Se utilizan para tareas que modifican datos o realizan operaciones complejas sin devolver un resultado.
Por ejemplo, el procedimiento siguiente actualiza el salary
del empleado con el employee_id
dado añadiendo el p_increment
especificado, de forma que el salario se actualice dinámicamente en función de los 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;
Las funciones, en cambio, devuelven un valor tras realizar operaciones. Son adecuados para cálculos o recuperación de datos que necesitan devolver un resultado.
La siguiente función simplifica la obtención del salario de un empleado, haciéndola reutilizable en consultas SQL u otros procedimientos.
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. ¿Qué son los paquetes PL/SQL?
Los paquetes PL/SQL son colecciones de procedimientos, funciones y variables relacionados que encapsulan el código para una mejor organización y reutilización. Constan de dos partes:
- Especificaciones del paquete: Declara elementos públicos (procedimientos, funciones, variables).
- Cuerpo del paquete: Contiene los detalles de implementación de los procedimientos y funciones declarados en la especificación.
Por ejemplo, la consulta siguiente crea un paquete employee_pkg
que define un procedimiento para aumentar el salario de un empleado y una función para recuperar el número total de empleados, cuyas implementaciones se proporcionarán en el cuerpo del paquete.
-- 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. ¿Qué son los disparadores PL/SQL?
Los activadores son bloques PL/SQL que se ejecutan automáticamente en respuesta a eventos específicos de la base de datos, como inserciones, actualizaciones o eliminaciones. Los desencadenantes se utilizan para aplicar reglas de negocio. También se utilizan habitualmente para realizar auditorías. Se clasifican en:
- Desencadenantes a nivel de fila: Ejecutar una vez por cada fila afectada.
- Activadores a nivel de declaración: Ejecutar una vez por sentencia SQL, independientemente del número de filas afectadas.
La siguiente consulta crea un disparador AFTER UPDATE
trg_salary_audit
en la tabla employees
que registra los cambios de salario en salary_audit table
, capturando el ID del empleado, el salario antiguo y el nuevo, y la marca de tiempo de actualización.
-- 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;
Estudia nuestro tutorial sobre Triggers SQL para estar preparado en caso de que saquen el tema de los triggers en la entrevista.
8. ¿Cuáles son los métodos de gestión de excepciones en PL/SQL?
PL/SQL proporciona mecanismos de gestión de errores para la estabilidad y para evitar fallos. Los tipos de excepciones son los siguientes:
-
Excepciones predefinidas: Excepciones incorporadas como
NO_DATA_FOUND
,TOO_MANY_ROWS
, yZERO_DIVIDE
. -
Excepciones definidas por el usuario: Las excepciones personalizadas se declaran con
EXCEPTION
y se plantean conRAISE
.
Por ejemplo, el siguiente bloque PL/SQL recupera el salario de un empleado con ID 100, lanza una excepción personalizada si el salario es inferior a 1000 y gestiona los posibles errores, incluidos los registros de empleados que falten y las excepciones 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;
Las mejores prácticas para la gestión de excepciones incluyen lo siguiente:
- Prevé siempre posibles excepciones.
- Utiliza mensajes de error significativos.
- Registra las excepciones para la auditoría.
- Mantén el código de gestión de excepciones conciso y centrado en la recuperación.
9. ¿Cómo puedes verificar si una sentencia UPDATE se ejecuta o no?
El atributo SQL %NOTFOUND
puede utilizarse para determinar si la sentencia UPDATE
modificó o no con éxito algún registro. Si la última sentencia SQL ejecutada no afectó a ninguna fila, esta variable devuelve TRUE
.
Por ejemplo, la siguiente consulta actualiza el salario de los empleados del departamento 10 aumentándolo un 10%, y luego comprueba si alguna fila se ha visto afectada por la sentencia UPDATE
utilizando el atributo %NOTFOUND
. Si no se actualizó ninguna fila, muestra un mensaje que dice: "No se actualizó ninguna fila". Si se actualizaron filas, indica el número de filas afectadas mediante el 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;
/
Preguntas avanzadas de la entrevista PL/SQL
Exploremos ahora algunas preguntas avanzadas de la entrevista en caso de que solicites un puesto más alto que requiera más experiencia.
10. ¿Cuáles son los métodos para optimizar el rendimiento en PL/SQL?
Minimizar los cambios de contexto entre SQL y PL/SQL es crucial para optimizar el rendimiento. Cada conmutador incurre en una sobrecarga, que puede ralentizar los tiempos de ejecución, especialmente en situaciones que implican transiciones frecuentes entre ambos.
11. ¿Cómo utilizas las operaciones masivas para minimizar los cambios de contexto?
PL/SQL proporciona técnicas de procesamiento masivo para optimizar la interacción SQL-PL/SQL mediante la obtención o modificación de varias filas a la vez.
Por ejemplo, el bloque PL/SQL siguiente recupera todos los empleados del departamento 10 mediante BULK COLLECT
en una colección e itera a través de ella para imprimir el nombre de cada empleado, mejorando el rendimiento al minimizar los cambios de contexto entre SQL y 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;
Además, este bloque PL/SQL utiliza FORALL
para la actualización masiva, aumentando el salario en un 10% para los empleados con ID 101, 102 y 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. ¿Qué son el SQL dinámico y los cursores de referencia?
El SQL Dinámico permite ejecutar sentencias SQL dinámicamente en tiempo de ejecución, lo que resulta útil cuando se trabaja con nombres de tablas, columnas o estructuras de consulta variables.
El siguiente bloque PL/SQL utiliza SQL dinámico para contar el número de filas de la tabla employees
e imprime el resultado. Me gusta este tipo de enfoque porque permite flexibilidad.
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;
Los cursores de referencia son cursores dinámicos que pueden abrirse, obtenerse y cerrarse en tiempo de ejecución, permitiendo el paso de resultados de consulta entre unidades de programa.
El bloque PL/SQL siguiente utiliza un REF CURSOR
para obtener e imprimir los nombres de los empleados del departamento 20. El cursor se abre dinámicamente, se itera mediante un bucle y se cierra después de procesarlo.
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. ¿Cómo se gestionan los errores de la tabla mutante?
Los errores de mutación de tabla se producen cuando un disparador intenta modificar la tabla sobre la que se dispara. Un disparador compuesto permite dividir la ejecución del disparador en varias fases, como BEFORE
, AFTER
y FOR EACH ROW
, para evitar problemas de modificación directa.
El desencadenador compuesto que se muestra a continuación registra los cambios salariales en la tabla salary_audit
de forma eficiente, recogiendo datos antes de cada actualización de fila y realizando una inserción masiva después de la sentencia, reduciendo los cambios de contexto y mejorando el rendimiento.
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. ¿Qué es la sobrecarga en PL/SQL?
La sobrecarga permite definir dentro de un paquete varios procedimientos o funciones con el mismo nombre pero diferentes parámetros. Esto mejora la legibilidad y la mantenibilidad del código al proporcionar múltiples formas de realizar operaciones similares.
En la siguiente consulta, el cuerpo del paquete implementa dos procedimientos sobrecargados llamados update_salary
: Una aumenta el salario de un empleado en una cantidad determinada, mientras que la otra establece un nuevo salario con una fecha de entrada en vigor, actualizando la tabla employees
en consecuencia.
-- 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. ¿Qué son las directivas del compilador y los pragmas en PL/SQL?
PL/SQL proporciona directivas del compilador (PRAGMA
) para optimizar el código y gestionar las excepciones. Los pragmas habituales son
-
PRAGMA EXCEPTION_INIT
: Asocia una excepción definida por el usuario con un código de error de Oracle. -
PRAGMA SERIALLY_REUSABLE
: Optimiza el uso de la memoria del paquete para que sea escalable.
El siguiente bloque PL/SQL gestiona la inserción de un empleado con un salario no válido utilizando una excepción personalizada e_invalid_salary
asignada al código de error -20001
. Si se produce una excepción, imprime un mensaje de error.
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. ¿Cuáles son los distintos métodos para rastrear y depurar código PL/SQL?
PL/SQL proporciona varios paquetes incorporados para rastrear y depurar el rendimiento del código. Entre los métodos habituales se incluyen el uso de DBMS_TRACE
para realizar un seguimiento del flujo de ejecución, DBMS_APPLICATION_INFO
para controlar la actividad de la sesión y DBMS_SESSION
para recopilar información de diagnóstico a nivel de sesión.
La siguiente consulta habilita primero el rastreo SQL mediante DBMS_SESSION.set_sql_trace(TRUE)
, y luego establece la información de sesión específica del cliente con DBMS_APPLICATION_INFO.set_client_info()
para su supervisión. Se ejecuta el bloque PL/SQL, que simula una operación UPDATE
. Por último, desactiva el rastreo tras la ejecución utilizando 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;
/
Preguntas de la entrevista PL/SQL basadas en escenarios
En las aplicaciones empresariales del mundo real, PL/SQL se utiliza para manejar lógica empresarial compleja. Los entrevistadores suelen evaluar la capacidad de un candidato para aplicar PL/SQL en escenarios prácticos. A continuación se presentan algunos retos clave, junto con estrategias para resolverlos.
Para esta siguiente y última sección, si te están entrevistando, te animo a que pienses en cómo responder a las preguntas siguiendo esta plantilla, pero intenta, por supuesto, reorientar tu respuesta para tu sector específico o para reflejar tu propia experiencia. Lo mismo ocurre si estás entrevistando a un candidato y quieres ideas sobre cómo formular una pregunta y juzgar lo exhaustiva que es la respuesta, en cuyo caso espero que esta sección te sirva de inspiración tanto para tus preguntas como para tus criterios de evaluación.
Aumenta la competencia SQL de tu equipo
Forma a tu equipo en SQL con DataCamp para empresas. Formación completa, proyectos prácticos y métricas de rendimiento detalladas para tu organización.

17. ¿Cómo se diseñan los activadores en entornos muy concurrentes?
Supongamos un escenario en el que necesitas aplicar una regla de negocio según la cual el salario de un empleado no puede actualizarse más de una vez al día. Sin embargo, la base de datos experimenta una alta concurrencia de transacciones, y un simple activador podría provocar problemas de contención o rendimiento.
En lugar de utilizar un disparador a nivel de fila que se dispara para cada actualización y puede ralentizar el rendimiento, utiliza un disparador a nivel de sentencia con una tabla de registro para evitar múltiples actualizaciones salariales en el mismo día.
Por ejemplo, el desencadenador que aparece a continuación impide que se actualicen varios sueldos de un empleado el mismo día, comprobando la tabla salary_update_log
antes de permitir una actualización. Si el salario ya se ha actualizado hoy, se produce un error; en caso contrario, se registra la fecha de actualización.
-- 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;
El ejemplo anterior reduciría el bloqueo a nivel de fila y minimizaría los conflictos de transacción durante las actualizaciones masivas.
18. ¿Cómo divides las transacciones grandes en trozos más pequeños para que sean fiables?
Imagina un escenario en el que un sistema bancario requiere una actualización masiva para ajustar los tipos de interés de millones de cuentas de clientes. Ejecutar una única transacción grande puede bloquear tablas durante demasiado tiempo o provocar fallos de reversión.
En este caso, utiliza el procesamiento masivo con COMMIT
por lotes para procesar los datos de forma incremental y evitar la contención.
El siguiente bloque PL/SQL implementa la solución utilizando BULK COLLECT
para obtener los ID de cuenta y, a continuación, itera a través de ellos para actualizar el tipo de interés en un 5%. Compila los cambios cada 1000 actualizaciones para mejorar el rendimiento y reducir el uso de recursos. Una confirmación final garantiza que se guarden las actualizaciones restantes.
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;
/
Esta solución garantizaría la fiabilidad de los sistemas financieros, como las nóminas, evitando fallos en las transacciones.
19. ¿Cómo organizas la lógica compleja en paquetes para facilitar su mantenimiento?
Una empresa minorista necesita implantar un sistema de procesamiento de pedidos que implica múltiples pasos: Comprobar la disponibilidad de inventario, reservar existencias, calcular descuentos y registrar el historial de transacciones.
En lugar de escribir procedimientos independientes por separado, tienes que organizar esta lógica de forma estructurada y mantenible. Por lo tanto, utiliza paquetes PL/SQL para encapsular procedimientos y funciones relacionados, mejorando la reutilización y mantenimiento del código.
La especificación del paquete que aparece a continuación define funciones y procedimientos para el procesamiento de pedidos, incluida la comprobación del inventario, la reserva de existencias, el cálculo de descuentos y el registro de los estados de las transacciones. Proporciona un enfoque modular para gestionar las tareas relacionadas con los 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;
A continuación, utilizamos el siguiente cuerpo de paquete para aplicar las funciones y procedimientos definidos en la especificación del paquete. Se encarga de tareas clave como comprobar la disponibilidad de inventario, reservar existencias, calcular descuentos y registrar el estado de las transacciones, garantizando operaciones fluidas de procesamiento de pedidos.
-- 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. ¿Cómo se gestionan los bloqueos en sistemas con muchas transacciones?
Supongamos un escenario en el que un sistema financiero actualiza con frecuencia varias tablas relacionadas simultáneamente. Los bloqueos se producen cuando dos transacciones esperan en los recursos bloqueados de la otra, provocando cuellos de botella en el rendimiento.
Para resolver este problema, bloquea siempre las filas en un orden coherente en todas las transacciones. Utiliza también la cláusula NOWAIT
o SKIP LOCKED
para evitar esperas indefinidas.
Por ejemplo, el siguiente bloque PL/SQL intenta bloquear una fila concreta de la tabla de cuentas para la actualización mediante la cláusula FOR UPDATE NOWAIT
, lo que hace que la transacción falle inmediatamente si otra sesión ya ha bloqueado la fila. Tras el bloqueo, actualiza el estado de la transacción y confirma los cambios. Si se produce un error, captura la excepción e imprime un mensaje de error.
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;
/
Del mismo modo, este bloque PL/SQL procesa las transacciones pendientes bloqueándolas para su actualización con FOR UPDATE SKIP LOCKED
, lo que le permite saltarse las filas que ya están bloqueadas por otras sesiones. Actualiza el estado de cada transacción a "Procesando" y confirma los cambios al 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;
`
Conclusión y otros recursos
Para los puestos centrados en Oracle, los empleadores buscan candidatos que puedan escribir código PL/SQL correcto y afrontar retos de la vida real, así como optimizar el rendimiento de la base de datos. Te recomiendo que consultes la documentación oficial de Oracle sobre Referencia del Lenguaje PL/SQL para obtener una guía detallada y las mejores prácticas sobre PL/SQL. Oracle Live SQL (Interactive PL/SQL Playground) proporciona acceso a la plataforma de Oracle basada en la nube para ejecutar consultas PL/SQL en línea. También te animo a que te unas a la Comunidad Oracle para relacionarte con expertos y desarrolladores de Oracle y al foro Stack Overflow para encontrar soluciones a preguntas relacionadas con PL/SQL.
Sin embargo, no hay nada mejor que un itinerario de aprendizaje estructurado. Por esta razón, te recomiendo encarecidamente que sigas nuestro curso Introducción a Oracle SQL, que es realmente, en mi opinión, la mejor forma de convertirte realmente en un experto. Además, si quieres avanzar en tus conocimientos sobre el trabajo con bases de datos, también te recomiendo que sigas nuestro curso de Diseño de Bases de Datos, donde aprenderás a crear y gestionar bases de datos y a seleccionar el SGBD adecuado a tus necesidades. Por último, prueba nuestro itinerario profesional de Ingeniero de Datos Asociado en SQL para aprender los fundamentos de la ingeniería de datos y el almacenamiento de datos.
Por último, pero no por ello menos importante, si estás entrevistando a candidatos y también quieres capacitar a otros, ponte en contacto con nuestro equipo de DataCamp para empresas. DataCamp puede capacitar a equipos enteros con proyectos prácticos y rutas de aprendizaje personalizadas. Es una forma estupenda de que los empresarios cubran las lagunas de cualificación y aumenten la confianza y credibilidad de un equipo, así que ponte en contacto con nuestro equipo hoy mismo.
PL SQL Preguntas frecuentes
¿Qué es PL/SQL y en qué se diferencia de SQL?
PL/SQL es un lenguaje procedimental desarrollado por Oracle, que permite estructuras de control y gestión de errores, mientras que SQL es declarativo y se encarga de la recuperación/manipulación de datos.
¿Qué es un paquete PL/SQL?
Una colección de procedimientos, funciones, variables y cursores relacionados para la programación modular y la reutilización.
¿En qué se diferencia un procedimiento de una función?
Los procedimientos realizan una acción que no devuelve ningún valor, mientras que las funciones devuelven un valor que puede utilizarse en consultas.
¿Qué son los disparadores en PL/SQL?
Acciones automatizadas ejecutadas antes o después de las operaciones INSERT
, UPDATE
, DELETE
.
¿Qué es el procesamiento masivo en PL/SQL?
El procesamiento masivo (BULK COLLECT
, FORALL
) mejora el rendimiento al reducir los cambios de contexto entre los motores PL/SQL y SQL cuando se manejan grandes conjuntos de datos.
Aprende SQL con DataCamp
curso
Data Manipulation in SQL
curso
Applying SQL to Real-World Problems
blog
Las 23 mejores preguntas y respuestas de entrevistas sobre Python

blog
Las 39 mejores preguntas y respuestas de entrevistas sobre ingeniería de datos en 2025

blog
Las 30 mejores preguntas de entrevista sobre Excel para todos los niveles

blog
20 preguntas principales de la entrevista sobre SQL Joins

blog