Ga naar hoofdinhoud

Top 20 PL/SQL-sollicitatievragen en -antwoorden in 2026

Bereid je voor op PL/SQL-interviews met kernonderwerpen zoals functies, triggers, dynamische SQL, foutafhandeling, best practices en scenariogebaseerde vragen uit de praktijk.
Bijgewerkt 16 apr 2026  · 10 min lezen

PL/SQL, de procedurele taaluitbreiding van Oracle op SQL, moet je kennen als je met Oracle-databases gaat werken. Dit geldt voor belangrijke rollen zoals databasebeheerder, ontwikkelaar en data-analist, die allemaal complexe bedrijfslogica binnen de database moeten afhandelen.

Ik denk dat interviewers kandidaten op drie kernaspecten beoordelen:

  • Conceptueel begrip: Kernprincipes, datatypen, besturingsstructuren en exception handling.
  • Praktische codeervaardigheid: Efficiënte stored procedures, functies, triggers en packages schrijven.
  • Prestatie-overwegingen: PL/SQL-code optimaliseren om de uitvoeringstijd te verbeteren, het verbruik van resources te minimaliseren en fouten te vermijden, zoals overmatig contextswitching tussen SQL en PL/SQL.

Om je te helpen, geef ik een gids met PL/SQL-sollicitatievragen. Ik begin met de fundamentele concepten en ga daarna verder met meer gevorderde onderwerpen zoals bulkverwerking, dynamische SQL en performance tuning.

Als je de basisconcepten van de Oracle-database wilt begrijpen, raad ik onze cursus Introduction to Oracle SQL aan, een heel belangrijke bron om te leren hoe je met de Oracle-database werkt en hoe de database PL/SQL gebruikt om queries te verwerken.

Beginner PL/SQL-sollicitatievragen

In de eerste interviewfase kan de interviewer basisvragen stellen om je kennis van algemene database- en PL/SQL-concepten te toetsen. Bestudeer deze vragen en antwoorden om je voor te bereiden op de beginfase van het interview.

1. Wat is PL/SQL?

PL/SQL is Oracle’s procedurele uitbreiding op SQL. In tegenstelling tot SQL, dat declaratief is en zich richt op het ophalen en manipuleren van data, laat PL/SQL ontwikkelaars procedurele logica implementeren. Dat maakt het een krachtig hulpmiddel om complexe bedrijfsregels binnen de database te schrijven. Het ondersteunt variabelen, lussen, conditionals, exception handling en modulair programmeren via procedures, functies en packages.

2. Wat is de basisstructuur van een PL/SQL-blok?

Een PL/SQL-blok is de fundamentele uitvoereenheid in PL/SQL en bestaat uit vier hoofdsecties:

  • DECLARE (optioneel): Gebruikt om variabelen, constanten, cursors en zelfgedefinieerde typen te definiëren.

  • BEGIN: De uitvoerbare sectie waar SQL-queries en procedurele statements worden geschreven.

  • EXCEPTION (optioneel): Handelt runtime-fouten en exceptions af om nette foutafhandeling te garanderen.

  • END;: Markeert het einde van het blok.

3. Wat zijn de essentiële PL/SQL-datatypen?

PL/SQL ondersteunt verschillende datatypen, ingedeeld als volgt:

  • Scalartypen: Enkelvoudige typen zoals NUMBER, VARCHAR2, DATE, BOOLEAN.

  • Samengestelde typen: Collecties zoals RECORD (aangepaste structuren) en TABLE/VARRAY (arrays).

  • Referentietypen: Pointers naar databaseobjecten, zoals REF CURSOR voor dynamische queryverwerking.

4. Wat zijn de basisbesturingsstructuren in PL/SQL?

PL/SQL bevat verschillende besturingsstructuren die helpen de programmalogica te sturen:

  • Lussen: Dit zijn LOOP, FOR LOOP en WHILE LOOP, waarmee je herhaaldelijk statements kunt uitvoeren.

  • Voorwaardelijke statements: Dit zijn IF- en CASE-statements, die verschillende codeblokken uitvoeren op basis van voorwaarden. De DECODE()-functie is nog een goed voorbeeld van een conditional dat het bestuderen waard is. 

Gevorderde basisvragen over PL/SQL

Nu we de basisvragen behandeld hebben, gaan we door naar vragen op gemiddeld niveau over datastructuren. Nadat je basiskennis is getest, gaan interviewers nu je technische vaardigheid toetsen in het implementeren en gebruiken van PL/SQL-concepten.

5. Wat is het verschil tussen stored procedures en functies?

Stored procedures en functies zijn beide herbruikbare PL/SQL-codeblokken, maar ze dienen verschillende doelen.

Stored procedures worden gebruikt om bewerkingen uit te voeren die geen waarde retourneren, zoals het invoegen, bijwerken of verwijderen van data. Ze worden gebruikt voor taken die data wijzigen of complexe handelingen uitvoeren zonder een resultaat terug te geven.

Zo werkt de onderstaande procedure de salary van de werknemer met het opgegeven employee_id bij door de opgegeven p_increment toe te voegen, zodat het salaris dynamisch wordt bijgewerkt op basis van de invoerparameters,

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;

Functies daarentegen geven na het uitvoeren van bewerkingen een waarde terug. Ze zijn geschikt voor berekeningen of dataopvragingen die een resultaat moeten retourneren.

De onderstaande functie vereenvoudigt het ophalen van het salaris van een werknemer, waardoor deze herbruikbaar is in SQL-queries of andere procedures.

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. Wat zijn PL/SQL-packages?

PL/SQL-packages zijn verzamelingen van gerelateerde procedures, functies en variabelen die code inkapselen voor betere organisatie en hergebruik. Ze bestaan uit twee delen:

  • Package Specification: Declareert publieke elementen (procedures, functies, variabelen).
  • Package Body: Bevat de implementatiedetails van de procedures en functies die in de specification zijn gedeclareerd.

Het onderstaande voorbeeld maakt een package employee_pkg die een procedure definieert om het salaris van een werknemer te verhogen en een functie om het totale aantal werknemers op te halen; de implementaties worden in de package body opgenomen.

-- 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. Wat zijn PL/SQL-triggers?

Triggers zijn PL/SQL-blokken die automatisch worden uitgevoerd als reactie op specifieke database-events, zoals inserts, updates of deletes. Triggers worden gebruikt om bedrijfsregels af te dwingen en ook vaak voor auditing. Ze worden als volgt gecategoriseerd:

  • Row-level triggers: Worden één keer uitgevoerd voor elke getroffen rij.
  • Statement-level triggers: Worden één keer per SQL-statement uitgevoerd, ongeacht het aantal getroffen rijen.

De onderstaande query maakt een AFTER UPDATE-trigger trg_salary_audit op de tabel employees die salariswijzigingen logt in de tabel salary_audit, waarbij het werknemers-ID, oud en nieuw salaris en de datum/tijd van de update worden vastgelegd.

-- 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;

Bestudeer onze tutorial over SQL-triggers zodat je klaar bent als triggers in het interview ter sprake komen. 

8. Wat zijn de methoden voor exception handling in PL/SQL?

PL/SQL biedt mechanismen voor foutafhandeling voor stabiliteit en om crashes te voorkomen. De typen exceptions omvatten het volgende:

  • Vooraf gedefinieerde exceptions: Ingebouwde exceptions zoals NO_DATA_FOUND, TOO_MANY_ROWS en ZERO_DIVIDE.

  • Door de gebruiker gedefinieerde exceptions: Aangepaste exceptions worden gedeclareerd met EXCEPTION en opgewekt met RAISE.

In het volgende PL/SQL-blok wordt het salaris van een werknemer met ID 100 opgehaald, een aangepaste exception opgewekt als het salaris lager is dan 1000, en worden mogelijke fouten afgehandeld, waaronder ontbrekende werknemersrecords en onverwachte exceptions.

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;

De best practices voor exception handling zijn onder meer:

  • Voorzie altijd mogelijke exceptions.
  • Gebruik betekenisvolle foutmeldingen.
  • Log exceptions voor auditing.
  • Houd code voor exception handling beknopt en gericht op herstel.

9. Hoe kun je verifiëren of een UPDATE-statement is uitgevoerd of niet?

Het SQL-attribuut %NOTFOUND kan worden gebruikt om te bepalen of het UPDATE-statement records heeft gewijzigd. Als het laatst uitgevoerde SQL-statement geen rijen beïnvloedde, retourneert deze variabele TRUE.

In het onderstaande voorbeeld wordt het salaris van werknemers in afdeling 10 met 10% verhoogd en wordt daarna gecontroleerd of het UPDATE-statement rijen heeft beïnvloed met het %NOTFOUND-attribuut. Als er geen rijen zijn bijgewerkt, wordt het bericht "No rows were updated." uitgegeven. Als er wel rijen zijn bijgewerkt, wordt het aantal getroffen rijen uitgegeven met het attribuut 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;
/

Geavanceerde PL/SQL-sollicitatievragen

Laten we nu enkele geavanceerde interviewvragen verkennen voor het geval je solliciteert naar een meer senior rol die meer ervaring vereist.

10. Wat zijn methoden om prestaties te optimaliseren in PL/SQL?

Het minimaliseren van contextswitches tussen SQL en PL/SQL is cruciaal voor prestatie-optimalisatie. Elke switch brengt overhead met zich mee, wat de uitvoering kan vertragen, vooral in situaties met frequente overgangen tussen beide.

11. Hoe gebruik je bulkoperaties om contextswitches te minimaliseren?

PL/SQL biedt bulkverwerkingstechnieken om de interactie tussen SQL en PL/SQL te optimaliseren door meerdere rijen tegelijk op te halen of te wijzigen.

In het onderstaande PL/SQL-blok worden alle werknemers uit afdeling 10 opgehaald met BULK COLLECT in een collectie en wordt er doorheen gelust om ieders naam af te drukken, wat de prestaties verbetert door contextswitches tussen SQL en PL/SQL te minimaliseren.

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;

Ook gebruikt dit PL/SQL-blok FORALL voor bulkupdates, waarbij het salaris met 10% wordt verhoogd voor werknemers met ID’s 101, 102 en 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. Wat zijn dynamische SQL en Ref Cursors?

Dynamische SQL maakt het mogelijk om SQL-statements dynamisch tijdens runtime uit te voeren, wat handig is bij variabele tabelnamen, kolommen of querystructuren.

Het volgende PL/SQL-blok gebruikt dynamische SQL om het aantal rijen in de tabel employees te tellen en het resultaat af te drukken. Ik houd van deze aanpak omdat die flexibiliteit biedt.

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 zijn dynamische cursors die tijdens runtime kunnen worden geopend, opgehaald en gesloten, waardoor je queryresultaten tussen programmadelen kunt doorgeven.

In het onderstaande PL/SQL-blok wordt een REF CURSOR gebruikt om de namen van werknemers uit afdeling 20 op te halen en af te drukken. De cursor wordt dynamisch geopend, met een lus doorlopen en na verwerking gesloten.

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. Hoe ga je om met mutating table-fouten?

Mutating table-fouten treden op wanneer een trigger probeert de tabel te wijzigen waarop hij is geactiveerd. Een samengestelde trigger (compound trigger) maakt het mogelijk de uitvoering op te splitsen in meerdere fasen zoals BEFORE, AFTER en FOR EACH ROW om directe wijzigingsproblemen te voorkomen.

De onderstaande compound trigger logt salariswijzigingen in de tabel salary_audit door gegevens te verzamelen vóór elke rij-update en na het statement een bulk insert uit te voeren, waardoor contextswitches worden verminderd en de prestaties verbeteren.

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. Wat is overloading in PL/SQL?

Overloading maakt het mogelijk om meerdere procedures of functies met dezelfde naam maar verschillende parameters binnen een package te definiëren. Dit verbetert de leesbaarheid en het onderhoud van de code door meerdere manieren te bieden om vergelijkbare bewerkingen uit te voeren.

In de onderstaande query implementeert de package body twee overbelaste procedures met de naam update_salary: de ene verhoogt het salaris van een werknemer met een opgegeven bedrag, de andere stelt een nieuw salaris in met een ingangsdatum en werkt de tabel employees dienovereenkomstig bij.

-- 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. Wat zijn compiler directives en pragmas in PL/SQL?

PL/SQL biedt compiler directives (PRAGMA) om code te optimaliseren en exceptions af te handelen. Veelgebruikte pragmas zijn:

  • PRAGMA EXCEPTION_INIT: Koppelt een door de gebruiker gedefinieerde exception aan een Oracle-foutcode.

  • PRAGMA SERIALLY_REUSABLE: Optimaliseert het geheugengebruik van packages voor schaalbaarheid.

In het onderstaande PL/SQL-blok wordt het invoegen van een werknemer met een ongeldig salaris afgehandeld door een aangepaste exception e_invalid_salary te gebruiken die is gekoppeld aan foutcode -20001. Als de exception wordt opgewekt, wordt een foutmelding afgedrukt.

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. Wat zijn de verschillende methoden om PL/SQL-code te traceren en te debuggen?

PL/SQL biedt verschillende ingebouwde packages om codeprestatie te traceren en te debuggen. Veelgebruikte methoden zijn DBMS_TRACE om de uitvoeringsstroom te volgen, DBMS_APPLICATION_INFO om sessie-activiteit te monitoren en DBMS_SESSION om diagnostische informatie op sessieniveau te verzamelen.

De onderstaande query schakelt eerst SQL-tracing in met DBMS_SESSION.set_sql_trace(TRUE), stelt vervolgens client-specifieke sessie-informatie in met DBMS_APPLICATION_INFO.set_client_info() voor monitoring. Het PL/SQL-blok wordt uitgevoerd, wat een UPDATE-bewerking simuleert. Tot slot wordt tracing uitgeschakeld na de uitvoering met 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;
/

Scenariogebaseerde PL/SQL-sollicitatievragen

In bedrijfstoepassingen in de echte wereld wordt PL/SQL gebruikt om complexe bedrijfslogica af te handelen. Interviewers beoordelen vaak het vermogen van een kandidaat om PL/SQL in praktische scenario’s toe te passen. Hieronder staan enkele belangrijke uitdagingen met strategieën om ze op te lossen.

Voor dit volgende en laatste deel, als je aan het interviewen bent, raad ik je aan om na te denken over hoe je vragen volgens dit sjabloon beantwoordt, maar probeer je antwoord natuurlijk te heroriënteren op jouw specifieke branche of om je eigen ervaring te weerspiegelen. Hetzelfde geldt als je een kandidaat interviewt en ideeën wilt over hoe je een vraag stelt en hoe je beoordeelt hoe volledig het antwoord is; in dat geval hoop ik dat dit deel dient als inspiratie voor zowel je vragen als je beoordelingscriteria.

17. Hoe ontwerp je triggers in sterk gelijktijdige omgevingen?

Ga uit van een scenario waarin je een bedrijfsregel moet afdwingen dat het salaris van een werknemer niet meer dan één keer per dag mag worden bijgewerkt. De database heeft echter hoge transactiegelijktijdigheid, en een eenvoudige trigger kan tot blokkades of prestatieproblemen leiden.

In plaats van een row-level trigger te gebruiken die bij elke update vuurt en de prestaties kan vertragen, gebruik je een statement-level trigger met een logtabel om meerdere salarisupdates op dezelfde dag te voorkomen.

De onderstaande trigger voorkomt meerdere salarisupdates voor een werknemer op dezelfde dag door de tabel salary_update_log te controleren voordat een update wordt toegestaan. Als het salaris vandaag al is bijgewerkt, wordt een fout gegenereerd; anders wordt de updatedatum gelogd.

-- 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;

Bovenstaand voorbeeld vermindert row-level locking en minimaliseert transactiebotsingen tijdens bulkupdates.

18. Hoe splits je grote transacties op in kleinere delen voor betrouwbaarheid?

Stel je een scenario voor waarin een banksysteem een bulkupdate moet uitvoeren om rentetarieven voor miljoenen klantenrekeningen aan te passen. Het uitvoeren van één grote transactie kan tabellen te lang vergrendelen of leiden tot rollback-fouten.

Gebruik in dit geval bulkverwerking met COMMIT in batches om de data stapsgewijs te verwerken en blokkades te vermijden.

Het onderstaande PL/SQL-blok implementeert de oplossing door met BULK COLLECT account-ID’s op te halen en er vervolgens doorheen te itereren om de rente met 5% te verhogen. Er wordt na elke 1000 updates gecommit om de prestaties te verbeteren en het resourcegebruik te verminderen. Een laatste commit zorgt dat de resterende updates worden opgeslagen.

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;
/

Deze oplossing zorgt voor betrouwbaarheid in financiële systemen zoals payroll door transactiefouten te voorkomen.

19. Hoe organiseer je complexe logica in packages voor onderhoudbaarheid?

Een retailbedrijf moet een orderverwerkingssysteem implementeren dat meerdere stappen omvat: voorraadsbeschikbaarheid controleren, voorraad reserveren, kortingen berekenen en transactiehistorie loggen.

In plaats van losse, zelfstandige procedures te schrijven, moet je deze logica op een gestructureerde, onderhoudbare manier organiseren. Gebruik daarom PL/SQL-packages om gerelateerde procedures en functies te kapselen, wat hergebruik en onderhoudbaarheid verbetert

De onderstaande package specification definieert functies en procedures voor orderverwerking, waaronder voorraad controleren, voorraad reserveren, kortingen berekenen en transactiestatussen loggen. Het biedt een modulaire aanpak voor ordergerelateerde taken.

-- 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;

Vervolgens gebruiken we de volgende package body om de functies en procedures uit de package specification te implementeren. Deze behandelt kerntaken zoals voorraadcontrole, voorraadreservering, kortingberekening en het loggen van transactiestatussen, zodat de orderverwerking soepel verloopt.

-- 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. Hoe ga je om met deadlocks in systemen met veel transacties?

Ga uit van een scenario waarin een financieel systeem vaak meerdere gerelateerde tabellen tegelijk bijwerkt. Deadlocks ontstaan wanneer twee transacties op elkaars vergrendelde resources wachten, wat prestatiefiles veroorzaakt.

Om dit probleem op te lossen, vergrendel je rijen altijd in een consistente volgorde tussen transacties. Gebruik ook de clausule NOWAIT of SKIP LOCKED om te voorkomen dat je oneindig blijft wachten.

In het onderstaande PL/SQL-blok wordt geprobeerd een specifieke rij in de tabel accounts te vergrendelen voor update met de clausule FOR UPDATE NOWAIT, waardoor de transactie onmiddellijk faalt als een andere sessie de rij al vergrendelt. Na het vergrendelen wordt de transactiestatus bijgewerkt en worden de wijzigingen gecommit. Als er een fout optreedt, wordt de exception opgevangen en een foutmelding afgedrukt.

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;
/

Evenzo verwerkt dit PL/SQL-blok openstaande transacties door ze te vergrendelen voor update met FOR UPDATE SKIP LOCKED, waardoor rijen die al door andere sessies zijn vergrendeld, worden overgeslagen. Het werkt de status van elke transactie bij naar 'Processing' en commit aan het einde de wijzigingen.

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;

Conclusie en verdere bronnen

Voor Oracle-gerichte rollen zoeken werkgevers kandidaten die correcte PL/SQL-code kunnen schrijven, realistische uitdagingen aankunnen en databaseprestaties kunnen optimaliseren. Ik raad aan de officiële Oracle-documentatie over de PL/SQL Language Reference te bekijken voor een diepgaande gids en best practices over PL/SQL. De Oracle Live SQL (Interactieve PL/SQL-playground) biedt toegang tot Oracle’s cloudplatform om PL/SQL-queries online uit te voeren. Ik moedig je ook aan om lid te worden van de Oracle-community om in contact te komen met Oracle-experts en -ontwikkelaars en het Stack Overflow-forum om oplossingen voor PL/SQL-gerelateerde vragen te vinden.

Maar niets gaat boven een gestructureerd leerpad. Daarom raad ik ten zeerste aan onze cursus Introduction to Oracle SQL te volgen, die naar mijn mening echt de beste manier is om een expert te worden. Als je je kennis van het werken met databases verder wilt verdiepen, raad ik ook onze cursus Database Design aan, waarin je leert databases te maken en beheren en het juiste DBMS voor jouw behoeften te kiezen. Probeer tot slot ons carrièrepad Associate Data Engineer in SQL om de basisprincipes van data-engineering en datawarehousing te leren. 

Last but not least: als je kandidaten interviewt en ook anderen wilt upskillen, neem dan contact op met ons DataCamp for Business-team. DataCamp kan hele teams upskillen met praktijkprojecten en aangepaste leerpaden. Dit is een geweldige manier voor werkgevers om vaardigheidskloof te overbruggen en het zelfvertrouwen en de geloofwaardigheid van een team te vergroten, dus neem vandaag nog contact op met ons team.


Allan Ouko's photo
Author
Allan Ouko
LinkedIn
\n
\n
\n
\n
Technical writer voor data science met praktische ervaring in data-analyse, business intelligence en data science. Ik schrijf praktische, op de industrie gerichte content over SQL, Python, Power BI, Databricks en data engineering, gebaseerd op analytisch werk in de echte wereld. Mijn schrijfwerk slaat een brug tussen technische diepgang en zakelijke impact, en helpt professionals om data om te zetten in onderbouwde beslissingen.
\n
\n
\n
\n

PL SQL FAQ's

Wat is PL/SQL en hoe verschilt het van SQL?

PL/SQL is een procedurele taal ontwikkeld door Oracle, met besturingsstructuren en foutafhandeling, terwijl SQL declaratief is en data-opvraging/-manipulatie afhandelt.

Wat is een PL/SQL-package?

Een verzameling gerelateerde procedures, functies, variabelen en cursors voor modulair programmeren en hergebruik.

Hoe verschilt een procedure van een functie?

Procedures voeren een actie uit die geen waarde retourneert, terwijl functies een waarde retourneren die in queries kan worden gebruikt.

Wat zijn triggers in PL/SQL?

Geautomatiseerde acties die vóór of na INSERT-, UPDATE-, DELETE-bewerkingen worden uitgevoerd.

Wat is bulkverwerking in PL/SQL?

Bulkverwerking (BULK COLLECT, FORALL) verbetert de prestaties door het aantal contextswitches tussen de PL/SQL- en SQL-engines te verminderen bij het verwerken van grote datasets.

Onderwerpen

Leer SQL met DataCamp

Cursus

Gegevens manipuleren in SQL

4 Hr
317K
Bekijk detailsRight Arrow
Begin met de cursus
Meer zienRight Arrow
Gerelateerd

blog

AI vanaf nul leren in 2026: een complete gids van de experts

Ontdek alles wat je moet weten om in 2026 AI te leren, van tips om te beginnen tot handige resources en inzichten van industrie-experts.
Adel Nehme's photo

Adel Nehme

15 min

Meer zienMeer zien