Assignment: - Scenarios about triggers & package in PLSQ - Group Work
Date: 25-NOV-2025
Institution: AUCA
Instructor: Maniraguha Eric
- Student 1: Ineza Agape 27464
- Student 2: Ntwari Ashimwe Fiacre 27438
- Student 3: Ndarasi Kaliza Chela 27800
- STudent 4: MICOMYIZA KANYAMIBWA GHISLAINE 27805
This repository demonstrates practical Oracle SQL/PL/SQL examples (in triggers.sql) that implement access-control triggers, server error logging, and a small HR payroll package. The project is structured so you can run and examine the objects and the output using SQL*Plus, SQL Developer, or any Oracle client like us vscode using sql developer extension.
A quick tree of the repository and what each file/folder contains:
triggers-packages/ # repo root
ββ.gitgnore #vscode config twazihishe
ββ README.md # This file: overview, how-to, screenshots descriptions
ββ triggers.sql # All SQL/PLSQL objects: tables, triggers, package and sample calls
ββ Screenshots/ # Sample screenshots showing test runs & output
ββ partone/ # Trigger-based screenshots (insert/update attempts, logs)
β ββ triggerrunning.png
β ββ triggerrunning_noerror.png
β ββ table_data.png
β ββ logs.png
β ββ notriggerdatacaptured.png
ββ partwo/ # Package & dynamic SQL screenshots (function calls, outputs)
β ββ first_run.png
β ββ second_run.png
β ββ output.png
β ββ dynamic_calling.png
ββ challenges/ # Environment / container & privilege debugging screenshots
ββ docker (2).png
ββ container_run.png
ββ priviledge_issue.png
- Table definitions & sample data
employeesβ a small HR table with sample rows
code:
--TODO Table Employee
CREATE TABLE employees (
employee_id NUMBER PRIMARY KEY,
first_name VARCHAR2(100),
last_name VARCHAR2(100),
salary NUMBER(12,2)
);
--sample data
INSERT INTO employees (employee_id, first_name, last_name, salary)
VALUES (101, 'Agape', 'Ineza', 500000);
INSERT INTO employees (employee_id, first_name, last_name, salary)
VALUES (102, 'Alice', 'Mukamana', 350000);
INSERT INTO employees (employee_id, first_name, last_name, salary)
VALUES (103, 'Eric', 'Ndayishimiye', 275000);
INSERT INTO employees (employee_id, first_name, last_name, salary)
VALUES (104, 'Grace', 'Iradukunda', 800000);
COMMIT;
SELECT * from employees;
studentsβ records of students used to demonstrate access control via triggersaccess_logsβ a logging table that records suspicious or disallowed access attempts
code:
-- TODO: Table iraza storing students info
CREATE TABLE students (
student_id NUMBER PRIMARY KEY,
first_name VARCHAR(200) NOT NULL,
last_name VARCHAR(200) NOT NULL,
marks NUMBER NOT NULL
);
--TODO: Table iraza capture errors
CREATE TABLE access_logs (
log_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
username VARCHAR2(200),
attempt_time DATE,
action_type VARCHAR2(100),
description VARCHAR2(200)
);
-- TODO:sample data zidufasha ko visualizinga the trigger easier
INSERT INTO students VALUES (27438,'Fiacre','Ntwari', 27);
INSERT INTO students VALUES (27800,'Chela','Kaliza', 30);
INSERT INTO students VALUES (27464,'Agape', 'Ineza', 28);
INSERT INTO students VALUES (27805,'Ghislaine','KANYAMIBWA', 29);
- Triggers
auth_access(BEFORE INSERT OR UPDATE OR DELETE ON students)- Purpose: enforce a database-level access policy β deny writes to the
studentstable on weekends and outside allowed working hours. - Behavior: raises an application error with codes (-20001, -20002) when an operation would violate the policy.
- Purpose: enforce a database-level access policy β deny writes to the
logging_trigger(AFTER SERVERERROR ON DATABASE)- Purpose: capture server/database error events and save a record to
access_logsfor diagnostics or audit.
- Purpose: capture server/database error events and save a record to
code
-- Trigger to log unauthorized access attempts
CREATE OR REPLACE TRIGGER auth_access
BEFORE INSERT OR UPDATE OR DELETE ON students
DECLARE
v_day VARCHAR2(10);
v_hour NUMBER;
BEGIN
v_day := TO_CHAR(SYSDATE, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH');
v_hour := TO_NUMBER(TO_CHAR(SYSDATE, 'HH24'));
-- Weekends block
IF v_day IN ('SAT', 'SUN') THEN
RAISE_APPLICATION_ERROR(-20001, 'Access denied: Weekend restriction.');
END IF;
-- Time restriction
IF v_hour < 8 OR v_hour >= 17 THEN
RAISE_APPLICATION_ERROR(-20002, 'Access denied: Allowed time is 08:00β17:00.');
END IF;
END;
/
CREATE OR REPLACE TRIGGER logging_trigger
AFTER SERVERERROR
ON DATABASE
DECLARE
BEGIN
INSERT INTO access_logs(username, attempt_time, action_type, description)
VALUES (
SYS_CONTEXT('USERENV', 'SESSION_USER'),
SYSDATE,
'DATA ACCESS ATTEMPT',
'Violation of AUCA access policy detected.'
);
END;
/-
PL/SQL package
hr_salary_pkgcalc_rssb_tax(p_salary)β returns RSSB / payroll tax (sample: 3%)calc_net_salary(p_salary)β returns net salary after RSSB deductionupdate_salary_dynamic(emp_id, new_salary)β demonstrates dynamic SQL to update an employee's salary and prints bothUSERandCURRENT_USERto show owner vs invoker context
Part 1 (triggers):
-
Here, queries runs and no trigger is triggered since we are working in interval time that we should be working.
-
triggerrunning.png
Here, queries runs and trigger is triggered since we are working in 22PM. -
logs.png
Here, we have table which stores and help us audit, inspect all denied access or people who to to enter in time which is prohibited.
Part 2 (package & dynamic SQL):
-
second_run.png,
here we run and function was applied twice, data automated itself. -
functions return expected calculations
-
source-code, with commented reasons about user vs current_user
-
dynamic_calling.png
β illustrates the dynamic update being executed and output from DBMS_OUTPUT.
Challenges / environment images:
docker (2).png,
Running gvenzl oracle image was not an easy task as we had to connect it to vscode as our working environment
container_run.png
β running inside containers;
priviledge_issue.png
Privilege issue encountered during testing. We had to grantpermission to the user: ntwari as Admin to use triggers
- Access control is often enforced at the application level β
auth_accessshows how to add database-level rules to prevent changes at the source. logging_triggerdemonstrates database-level error auditing so you can detect and store incidents automatically.hr_salary_pkgbundles payroll utilities into a single reusable package and shows dynamic SQL + output for learning about invoker/definer security context.
-- View employees and sample data SELECT * FROM employees;
-- Calculate RSSB & net salary SELECT hr_salary_pkg.calc_rssb_tax(500000) AS tax FROM dual; SELECT hr_salary_pkg.calc_net_salary(500000) AS net_salary FROM dual;
-- Dynamic update (updates employee id 101 to new salary) BEGIN hr_salary_pkg.update_salary_dynamic(101, 700000); END;
-- Try to insert into students outside allowed hours (will fail)
INSERT INTO students (student_id, first_name, last_name, marks) VALUES (99999, 'Try', 'Outside', 10);
You can compare the actual screenshot images in Screenshots/ after running the examples to verify expected behavior.
- The
auth_accesstrigger usesTO_CHAR(SYSDATE, 'DY')and hour extraction to enforce the window of allowed times (08:00β17:00) and blocks weekends. logging_triggerusesSYS_CONTEXT('USERENV', 'SESSION_USER')to capture the session user for the audit record.hr_salary_pkg.update_salary_dynamicprints bothUSERand the invoker (CURRENT_USER) to illustrate privileges and ownership when using dynamic SQL.
- Expand the
access_logstable to application identifiers, or more detailed stack traces for improved auditing. - Add tests that try insert/update during blocked times to verify the trigger behavior.
- Add grants or role tests to explore definer vs invoker rights in packages.
- Create
employees,studentsandaccess_logstables - Create and test
auth_accesstrigger (blocks weekends and non-office hours) - Create
logging_triggerto insert intoaccess_logson server errors - Implement
hr_salary_pkg(RSSB tax, net salary, dynamic update) - (Optional) Add automated tests / CI for the SQL file




