cours
Les 20 meilleures questions d'entretien PL/SQL et leurs réponses en 2025
PL/SQL, qui est l'extension du langage procédural Oracle de SQL, est quelque chose que vous devez connaître si vous allez travailler avec des bases de données Oracle. C'est le cas pour des fonctions importantes telles que celles d'administrateur de base de données, de développeur et d'analyste de données, qui doivent toutes gérer une logique commerciale complexe au sein de la base de données.
Je pense que les recruteurs évaluent les candidats sur trois aspects essentiels :
- Compréhension conceptuelle : Principes de base, types de données, structures de contrôle et gestion des exceptions.
- Capacité pratique de codage : Rédiger des procédures stockées, des fonctions, des déclencheurs et des paquets efficaces.
- Considérations sur les performances : Optimisation du code PL/SQL pour améliorer le temps d'exécution, minimiser la consommation de ressources et éviter les erreurs telles que le changement excessif de contexte entre SQL et PL/SQL.
Pour vous aider, je vous propose un guide sur les questions d'entretien PL/SQL. Je commencerai par les concepts fondamentaux, puis j'aborderai des sujets plus avancés tels que le traitement en masse, le SQL dynamique et l'optimisation des performances.
Si vous souhaitez comprendre les concepts fondamentaux de la base de données Oracle, je vous recommande de suivre notre cours Introduction à Oracle SQL, qui est une ressource vraiment importante pour apprendre comment interagir avec la base de données Oracle et comment la base de données utilise PL/SQL pour traiter les requêtes.
Questions d'entretien PL/SQL pour débutants
Lors de la phase initiale de l'entretien, l'examinateur peut poser des questions fondamentales pour évaluer votre connaissance des concepts de base des bases de données et de PL/SQL. Essayez d'étudier ces questions et réponses pour vous préparer à la phase initiale de l'entretien.
1. Qu'est-ce que PL/SQL ?
PL/SQL est l'extension procédurale d'Oracle pour SQL. Contrairement à SQL, qui est déclaratif et se concentre sur l'extraction et la manipulation de données, PL/SQL permet aux développeurs de mettre en œuvre une logique procédurale, ce qui en fait un outil puissant pour l'écriture de règles commerciales complexes dans la base de données. Il prend en charge les variables, les boucles, les conditionnelles, la gestion des exceptions et la programmation modulaire par le biais de procédures, de fonctions et de paquets.
2. Quelle est la structure de base d'un bloc PL/SQL ?
Un bloc PL/SQL est l'unité fondamentale d'exécution en PL/SQL et se compose de quatre sections principales :
-
DECLARE
(facultatif) : Utilisé pour définir les variables, les constantes, les curseurs et les types définis par l'utilisateur. -
BEGIN
: La section exécutable où sont écrites les requêtes SQL et les instructions procédurales. -
EXCEPTION
(facultatif) : Gère les erreurs d'exécution et les exceptions afin d'assurer une récupération gracieuse des erreurs. -
END;
: Marque la fin du bloc.
3. Quels sont les types de données PL/SQL essentiels ?
PL/SQL prend en charge différents types de données, classés comme suit :
-
Types scalaires: Les types à valeur unique tels que
NUMBER
,VARCHAR2
,DATE
,BOOLEAN
. -
Types de composites : Collections telles que
RECORD
(structures personnalisées) etTABLE
/VARRAY
(tableaux). -
Types de référence : Pointeurs vers des objets de base de données, tels que
REF CURSOR
pour le traitement dynamique des requêtes.
4. Quelles sont les structures de contrôle de base en PL/SQL ?
PL/SQL comprend plusieurs structures de contrôle qui aident à gérer le flux d'un programme :
-
Boucles : Il s'agit notamment de
LOOP
,FOR LOOP
, etWHILE LOOP
, qui permettent l'exécution répétitive de déclarations. -
Déclarations conditionnelles : Il s'agit notamment des instructions
IF
etCASE
, qui exécutent différents blocs de code en fonction de conditions. La fonction DECODE() est un autre bon exemple de conditionnel qui mérite d'être étudié.
Questions d'entretien PL/SQL intermédiaires
Après avoir abordé les questions de base, passons maintenant à des questions d'entretien de niveau intermédiaire sur la structure des données. Après avoir testé vos connaissances de base, les examinateurs vont maintenant tester vos compétences techniques dans la mise en œuvre et l'utilisation des concepts PL/SQL.
5. Quelle est la différence entre les procédures stockées et les fonctions ?
Les procédures stockées et les fonctions sont toutes deux des blocs de code PL/SQL réutilisables, mais elles ont des objectifs assez différents.
Les procédures stockées sont utilisées pour effectuer des opérations qui ne renvoient pas de valeur, telles que l'insertion, la mise à jour ou la suppression de données. Ils sont utilisés pour les tâches qui modifient les données ou effectuent des opérations complexes sans renvoyer de résultat.
Par exemple, la procédure ci-dessous met à jour le site salary
de l'employé dont l'adresse est employee_id
en y ajoutant l'adresse p_increment
, de sorte que le salaire soit mis à jour de manière dynamique en fonction des paramètres d'entrée,
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;
Les fonctions, quant à elles, renvoient une valeur après avoir effectué des opérations. Ils conviennent aux calculs ou à la recherche de données qui doivent renvoyer un résultat.
La fonction ci-dessous simplifie la recherche du salaire d'un employé, ce qui permet de la réutiliser dans des requêtes SQL ou d'autres procédures.
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'est-ce qu'un paquet PL/SQL ?
Les packages PL/SQL sont des collections de procédures, de fonctions et de variables apparentées qui encapsulent le code pour une meilleure organisation et réutilisation. Ils se composent de deux parties :
- Spécification de l'emballage : Déclare les éléments publics (procédures, fonctions, variables).
- Corps de l'emballage : Contient les détails de la mise en œuvre des procédures et des fonctions déclarées dans la spécification.
Par exemple, la requête ci-dessous crée un paquetage employee_pkg
qui définit une procédure pour augmenter le salaire d'un employé et une fonction pour récupérer le nombre total d'employés, leurs implémentations devant être fournies dans le corps du paquetage.
-- 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. Que sont les déclencheurs PL/SQL ?
Les déclencheurs sont des blocs PL/SQL qui s'exécutent automatiquement en réponse à des événements spécifiques de la base de données, tels que des insertions, des mises à jour ou des suppressions. Les déclencheurs sont utilisés pour appliquer les règles de gestion. Ils sont également couramment utilisés pour effectuer des audits. Ils sont classés en plusieurs catégories :
- Déclencheurs au niveau de la ligne : Exécutez une fois pour chaque ligne affectée.
- Déclencheurs au niveau de la déclaration : Exécutez une fois par instruction SQL, quel que soit le nombre de lignes affectées.
La requête ci-dessous crée un déclencheur AFTER UPDATE
trg_salary_audit
sur le tableau employees
qui enregistre les modifications de salaire dans le tableau salary_audit table
, en saisissant l'ID de l'employé, l'ancien et le nouveau salaire, ainsi que l'horodatage de la mise à jour.
-- 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;
Étudiez notre tutoriel sur les déclencheurs SQL afin d'être prêt au cas où les déclencheurs seraient évoqués lors de l'entretien.
8. Quelles sont les méthodes de gestion des exceptions en PL/SQL ?
PL/SQL fournit des mécanismes de gestion des erreurs pour assurer la stabilité et éviter les pannes. Les types d'exceptions sont les suivants :
-
Exceptions prédéfinies : Les exceptions intégrées telles que
NO_DATA_FOUND
,TOO_MANY_ROWS
, etZERO_DIVIDE
. -
Exceptions définies par l'utilisateur : Les exceptions personnalisées sont déclarées à l'aide de
EXCEPTION
et levées à l'aide deRAISE
.
Par exemple, le bloc PL/SQL suivant récupère le salaire d'un employé dont l'ID est 100, lève une exception personnalisée si le salaire est inférieur à 1000 et gère les erreurs éventuelles, y compris les enregistrements d'employés manquants et les exceptions inattendues.
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;
Les meilleures pratiques en matière de gestion des exceptions sont les suivantes :
- Anticipez toujours les exceptions potentielles.
- Utilisez des messages d'erreur significatifs.
- Enregistrez les exceptions à des fins d'audit.
- Veillez à ce que le code de gestion des exceptions soit concis et axé sur la récupération.
9. Comment pouvez-vous vérifier si une instruction UPDATE est exécutée ou non ?
L'attribut SQL %NOTFOUND
peut être utilisé pour déterminer si l'instruction UPDATE
a modifié avec succès des enregistrements. Si la dernière instruction SQL exécutée n'a affecté aucune ligne, cette variable renvoie TRUE
.
Par exemple, la requête ci-dessous met à jour le salaire des employés du département 10 en l'augmentant de 10 %, puis vérifie si des lignes ont été affectées par l'instruction UPDATE
à l'aide de l'attribut %NOTFOUND
. Si aucune ligne n'a été mise à jour, il affiche un message indiquant "Aucune ligne n'a été mise à jour". Si des lignes ont été mises à jour, le nombre de lignes concernées est indiqué à l'aide de l'attribut 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;
/
Questions d'entretien avancées sur PL/SQL
Examinons maintenant quelques questions d'entretien plus poussées, au cas où vous postuleriez à un poste plus élevé exigeant davantage d'expérience.
10. Quelles sont les méthodes d'optimisation des performances en PL/SQL ?
Minimiser les changements de contexte entre SQL et PL/SQL est crucial pour optimiser les performances. Chaque commutation entraîne des frais généraux qui peuvent ralentir les temps d'exécution, en particulier dans les situations impliquant des transitions fréquentes entre les deux.
11. Comment utilisez-vous les opérations en bloc pour minimiser les changements de contexte ?
PL/SQL fournit des techniques de traitement en masse pour optimiser l'interaction entre SQL et PL/SQL en récupérant ou en modifiant plusieurs lignes à la fois.
Par exemple, le bloc PL/SQL ci-dessous récupère tous les employés du département 10 à l'aide de BULK COLLECT
dans une collection et la parcourt pour imprimer le nom de chaque employé, ce qui améliore les performances en minimisant les changements de contexte entre SQL et 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;
De plus, ce bloc PL/SQL utilise FORALL
pour la mise à jour en masse, augmentant le salaire de 10% pour les employés avec les ID 101, 102 et 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. Que sont les curseurs dynamiques SQL et Ref ?
Le SQL dynamique permet d'exécuter des instructions SQL de manière dynamique au moment de l'exécution, ce qui est utile lorsqu'il s'agit de noms de tableaux, de colonnes ou de structures de requêtes variables.
Le bloc PL/SQL suivant utilise la SQL dynamique pour compter le nombre de lignes dans le tableau employees
et imprime le résultat. J'aime ce type d'approche parce qu'elle permet une certaine flexibilité.
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;
Les curseurs Ref sont des curseurs dynamiques qui peuvent être ouverts, récupérés et fermés au moment de l'exécution, ce qui permet de transmettre les résultats des requêtes entre les unités du programme.
Le bloc PL/SQL ci-dessous utilise REF CURSOR
pour récupérer et imprimer les noms des employés du département 20. Le curseur est ouvert dynamiquement, parcouru à l'aide d'une boucle et fermé après traitement.
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. Comment gérez-vous les erreurs de mutation des tableaux ?
Les erreurs de mutation de tableau se produisent lorsqu'un déclencheur tente de modifier le tableau sur lequel il est déclenché. Un déclencheur composé permet de diviser l'exécution du déclencheur en plusieurs phases telles que BEFORE
, AFTER
, et FOR EACH ROW
afin d'éviter les problèmes de modification directe.
Le déclencheur composé ci-dessous enregistre efficacement les modifications de salaire dans le tableau salary_audit
en collectant les données avant chaque mise à jour de ligne et en effectuant une insertion en bloc après l'instruction, ce qui réduit les changements de contexte et améliore les performances.
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'est-ce que la surcharge en PL/SQL ?
La surcharge permet de définir dans un paquet plusieurs procédures ou fonctions portant le même nom mais ayant des paramètres différents. Cela permet d'améliorer la lisibilité et la maintenabilité du code en proposant plusieurs façons d'effectuer des opérations similaires.
Dans la requête ci-dessous, le corps du paquet met en œuvre deux procédures surchargées nommées update_salary
: L'une augmente le salaire d'un employé d'un montant déterminé, tandis que l'autre fixe un nouveau salaire avec une date d'entrée en vigueur, en mettant à jour le tableau employees
en conséquence.
-- 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. Quels sont les directives du compilateur et les pragmas en PL/SQL ?
PL/SQL fournit des directives de compilation (PRAGMA
) pour optimiser le code et gérer les exceptions. Les pragmas les plus courants sont les suivants :
-
PRAGMA EXCEPTION_INIT
: Associe une exception définie par l'utilisateur à un code d'erreur Oracle. -
PRAGMA SERIALLY_REUSABLE
: Optimise l'utilisation de la mémoire des paquets pour une meilleure évolutivité.
Le bloc PL/SQL ci-dessous gère l'insertion d'un employé dont le salaire n'est pas valide en utilisant une exception personnalisée e_invalid_salary
associée au code d'erreur -20001
. Si l'exception est levée, un message d'erreur est imprimé.
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. Quelles sont les différentes méthodes de traçage et de débogage du code PL/SQL ?
PL/SQL fournit plusieurs packages intégrés pour le suivi et le débogage des performances du code. Les méthodes courantes consistent à utiliser DBMS_TRACE
pour suivre le déroulement de l'exécution, DBMS_APPLICATION_INFO
pour surveiller l'activité de la session et DBMS_SESSION
pour recueillir des informations de diagnostic au niveau de la session.
La requête ci-dessous active d'abord le suivi SQL à l'aide de DBMS_SESSION.set_sql_trace(TRUE)
, puis définit les informations de session spécifiques au client à l'aide de DBMS_APPLICATION_INFO.set_client_info()
pour la surveillance. Le bloc PL/SQL est exécuté, ce qui simule une opération UPDATE
. Enfin, il désactive le traçage après l'exécution en utilisant 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;
/
Questions d'entretien PL/SQL basées sur des scénarios
Dans les applications d'entreprise réelles, PL/SQL est utilisé pour gérer une logique commerciale complexe. Les intervieweurs évaluent souvent la capacité d'un candidat à appliquer PL/SQL dans des scénarios pratiques. Vous trouverez ci-dessous quelques défis majeurs, ainsi que des stratégies pour les résoudre.
Pour cette dernière section, si vous passez un entretien, je vous encourage à réfléchir à la manière de répondre aux questions en suivant ce modèle, mais essayez, bien sûr, de réorienter votre réponse en fonction de votre secteur d'activité spécifique ou de votre propre expérience. Il en va de même si vous interrogez un candidat et que vous souhaitez avoir des idées sur la manière de poser une question et de juger de la rigueur de la réponse, auquel cas j'espère que cette section vous servira d'inspiration pour vos questions et vos critères d'évaluation.
Améliorez les compétences SQL de votre équipe
Formez votre équipe à SQL avec DataCamp for Business. Une formation complète, des projets pratiques et des indicateurs de performance détaillés pour votre organisation.

17. Comment concevoir des déclencheurs dans des environnements fortement concurrentiels ?
Supposons un scénario dans lequel vous devez appliquer une règle de gestion selon laquelle le salaire d'un employé ne peut être mis à jour plus d'une fois par jour. Cependant, la base de données connaît une forte concurrence des transactions, et un simple déclencheur pourrait entraîner des problèmes de contention ou de performance.
Au lieu d'utiliser un déclencheur au niveau de la ligne qui se déclenche pour chaque mise à jour et peut ralentir les performances, utilisez un déclencheur au niveau de la déclaration avec un tableau d'enregistrement pour empêcher plusieurs mises à jour des salaires au cours de la même journée.
Par exemple, le déclencheur ci-dessous empêche les mises à jour multiples du salaire d'un employé le même jour en vérifiant le tableau salary_update_log
avant d'autoriser une mise à jour. Si le salaire a déjà été mis à jour aujourd'hui, une erreur est soulevée ; sinon, la date de mise à jour est enregistrée.
-- 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;
L'exemple ci-dessus permet de réduire le verrouillage au niveau des lignes et de minimiser les conflits de transaction lors des mises à jour en masse.
18. Comment diviser les transactions importantes en petits morceaux pour garantir la fiabilité ?
Imaginez un scénario dans lequel un système bancaire nécessite une mise à jour en masse pour ajuster les taux d'intérêt de millions de comptes clients. L'exécution d'une seule transaction importante risque de bloquer les tableaux pendant trop longtemps ou d'entraîner des échecs de retour en arrière.
Dans ce cas, utilisez le traitement en masse avec COMMIT
en lots pour traiter les données de manière incrémentielle et éviter les conflits.
Le bloc PL/SQL ci-dessous met en œuvre la solution en utilisant BULK COLLECT
pour récupérer les identifiants de compte et les parcourir pour mettre à jour le taux d'intérêt de 5 %. Les modifications sont validées toutes les 1000 mises à jour afin d'améliorer les performances et de réduire l'utilisation des ressources. Une validation finale garantit que toutes les mises à jour restantes sont sauvegardées.
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;
/
Cette solution garantirait la fiabilité des systèmes financiers tels que les systèmes de paie en évitant les échecs de transaction.
19. Comment organiser une logique complexe en paquets pour en faciliter la maintenance ?
Une entreprise de vente au détail doit mettre en place un système de traitement des commandes qui comporte plusieurs étapes : Vérification de la disponibilité des stocks, réservation des stocks, calcul des remises et enregistrement de l'historique des transactions.
Au lieu d'écrire des procédures autonomes séparées, vous devez organiser cette logique d'une manière structurée et facile à maintenir. Par conséquent, utilisez les paquets PL/SQL pour encapsuler les procédures et les fonctions connexes, afin d'améliorer la réutilisation et la maintenance du code.
La spécification du paquet ci-dessous définit les fonctions et les procédures de traitement des commandes, y compris la vérification de l'inventaire, la réservation du stock, le calcul des remises et l'enregistrement des statuts des transactions. Il offre une approche modulaire de la gestion des tâches liées aux commandes.
-- 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;
Nous utilisons ensuite le corps du paquet suivant pour mettre en œuvre les fonctions et les procédures définies dans la spécification du paquet. Il prend en charge des tâches essentielles telles que la vérification de la disponibilité des stocks, la réservation des stocks, le calcul des remises et l'enregistrement de l'état des transactions, garantissant ainsi le bon déroulement des opérations de traitement des commandes.
-- 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. Comment gérer les blocages dans les systèmes à forte transaction ?
Supposons un scénario dans lequel un système financier met fréquemment à jour plusieurs tableaux connexes simultanément. Les blocages se produisent lorsque deux transactions attendent sur les ressources verrouillées de l'autre, ce qui provoque des goulets d'étranglement.
Pour résoudre ce problème, verrouillez toujours les lignes dans un ordre cohérent d'une transaction à l'autre. Utilisez également la clause NOWAIT
ou SKIP LOCKED
pour éviter d'attendre indéfiniment.
Par exemple, le bloc PL/SQL ci-dessous tente de verrouiller une ligne spécifique du tableau des comptes pour la mise à jour à l'aide de la clause FOR UPDATE NOWAIT
, ce qui entraîne l'échec immédiat de la transaction si une autre session verrouille déjà la ligne. Après le verrouillage, il met à jour l'état de la transaction et valide les modifications. Si une erreur se produit, il attrape l'exception et imprime un message d'erreur.
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;
/
De même, ce bloc PL/SQL traite les transactions en attente en les verrouillant pour la mise à jour avec FOR UPDATE SKIP LOCKED
, ce qui lui permet de sauter les lignes qui sont déjà verrouillées par d'autres sessions. Il met à jour le statut de chaque transaction en "Traitement" et valide les modifications à la fin.
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;
`
Conclusion et autres ressources
Pour les postes centrés sur Oracle, les employeurs recherchent des candidats capables d'écrire un code PL/SQL correct, de relever des défis réels et d'optimiser les performances des bases de données. Je vous recommande de consulter la documentation officielle d'Oracle sur la référence du langage PL/SQL pour un guide approfondi et les meilleures pratiques en matière de PL/SQL. L'Oracle Live SQL (Interactive PL/SQL Playground) permet d'accéder à la plateforme basée sur le cloud d'Oracle pour exécuter des requêtes PL/SQL en ligne. Je vous encourage également à rejoindre la communauté Oracle pour échanger avec des experts et des développeurs Oracle et le forum Stack Overflow pour trouver des solutions aux questions relatives à PL/SQL.
Cependant, rien ne vaut un parcours d'apprentissage structuré. C'est pourquoi je vous recommande vivement de suivre notre cours Introduction à Oracle SQL, qui est vraiment, à mon avis, le meilleur moyen de devenir un expert. Par ailleurs, si vous souhaitez approfondir vos connaissances en matière de bases de données, je vous recommande également de suivre notre cours sur la conception de bases de données, dans lequel vous apprendrez à créer et à gérer des bases de données et à sélectionner le SGBD le mieux adapté à vos besoins. Enfin, essayez notre cursus d'ingénieur de données associé en SQL pour apprendre les fondamentaux de l'ingénierie des données et de l'entreposage de données.
Enfin, si vous interviewez des candidats et que vous souhaitez également faire progresser d'autres personnes, prenez contact avec notre équipe DataCamp for Business. DataCamp peut faire monter en compétence des équipes entières grâce à des projets pratiques et des parcours d'apprentissage personnalisés. C'est un excellent moyen pour les employeurs de combler les écarts de compétences et de renforcer la confiance et la crédibilité d'une équipe, alors contactez notre équipe dès aujourd'hui.
FAQ PL SQL
Qu'est-ce que PL/SQL et en quoi diffère-t-il de SQL ?
PL/SQL est un langage procédural développé par Oracle, permettant des structures de contrôle et la gestion des erreurs, tandis que SQL est déclaratif et gère la récupération/manipulation des données.
Qu'est-ce qu'un package PL/SQL ?
Une collection de procédures, de fonctions, de variables et de curseurs apparentés pour une programmation modulaire et une réutilisation aisée.
En quoi une procédure diffère-t-elle d'une fonction ?
Les procédures effectuent une action qui ne renvoie pas de valeur, tandis que les fonctions renvoient une valeur qui peut être utilisée dans des requêtes.
Que sont les déclencheurs en PL/SQL ?
Actions automatisées exécutées avant ou après les opérations INSERT
, UPDATE
, DELETE
.
Qu'est-ce que le traitement en masse en PL/SQL ?
Le traitement en masse (BULK COLLECT
, FORALL
) améliore les performances en réduisant les changements de contexte entre les moteurs PL/SQL et SQL lors de la manipulation de grands ensembles de données.
Apprenez SQL avec DataCamp
cours
Data Manipulation in SQL
cours
Applying SQL to Real-World Problems
blog
Les 32 meilleures questions d'entretien sur AWS et leurs réponses pour 2024
blog
Les 20 meilleures questions d'entretien pour les flocons de neige, à tous les niveaux

Nisha Arya Ahmed
20 min
blog
Q2 2023 DataCamp Donates Digest
blog
2022-2023 Rapport annuel DataCamp Classrooms
blog
Célébration de Saghar Hazinyar : Une boursière de DataCamp Donates et une diplômée de Code to Inspire

Fereshteh Forough
4 min
blog