You are on page 1of 4

--1.

Create an audit table containing the identifying attribute, modification date,


comment, name of the object being changed, number of changes, type of change.

CREATE TABLE audit_table (


audit_id NUMBER PRIMARY KEY,
audit_date DATE,
description VARCHAR2(100),
object_name VARCHAR2(35),
ch_num NUMBER,
ch_type VARCHAR2(35)
);

--2. Implement a trigger that responds to changes made to the employees table.
After each change, it should add an appropriate comment to the previously created
auditing table. Test it.e

CREATE SEQUENCE aud_seq;

CREATE OR REPLACE TRIGGER emp_change


AFTER INSERT OR UPDATE OR DELETE ON employees
BEGIN
IF INSERTING THEN
INSERT INTO audit_table VALUES(aud_seq.NEXTVAL, DEFAULT, 'Insert of the
new employee', 'employee', NULL, 'INSERT');
IF DELETING THEN
INSERT INTO audit_table VALUES(aud_seq.NEXTVAL, DEFAULT, 'Deleting of
the employee', 'employee', NULL, 'DELETE');
END IF;
IF UPDATING THEN
INSERT INTO audit_table VALUES(aud_seq.NEXTVAL, DEFAULT, 'Update of the
employee', 'employee', NULL, 'UPDATE');
END IF;
END IF;
END emp_change;

CREATE OR REPLACE TRIGGER emp_change


AFTER INSERT OR UPDATE OR DELETE
ON employees
FOR EACH ROW
BEGIN
IF Inserting THEN
INSERT INTO audit_table VALUES(aud_seq.NEXTVAL, DEFAULT, 'Insert of the new
employee with number ' || :NEW.employee_id, 'employee', 1,'INSERT');
END IF;
IF Updating THEN
INSERT INTO audit_table VALUES(aud_seq.NEXTVAL, DEFAULT, 'Update of the
employee '||:NEW.employee_id, 'employee', 1,'UPDATE');
END IF;
IF Deleting THEN
INSERT INTO audit_table VALUES(aud_seq.NEXTVAL, DEFAULT, 'Deleting of the
employee'||:OLD.employee_id, 'employee', 1,'DELETE');
END IF;
END emp_change;

UPDATE employees SET salary = salary*1.1;

SELECT * FROM audit_table;

DROP TRIGGER emp_change;


-- 3. Create an archive table from the result of the query that selects all single
employee data. Add a column that tells you when the employee left. Clear data from
the archive table. Confirm. Implement a trigger that, when deleting data in the
employees table, places the deleted data in the archive table and adds the
appropriate operation date. Test it.

CREATE TABLE archive AS


SELECT * FROM employees WHERE employee_id = 205;

SELECT * FROM archive;

ALTER TABLE archive ADD left_date DATE;

DELETE FROM archive;

SELECT * FROM archive;

DESC archive;

SELECT * FROM employees;

CREATE OR REPLACE TRIGGER move_to_archive


AFTER DELETE ON employees
FOR EACH ROW
BEGIN
INSERT INTO archive
VALUES(:OLD.employee_id, :OLD.first_name, :OLD.last_name, :OLD.email,

:OLD.phone_number, :OLD.hire_date, :OLD.job_id, :OLD.salary,

:OLD.commission_pct, :OLD.manager_id,:OLD.department_id, Current_date);


END move_to_archive;

DELETE FROM employees WHERE employee_id=206;

SELECT * FROM archive;

SELECT * FROM USER_SOURCE WHERE name='MOVE_TO_ARCHIVE';

--4. Create a trigger that blocks salary and commission modification operations on
the employees table. Test it.

CREATE OR REPLACE TRIGGER emp_salary_stop


BEFORE UPDATE OF salary, commission_pct ON employees
FOR EACH ROW
BEGIN
RAISE_APPLICATION_ERROR (-20002,'You cannot modify salaries and
commissions!!!');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error inside emp_salary_stop trigger.');
END emp_salary_stop;

UPDATE employees SET salary = salary*1.1;

DROP TRIGGER emp_salary_stop;

--5. Create a trigger that will check and correct the data when data is inserted
into the employees table. Test it.

CREATE OR REPLACE TRIGGER emp_insert


BEFORE INSERT ON employees
FOR EACH ROW
DECLARE
v_min jobs.min_salary%TYPE;
v_max jobs.max_salary%TYPE;
BEGIN
:NEW.employee_id := employees_seq.NEXTVAL;
:NEW.first_name := INITCAP(:NEW.first_name);
:NEW.last_name := INITCAP(:NEW.last_name);
:NEW.email := UPPER(:NEW.email);
:NEW.job_id := UPPER(:NEW.job_id);
SELECT min_salary, max_salary INTO v_min, v_max FROM jobs WHERE job_id
= :NEW.job_id;

IF(:NEW.salary > v_max) THEN


:NEW.salary := v_max;
ELSIF (:NEW.salary < v_min) THEN
:NEW.salary := v_min;
END IF;
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.put_line('Too many rows!');
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.put_line('No data found!');
WHEN OTHERS THEN
DBMS_OUTPUT.put_line('Other error on emp_insert trigger!');
END emp_insert;

ALTER TRIGGER emp_insert DISABLE;

ALTER TRIGGER emp_insert ENABLE;

SELECT * FROM employees;

SELECT * FROM jobs;

INSERT INTO employees (first_name, last_name,email,hire_date,job_id,salary)


VALUES('james','bond','jb007',Current_date,'ad_vp',45000);

SELECT * FROM employees WHERE LOWER(last_name) = 'bond';

--6. Create a view and then a trigger that lets you modify data through the view.

CREATE VIEW how_many_employees AS

SELECT location_id, street_address,postal_code,city, state_province, country_id,


country_name,
(SELECT Count(*) FROM employees JOIN departments USING (department_id)
WHERE location_id = l.location_id) emp_num
FROM locations l JOIN countries USING (country_id);

CREATE OR REPLACE TRIGGER tr_how_many_emp


INSTEAD OF INSERT ON how_many_employees
FOR EACH ROW
DECLARE
v_help NUMBER(8);
BEGIN
SELECT Count(*) INTO v_help FROM countries
WHERE country_id = :NEW.country_id OR country_name = :NEW.country_name;
IF(v_help = 0) THEN
INSERT INTO countries VALUES (:NEW.country_id,:NEW.country_name,NULL);
END IF;
SELECT Count(*) INTO v_help FROM locations
WHERE street_address = :NEW.street_address;
IF(v_help = 0) THEN
INSERT INTO locations VALUES
(:NEW.location_id, :NEW.street_address, :NEW.postal_code,
:NEW.city, :NEW.state_province, :NEW.country_id);
END IF;
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.put_line('No data found!');
WHEN too_many_rows THEN
DBMS_OUTPUT.put_line('Too many rows!');
WHEN others THEN
DBMS_OUTPUT.put_line('Other problem in trigger tr_how_man_emp!');
END tr_how_man_emp;
SELECT * FROM how_many_employees;
SELECT * FROM countries;

INSERT INTO how_many_employees VALUES (2, 'Armii Krajowej','42-


201','Czestochowa','Slask','PL','Poland',NULL);

You might also like