You are on page 1of 23

Bucharest University of Economic Studies

Faculty: Cybernetics, Statistics and Economic Informatics


Domain of study: Economic Informatics

[Company name]

DBMS Project
- Managing a Business Hub

Thesis Supervisor: Student:


Assoc. Prof. Ph.D Diaconita Vlad Andreea Stroe
Group 1050, F Series

Bucharest 2018
Table of contents
1. Premises
2. Schema and scripts to create and alter table
3. Interacting with the Oracle server through SQL
commands
4. Interacting with Application Builder through
APEX
Managing a Business Hub

1. Premises
This project presents a software solution designed to depict and facilitate the management of a
business hub. The concept of business hubs is relatively new to the Romanian market, on the basis of
them being a globally developing trend to ensure entrepreneurs, business startups, self-employed people
and small business owners to have a low-cost option to creating, developing and maintaining a
sustainable business. It is managed internally as any economic establishment, employing white collar
workers divided each in only one department and having only one job position at a time. It has many
clients, activating in various work fields, which rent office and/or miscellaneous space for fixed periods
of time in order to deploy activities there. The process of renting involves one employee signing one
contract for each space with one client, clauses such as the value of the contract being established through
considerations as the length of the rental period and the useful floor area of the space being rented. The
terms of the contract state a payment frequency agreed by both parts, so that the business hub issues
invoices with an outstanding value equal to the agreed one and, based on the payment frequency, a
calculated due date for each one. A client may rent many spaces simultaneously but a space can be rented
to only one client at a given time.
Data about this has been stored in a database based on the relational model, using 8 entities connected
by relations. These are the 8 tables intuitively called Employees, Departments ( are situated in the
locations the company also rents space in ) , Locations, Spaces, Price Currents ( the categories of price
taken into consideration when establishing the value of a contract ) , Clients, Contracts and Invoices.

2. Schema and scripts to create and alter table


The scripts to create and specify extra constraints in order to maintain the integrity of the database are
attached below, each presented in a separate anonymous block and successfully executed with the help of
the dynamic PL/SQL command „EXECUTE IMMEDIATE”:
BEGIN
EXECUTE IMMEDIATE ‘CREATE TABLE PRICE_CURRENTS(
price_current_ID NUMBER(10,0) NOT NULL,
min_useful_floor_area NUMBER(6,2) NOT NULL,
max_useful_floor_area NUMBER(6,2),
min_contract_duration NUMBER(2,0) NOT NULL,
max_contract_duration NUMBER(2,0),
price NUMBER(6,2) NOT NULL
);’;
END;
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE "PRICE_CURRENTS" ADD CONSTRAINT
"Price_Currents_ID_PK" PRIMARY KEY ("PRICE_CURRENT_ID") ENABLE;’;
EXECUTE IMMEDIATE 'ALTER TABLE "PRICE_CURRENTS" MODIFY
("MAX_USEFUL_FLOOR_AREA" CONSTRAINT "max_useful_floor_area_NN" NOT NULL
ENABLE); ';
EXECUTE IMMEDIATE 'ALTER TABLE "PRICE_CURRENTS" MODIFY
("MAX_CONTRACT_DURATION" CONSTRAINT "max_contract_duration_NN" NOT NULL
ENABLE); ';
EXECUTE IMMEDIATE ' ALTER TABLE "PRICE_CURRENTS" ADD CONSTRAINT
"useful_floor_area_interval" CHECK (MAX_USEFUL_FLOOR_AREA >
MIN_USEFUL_FLOOR_AREA) ENABLE; ';
EXECUTE IMMEDIATE 'ALTER TABLE "PRICE_CURRENTS" ADD CONSTRAINT
"contract_duration_interval" CHECK (MAX_CONTRACT_DURATION >
MIN_CONTRACT_DURATION) ENABLE; ';

BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE LOCATIONS(
location_ID NUMBER(2,0) NOT NULL,
address VARCHAR2(70),
building_year NUMBER(4,0),
floors_no NUMBER(2,0) NOT NULL,
total_useful_floor_area NUMBER(10,0),
postal_code VARCHAR2(6),
city VARCHAR2(20)
); ';
END;

BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE "LOCATIONS" ADD CONSTRAINT "Locations_ID_PK"
PRIMARY KEY ("LOCATION_ID") ENABLE; ';
EXECUTE IMMEDIATE 'ALTER TABLE "LOCATIONS" MODIFY ("ADDRESS" CONSTRAINT
"address_NN" NOT NULL ENABLE); ';
EXECUTE IMMEDIATE 'ALTER TABLE "LOCATIONS" MODIFY
("TOTAL_USEFUL_FLOOR_AREA" CONSTRAINT "total_useful_floor_area_NN" NOT NULL
ENABLE); ';
EXECUTE IMMEDIATE 'ALTER TABLE "LOCATIONS" MODIFY ("POSTAL_CODE"
CONSTRAINT "postal_code_NN" NOT NULL ENABLE); ';
EXECUTE IMMEDIATE 'ALTER TABLE "LOCATIONS" MODIFY ("CITY" CONSTRAINT
"city_NN" NOT NULL ENABLE); ';
EXECUTE IMMEDIATE 'ALTER TABLE "LOCATIONS" MODIFY
("TOTAL_USEFUL_FLOOR_AREA" CONSTRAINT "total_useful_floor_area_NN" NOT NULL
ENABLE); ';
END;

BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE SPACES(
space_ID NUMBER(3,0) NOT NULL,
space_type VARCHAR2(30) NOT NULL,
useful_floor_area NUMBER(6,0) NOT NULL,
status VARCHAR2(7) NOT NULL,
facilities VARCHAR2(300),
location_id NUMBER(2) NOT NULL,
price_currents_id NUMBER(10) NOT NULL,
CONSTRAINT "Spaces_Price_Currents_FK" FOREIGN KEY (price_currents_id)
REFERENCES PRICE_CURRENTS(PRICE_CURRENT_ID),
CONSTRAINT "Spaces_Locations_FK" FOREIGN KEY (location_id) REFERENCES
LOCATIONS(LOCATION_ID)
);';
END;

BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE "SPACES" ADD CONSTRAINT "Spaces_ID_PK"
PRIMARY KEY ("SPACE_ID") ENABLE;’;
EXECUTE IMMEDIATE 'ALTER TABLE "SPACES" ADD CONSTRAINT "Space_type_domain"
CHECK (SPACE_TYPE in ('Enclosed Office','Open Office','Open Workstation','Conference
Room','Break Room Service Unit', 'Informal Breakout Center', 'Documents Room')) ENABLE;’;
EXECUTE IMMEDIATE 'ALTER TABLE "SPACES" ADD CONSTRAINT "Status_domain" CHECK
(STATUS in ('Liber', 'Ocupat')) ENABLE;’;
END;

BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE CLIENTS(
client_ID NUMBER(4,0) NOT NULL,
organization_name VARCHAR2(100) NOT NULL,
organization_type VARCHAR2(70),
description VARCHAR2(750),
geographic_focus VARCHAR2(15),
organisational_focus VARCHAR2(40),
sector_focus VARCHAR2(40),
manager_first_name VARCHAR2(30) NOT NULL,
manager_last_name VARCHAR2(30) NOT NULL,
manager_email VARCHAR2(70),
phone_number VARCHAR2(11) NOT NULL,
status VARCHAR2(9)
);’;
END;

BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE "CLIENTS" ADD CONSTRAINT "Clients_ID_PK"
PRIMARY KEY ("CLIENT_ID") ENABLE;’;
EXECUTE IMMEDIATE 'ALTER TABLE "CLIENTS" ADD CONSTRAINT
"Geographic_focus_domain" CHECK (GEOGRAPHIC_FOCUS in ('Global', 'EU', 'Asia&Pacific',
'America', 'Africa')) ENABLE;’;
EXECUTE IMMEDIATE 'ALTER TABLE "CLIENTS" ADD CONSTRAINT "Client_status_domain"
CHECK (STATUS in ('Current', 'Previous')) ENABLE;’;
END;

BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE DEPARTMENTS(
department_ID NUMBER(2,0) NOT NULL ,
dep_name VARCHAR2(30) NOT NULL,
acronym VARCHAR2(10) NOT NULL,
location_id NUMBER(2,0) NOT NULL,
CONSTRAINT "Departments_ID_PK" PRIMARY KEY ("DEPARTMENT_ID") ENABLE,
CONSTRAINT "Departments_Locations_FK" FOREIGN KEY (location_id) REFERENCES
LOCATIONS(LOCATION_ID)
);’;
END;

BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE EMPLOYEES(
employee_ID NUMBER(6,0) NOT NULL,
first_name VARCHAR2(50) NOT NULL,
last_name VARCHAR2(50) NOT NULL,
email VARCHAR2(100),
phone_number VARCHAR2(20),
employment_date DATE,
job_position VARCHAR2(50),
salary NUMBER(10,2),
commission_points NUMBER(3,2),
manager_id NUMBER(6,0),
department_id NUMBER(2,0) NOT NULL,
CONSTRAINT "Employees_ID_PK" PRIMARY KEY ("EMPLOYEE_ID") ENABLE,
CONSTRAINT "Employees_Deartments_FK" FOREIGN KEY (department_id) REFERENCES
DEPARTMENTS(DEPARTMENT_ID)
);’;
END;

BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE CONTRACTS(
contract_ID NUMBER(6,0) NOT NULL,
contract_no VARCHAR2(20) NOT NULL UNIQUE,
space_id NUMBER(3,0) NOT NULL,
location_id NUMBER(2,0) NOT NULL,
employee_id NUMBER(6,0) NOT NULL,
client_id NUMBER(4,0) NOT NULL,
start_date DATE NOT NULL,
end_date DATE,
worth NUMBER(6,2) NOT NULL,
payment_frequency NUMBER(2,0) NOT NULL,
payment_per_period NUMBER(4,0),
possibility_to_prolongue VARCHAR2(3),
CONSTRAINT "Contracts_ID_PK" PRIMARY KEY ("CONTRACT_ID") ENABLE,
CONSTRAINT "Contracts_Spaces_FK" FOREIGN KEY (space_id) REFERENCES
SPACES(SPACE_ID),
CONSTRAINT "Contracts_Locations_FK" FOREIGN KEY (location_id) REFERENCES
LOCATIONS(LOCATION_ID),
CONSTRAINT "Contracts_Employees_FK" FOREIGN KEY (employee_id) REFERENCES
EMPLOYEES(EMPLOYEE_ID),
CONSTRAINT "Contracts_Clients_FK" FOREIGN KEY (client_id) REFERENCES
CLIENTS(CLIENT_ID)
);’;
END;

BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE "CONTRACTS" ADD CONSTRAINT
"Poss_to_prolongue_domain" CHECK (POSSIBILITY_TO_PROLONGUE in ('YES', 'NO')) ENABLE;
EXECUTE IMMEDIATE 'ALTER TABLE "CONTRACTS" ADD CONSTRAINT "date_interval"
CHECK (END_DATE > START_DATE) ENABLE;’;
END;

BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE INVOICES(
invoice_ID NUMBER(10,0) NOT NULL ,
invoice_no NUMBER(10,0) NOT NULL,
invoicing_date DATE NOT NULL,
due_date DATE NOT NULL,
contract_id NUMBER(6,0) NOT NULL,
status VARCHAR2(10),
worth NUMBER(6,2) NOT NULL,
credit_account VARCHAR2(35) NOT NULL,
debit_account VARCHAR2(35) NOT NULL,
CONSTRAINT "Invoices_ID_PK" PRIMARY KEY ("INVOICE_ID") ENABLE,
CONSTRAINT "Invoices_Contracts_FK" FOREIGN KEY (contract_id) REFERENCES
CONTRACTS(CONTRACT_ID)
);’;
END;

BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE "INVOICES" ADD CONSTRAINT
"Invoice_status_domain" CHECK (STATUS in ('Paid', 'Outstanding')) ENABLE;
ALTER TABLE "INVOICES" ADD CONSTRAINT "Invoice_date_interval" CHECK (DUE_DATE >
INVOICING_DATE) ENABLE;’;
END;
The database schema that shows the relations between the tables in shown below:

3. Interacting with the Oracle server through SQL commands


In order to prove the functionality of the database we may execute the following statements within
the SQL Commands section of APEX:

1. Display the details of the first and the last clients the hub has signed contracts with, the full
name of the employee that intermediated the signing of the contract and the time it has been since the
contracts were signed. Treat the case of the employee not working for the
company anymore as an exception.
_____________________________________________________________________________________________________________________________ _____________________________________________________________________________________________________________

DECLARE
TYPE ClientsType IS RECORD (client_id CLIENTS.CLIENT_ID%TYPE,
client_manager_name VARCHAR2(60),
organization_name VARCHAR2(100),
time_since_contract NUMBER,
contract_id CONTRACTS.CONTRACT_ID%TYPE,
employee_name VARCHAR2(100));
TYPE tab_clients IS VARRAY(2) OF ClientsType;
t tab_clients := tab_clients();
BEGIN
T.EXTEND(2);
SELECT cl.CLIENT_ID, cl.MANAGER_FIRST_NAME||' '||cl.MANAGER_LAST_NAME,
cl.ORGANIZATION_NAME, MONTHS_BETWEEN(SYSDATE, START_DATE),
cr.CONTRACT_ID INTO t(1).client_id, t(1).client_manager_name, t(1).organization_name,
t(1).time_since_contract, t(1).contract_id FROM CLIENTS cl, CONTRACTS cr WHERE
cl.CLIENT_ID=cr.CLIENT_ID AND START_DATE = (SELECT MIN(START_DATE) FROM
CONTRACTS);
SELECT cl.CLIENT_ID, cl.MANAGER_FIRST_NAME||' '||cl.MANAGER_LAST_NAME,
cl.ORGANIZATION_NAME, MONTHS_BETWEEN(SYSDATE, START_DATE),
cr.CONTRACT_ID INTO t(2).client_id, t(2).client_manager_name, t(2).organization_name,
t(2).time_since_contract, t(2).contract_id FROM CLIENTS cl, CONTRACTS cr WHERE
cl.CLIENT_ID=cr.CLIENT_ID AND START_DATE = (SELECT MAX(START_DATE) FROM
CONTRACTS);
SELECT emp.FIRST_NAME||' '||emp.LAST_NAME INTO T(1).EMPLOYEE_NAME FROM
EMPLOYEES emp, CONTRACTS ct WHERE ct.EMPLOYEE_ID=emp.EMPLOYEE_ID AND
ct.CONTRACT_ID=t(1).CONTRACT_ID;
SELECT emp.FIRST_NAME||' '||emp.LAST_NAME INTO T(2).EMPLOYEE_NAME FROM
EMPLOYEES emp, CONTRACTS ct WHERE ct.EMPLOYEE_ID=emp.EMPLOYEE_ID AND
ct.CONTRACT_ID=t(2).CONTRACT_ID;
FOR i IN t.FIRST..t.LAST LOOP
DBMS_OUTPUT.PUT_LINE(t(i).organization_name ||' '|| T(I).client_manager_name||'
'||ROUND(T(I).time_since_contract)||' '||T(I).EMPLOYEE_NAME);
END LOOP;
END;
// Manocap Colette Trott 99 Laura Cadiz
Making Markets Work Better for the Poor (M4P) Brian Smith 7 Katie Monroe

2. Display the name of employee occupying the highest position in the company and store their
direct subalterns.
_____________________________________________________________________________________________________________________________ _____________________________________________________________________________________________________________

DECLARE
TYPE TopEmp is TABLE OF EMPLOYEES%ROWTYPE;
topDescendants TopEmp;
v_boss_first_name EMPLOYEES.FIRST_NAME%TYPE;
v_boss_last_name EMPLOYEES.LAST_NAME%TYPE;
v_position EMPLOYEES.JOB_POSITION%TYPE;
v_counter NUMBER :=0;
BEGIN
SELECT * INTO v_boss_first_name, v_boss_last_name, V_POSITION FROM (SELECT
FIRST_NAME, LAST_NAME,
JOB_POSITION FROM EMPLOYEES ORDER BY EMPLOYEE_ID) WHERE ROWNNUM=1;
EXECUTE IMMEDIATE 'CREATE curs_descend CURSOR FOR SELECT * FROM
EMPLOYEES WHERE LEVEL=1
CONNECT BY PRIOR EMPLOYEE_ID=MANAGER_ID START WITH
FIRST_NAME=V_BOSS_FIRST_NAME AND
LAST_NAME=V_BOSS_LAST_NAME ORDER BY LEVEL;';
FOR I IN curs_descend LOOP
topDescendants.EXTEND();
topDescendants(v_counter):=I;
v_counter=v_counter+1;
END LOOP;
DBMS_OUTPUT.PUT_LINE(V_BOSS_FIRST_NAME||' '||V_BOSS_LAST_NAME);
END;
// Andreea Stroe

3. Display the name of employee whose id is entered from the keyboard and the number of
contracts they have signed.
__________________________________________________________________________________________________________________________________________________________________________________________________________________________ ________________

set define on
ACCEPT VAR_EMPLOYEE_ID PROMPT 'Please insert the id of the employee: '
DECLARE
V_FIRST_NAME EMPLOYEES.FIRST_NAME%TYPE;
V_LAST_NAME EMPLOYEES.LAST_NAME%TYPE;
V_NO_CONTRACTS NUMBER;
VAR_EMPLOYEE_ID EMPLOYEES.EMPLOYEE_ID%TYPE;
BEGIN
SELECT empl.FIRST_NAME, empl.LAST_NAME, COUNT(ct.CONTRACT_ID) INTO
V_FIRST_NAME, V_LAST_NAME, V_NO_CONTRACTS FROM EMPLOYEES empl,
CONTRACTS ct WHERE empl.EMPLOYEE_ID=&VAR_EMPLOYEE_ID AND
ct.EMPLOYEE_ID=empl.EMPLOYEE_ID GROUP BY EMPLOYEE_ID;
EXCEPTION WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('The employee id you have entered is not valid.');
END;
4. Display the names of the employee and the client's manager and for each contract if it is
small(worth<300), medium(<5000), grande(<7000) or premium(>7000).
_____________________________________________________________________________________________________________________________ _____________________________________________________________________________________________________________

DECLARE
CURSOR c_emp is select emp.FIRST_NAME, emp.LAST_NAME,
cl.MANAGER_FIRST_NAME, cl.MANAGER_LAST_NAME, ct.WORTH from EMPLOYEES
emp, CLIENTS cl, CONTRACTS ct WHERE
ct.EMPLOYEE_ID=emp.EMPLOYEE_ID AND ct.CLIENT_ID=cl.CLIENT_ID;
r_emp c_emp%ROWTYPE;
BEGIN
open c_emp;
if c_emp%found then dbms_output.put_line('The contracts are:');
end if;
loop
fetch c_emp into r_emp;
exit when c_emp%notfound;
dbms_output.put_line('');
dbms_output.put_line('Employee: '||r_emp.first_name||' '||r_emp.last_name||' '||' Client manager:
'||r_emp.manager_first_name||' '||r_emp.manager_last_name);
CASE WHEN r_emp.worth<3000 THEN DBMS_OUTPUT.PUT('Type of contract: Small');
WHEN r_emp.worth>3000 AND r_emp.worth<5000 THEN DBMS_OUTPUT.PUT_LINE('Type
of contract: Medium');
WHEN r_emp.worth>5000 AND r_emp.worth<7000 THEN DBMS_OUTPUT.PUT_LINE('Type
of contract: Grande');
WHEN r_emp.worth>=7000 THEN DBMS_OUTPUT.PUT_LINE('Type of contract: Premium');
ELSE DBMS_OUTPUT.PUT_LINE('Type of contract: N/A');
END CASE;
end loop;
close c_emp;
END;
//Employee: Riven Leigh Client manager: Rita Adams
Type of contract: Small

5. Check if the client with id 30 deploys activities in the Energy&Infrastructure sector and if so,
store the percentage of contracts signed with them in a bind variable and later display it.
_____________________________________________________________________________________________________________________________ _____________________________________________________________________________________________________________

set serveroutput on
VARIABLE G_PERCENTAGE NUMBER(4,3)
DECLARE
V_CLIENT_NAME CLIENTS.ORGANIZATION_NAME%TYPE;
V_SECTOR_FOCUS CLIENTS.SECTOR_FOCUS%TYPE;
V_AUX_COUNTER NUMBER:=0;
BEGIN
SELECT ORGANIZATION_NAME, SECTOR_FOCUS INTO V_CLIENT_NAME,
V_SECTOR_FOCUS FROM CLIENTS WHERE CLIENT_ID=30;
IF V_SECTOR_FOCUS LIKE '%Energy&Infrastructure%' THEN
SELECT COUNT(CONTRACT_NO) INTO :G_PERCENTAGE FROM CONTRACTS WHERE
CLIENT_ID=30;
SELECT COUNT(CONTRACT_NO) INTO V_AUX_COUNTER FROM CONTRACTS;
:G_PERCENTAGE:=V_AUX_COUNTER/:G_PERCENTAGE*100;
DBMS_OUTPUT.PUT_LINE('Client '||V_CLIENT_NAME||' indeed has id 30 and has signed
'||:G_PERCENTAGE'||' of our company's contracts');
ELSE DBMS_OUTPUT.PUT_LINE('The client with id 30 doesn't work in Energy&Infrastructure.');
END IF;
END;
//Employee: Riven Leigh Client manager: Rita Adams
Type of contract: Small

6. Check if the client with id 30 deploys activities in the Energy&Infrastructure sector and if so,
display the percentage of contracts signed with them.
_____________________________________________________________________________________________________________________________ ____________________________________________________________________________________________________________

DECLARE
V_CLIENT_NAME CLIENTS.ORGANIZATION_NAME%TYPE;
V_SECTOR_FOCUS CLIENTS.SECTOR_FOCUS%TYPE;
V_AUX_COUNTER NUMBER:=0;
V_PERCENTAGE NUMBER;
BEGIN
SELECT ORGANIZATION_NAME, SECTOR_FOCUS INTO V_CLIENT_NAME,
V_SECTOR_FOCUS FROM CLIENTS WHERE CLIENT_ID=30;
IF V_SECTOR_FOCUS LIKE '%Energy&Infrastructure%' THEN
SELECT COUNT(CONTRACT_NO) INTO V_PERCENTAGE FROM CONTRACTS WHERE
CLIENT_ID=30;
SELECT COUNT(CONTRACT_NO) INTO V_AUX_COUNTER FROM CONTRACTS;
V_PERCENTAGE:=V_PERCENTAGE/V_AUX_COUNTER*100;
DBMS_OUTPUT.PUT_LINE('Client '||V_CLIENT_NAME||' indeed has id 30 and has signed
'||to_char(V_PERCENTAGE,'0.0')||'% of our company''s contracts');
ELSE DBMS_OUTPUT.PUT_LINE('The client with id 30 doesn''t work in Energy&Infrastructure.');
END IF;
END;

7. A new bussiness rule states that each employee gets an automatically generated professional
email upon their employment, which follows the patters: ’first_name’_’last_name’@bhub.com. First we
update the entries for current employees, then we create a cursor that automatically does it.
_____________________________________________________________________________________________________________________________ ____________________________________________________________________________________________________________

BEGIN
EXECUTE IMMEDIATE 'UPDATE EMPLOYEES SET
EMAIL=LOWER(FIRST_NAME)||'_'||LOWER(LAST_NAME)||'@bhub.com';';
END;

CREATE OR REPLACE TRIGGER generate_employee_email AFTER INSERT ON EMPLOYEES


FOR EACH ROW
BEGIN
EXECUTE IMMEDIATE 'UPDATE EMPLOYEES SET
EMAIL=LOWER(FIRST_NAME)||''_''||LOWER(LAST_NAME)||''@bhub.com''
WHERE EMPLOYEE_ID=:NEW.EMPLOYEE_ID;';
IF :NEW.EMAIL IS NULL THEN
RAISE_APPLICATION_ERROR(-20001, 'The employee was not asigned an email address.');
END IF;
END;

8. Create a trigger that restricts raising the salary of an employee above the current maximum
Salary.
_________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

CREATE OR REPLACE TRIGGER restrict_salary BEFORE INSERT OR UPDATE ON EMPLOYEES


FOR EACH ROW
DECLARE
V_SAL_MAX NUMBER(10,2);
BEGIN
SELECT MAX(SALARY) INTO V_SAL_MAX FROM EMPLOYEES;
IF :NEW.SALARY>V_SAL_MAX THEN
RAISE_APPLICATION_ERROR(-20002,'New salary cannot exceed the greatest salary we currently
offer.');
END IF;
END;

9. Display the first places to be rented, excluding the ones situated in location 2.
________________________________________________________________________________________________________________________________________________________________________________________ _________________________________________________

SET SERVEROUTPUT ON
SET DEFINE ON
ACCEPT LIM_INF PROMPT 'Inferior limit: '
ACCEPT LIM_SUP PROMPT 'Superior limit: '
DECLARE
LIM_INF NUMBER(2):=&LIM_INF;
LIM_SUP NUMBER(2):=&LIM_SUP;
V_SPACE VARCHAR2(35);
V_LOC NUMBER(6,2);
BEGIN
FOR I IN LIM_INF..LIM_SUP LOOP
SELECT TO_CHAR(SPACE_ID)||' '||SPACE_TYPE, LOCATION_ID INTO V_SPACE, V_LOC
FROM SPACES WHERE SPACE_ID=I;
EXIT WHEN V_LOC=2;
DBMN_OUTPUT.PUT_LINE(V_SPACE);
END LOOP;
END;

10. Create a trigger that displays the number of remaining clients upon the deletion of one.
_____________________________________________________________________________________________________________________________ ____________________________________________________________________________________________________________

CREATE OR REPLACE TRIGGER del_client AFTER DELETE ON CLIENTS


DECLARE
V_TOTAL NUMBER:=0;
BEGIN
SELECT COUNT(CLIENT_ID) INTO V_TOTAL FROM CLIENTS;
DBMS_OUTPUT.PUT_LINE(TO_CHAR(V_TOTAL)||' clients remaining.');
END;
11. Remove at most 10 invoices issued between 01-01-2014 and 09-01-2015 and keep track of
the number of deleted rows.
_____________________________________________________________________________________________________________________________ ____________________________________________________________________________________________________________

DECLARE
V_NO NUMBER;
V_COUNTER NUMBER :=0;
BEGIN
FOR I IN 1..50 LOOP
DELETE FROM INVOICES WHERE INVOICING_DATE>TO_DATE('01-01-2014','DD-MM-YYYY')
AND
INVOICING_DATE<TO_DATE('09-01-2015','DD-MM-YYYY');
V_NO:=SQL%ROWCOUNT;
V_COUNTER:=V_COUNTER+V_NO;
END LOOP;
DBMS_OUTPUT.PUT_LINE(V_COUNTER||' rows have been deleted.');
end;

12. Move employee with id 13 from their current department to department 4.


_____________________________________________________________________________________________________________________________ ____________________________________________________________________________________________________________

BEGIN
UPDATE EMPLOYEES SET DEPARTMENT_ID=4 WHERE EMPLOYEE_ID=13;
IF SQL%NOTFOUND THEN
DBMS_OUTPUT.PUT_LINE('There is no employee with this id');
END IF;
END;
13. Display a list of all clients that a given employee has signed.
_________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

VARIABLE empl_id NUMBER;


DECLARE
CURSOR cl_emp(emp_id NUMBER) IS SELECT cl.* FROM CLIENTS cl, EMPLOYEES emp,
CONTRACTS ct WHERE
emp.EMPLOYEE_ID=ct.EMPLOYEE_ID AND ct.CLIENT_ID=cl.CLIENT_ID AND
emp.EMPLOYEE_ID=emp_id;
V_CLIENT CLIENTS%ROWTYPE;
BEGIN
DBMS_OUTPUT.PUT_LINE('The employee with id '||empl_id||' has signed the following clients:');
OPEN cl_emp(:empl_id);
LOOP
fetch cl_emp INTO V_CLIENT;
EXIT WHEN cl_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(V_CLIENT);
END LOOP;
CLOSE cl_emp;
END;
14. Display a list of all clients that a given employee has signed.
_____________________________________________________________________________________________________________________________ ____________________________________________________________________________________________________________

DECLARE
CURSOR c_empl IS SELECT emp.FIRST_NAME||' '||emp.LAST_NAME, man.FIRST_NAME||'
'||man.LAST_NAME,
MONTHS_BETWEEN(SYSDATE, emp.EMPLOYMENT_DATE) FROM EMPLOYEES emp,
EMPLOYEES man WHERE
man.EMPLOYEE_ID=emp.MANAGER_ID ORDER BY MONTHS_BETWEEN(SYSDATE,
emp.EMPLOYMENT_DATE) DESC;
TYPE empl IS RECORD (EMP_NAME VARCHAR2(100), MAN_NAME VARCHAR2(100),
SENIORITY NUMBER);
V_EMP empl;
BEGIN
DBMS_OUTPUT.PUT_LINE('The employees who have worked the longest for us are:');
IF NOT c_empl%ISOPEN THEN
OPEN c_empl;
END IF;
LOOP
FETCH c_empl INTO V_EMP;
EXIT WHEN c_empl%NOTFOUND OR c_empl%ROWCOUNT>3;
DBMS_OUTPUT.PUT_LINE(V_EMP.EMP_NAME||' '||V_EMP.MAN_NAME||'
'||V_EMP.SENIORITY);
END LOOP;
CLOSE c_empl;
END;
15. Create a log table where to enter the user, the error code and the error message each time
an error in encountered.
_____________________________________________________________________________________________________________________________ ____________________________________________________________________________________________________________

CREATE TABLE ERRORS(


USR VARCHAR2(50),
ERR_CODE NUMBER(10),
ERR_MSG VARCHAR2(255));

DECLARE
V_CODE NUMBER;
V_MSG VARCHAR2(255);
exception01 EXCEPTION;
PRAGMA EXCEPTION_INIT(exception01 , -0001);
BEGIN
INSERT INTO
EMPLOYEES(EMPLOYEE_ID,FIRST_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,EMPLOY
MENT_DATE,JOB_POSITION,SALARY,COMMISSION_POINTS,MANAGER_ID,DEPARTMENT_
ID) VALUES
(2,'John','Doe',null,'0730526827',to_date('15-JAN-10','DD-MON-RR'),'Chief Executive
Officer',139000,0.75,null,1);
EXCEPTION
WHEN exception01 THEN
DBMS_OUTPUT.PUT_LINE('There already is an employee with that id.');
V_CODE:=SQLCODE;
V_MSG:=SQLERRM;
INSERT INTO ERRORS VALUES (USER, V_CODE, V_MSG);
END;
16. Display the number of the contract signed by client with id 15.
_____________________________________________________________________________________________________________________________ ____________________________________________________________________________________________________________

DECLARE
NO_CT CONTRACTS.CONTRACT_NO%TYPE;
BEGIN
SELECT CONTRACT_NO INTO NO_CT FROM CONTRACTS WHERE CLIENT_ID=13;
DBMS_OUTPUT.PUT_LINE('The contract number is: '||NO_CT);
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('There is more than one contract signed for that client');
END;

17. Change the name of the department with id 7 to "Information Management".


_____________________________________________________________________________________________________________________________ ____________________________________________________________________________________________________________

DECLARE
invalid_code EXCEPTION;
BEGIN
UPDATE DEPARTMENTS SET DEP_NAME='Information Management' WHERE
DEPARTMENT_ID=7;
IF SQL%NOTFOUND THEN
RAISE invalid_code;
END IF;
EXCEPTION
WHEN invalid_code THEN
DBMS_OUTPUT.PUT_LINE('There is no department with that id.');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('We've encountered an error! The department name could not be
updated.');
END;

18. Create a procedure that displays the money cashed from a specified type of space's rental
and creates a list of all clients having rented that type of space.
_____________________________________________________________________________________________________________________________________________________________________________________________________________________________ ____________

TYPE cl_list IS TABLE OF CLIENTS%ROWTYPE INDEX BY PLS_INTEGER;


CREATE OR REPLACE PROCEDURE money_on_space(t_space IN SPACED.SPACE_TYPE%TYPE,
client_list OUT cl_list) IS
V_TOTAL NUMBER:=0;
V_SPACE_TYPE SPACES.SPACE_TYPE%TYPE;
BEGIN
SELECT SUM(ct.WORTH), sp.SPACE_TYPE INTO V_TOTAL, V_SPACE_TYPE FROM SPACES
sp, CONTRACTS ct WHERE ct.SPACE_ID=sp.SPACE_ID AND sp.SPACE_TYPE=t_space GROUP
BY sp.SPACE_TYPE;
for i in (SELECT cl.* FROM CLIENTS cl, CONTRACTS ct, SPACES sp WHERE
ct.CLIENT_ID=cl.CLIENT_ID AND ct.SPACE_ID= sp.SPACE_ID AND SPACE_TYPE=t_space)
LOOP
client_list(client_list.COUNT+1):=I;
DBMS_OUTPUT.PUT_LINE(client_list(client_list.COUNT));
END LOOP;
END;
19. Create a procedure that gives a gratification to the employee with specified id, only if it is
smaller than a limit, and return the value obtained with an OUT parameter.
_________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

CREATE OR REPLACE PROCEDURE give_gratification(emp_id IN


EMPLOYEES.EMPLOYEE_ID%TYPE, limit IN NUMBER, gratification OUT NUMBER) IS
V_SALARY EMPLOYEES.SALARY%TYPE;
V_EMP_DATE DATE;
BEGIN
SELECT SALARY, EMPLOYMENT_DATE INTO V_SALARY, V_EMP_DATE FROM
EMPLOYEES WHERE EMPLOYEE_ID=emp_id;
CASE WHEN V_EMP_DATE<TO_DATE('01/01/2012','DD/MM/YYYY') THEN
gratification:=V_SALARY*0.25;
WHEN V_EMP_DATE>TO_DATE('01/01/2012','DD/MM/YYYY') AND
V_EMP_DATE<TO_DATE('01/01/2014','DD/MM/YYYY') THEN gratification:=V_SALARY*0.15;
WHEN V_EMP_DATE>TO_DATE('01/01/2012','DD/MM/YYYY') AND
V_EMP_DATE<TO_DATE('01/01/2016','DD/MM/YYYY') THEN gratification:=V_SALARY*0.10;
ELSE gratification:=V_SALARY*0.05;
END CASE;
IF gratification>limit THEN
gratification:=limit;
RAISE_APPLICATION_ERROR(-20003,'The computed gratification is too big.');
END IF;
END;

20. Create a function that receives the id of a client and returns a number representing the place
in a top of most important clients of the company, taking into consideration the value of all contracts
signed with them.
_____________________________________________________________________________________________________________________________ ____________________________________________________________________________________________________________

CREATE OR REPLACE FUNCTION assess_client (cl_id IN CLIENTS.CLIENT_ID%TYPE)


RETURN NUMBER
V_VAL_TOT NUMBER;
V_VAL_CL NUMBER;
RANK NUMBER;
IS
SELECT SUM(WORTH) INTO V_VAL_CL FROM CONTRACTS;
EXECUTE IMMEDIATE 'CREATE TABLE TEMPTAB AS (SELECT CLIENT_ID, SUM(WORTH)
AS GROUP_WORTH FROM CONTRACTS GROUP BY CLIENT_ID)';
SELECT GROUP_WORTH/V_VAL_TOT, %ROWNUM INTO V_VAL_CL, RANK FROM
TEMPTAB WHERE CLIENT_ID=cl_id ORDER BY GROUP_WORTH/V_VAL_TOT DESC;
EXECUTE IMMEDIATE 'DROP TEMPTAB;';
RETURN RANK;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('A generic error has been encountered. ');
RETURN -1;
END;

21. Create a function that displays the number of contracts and returns the value of the largest
one an employee has signed until a given date.
______________________________________________________________________________________________________________________________________________________________ ___________________________________________________________________________

CREATE OR REPLACE FUNCTION assess_employee (emp_id IN


EMPLOYEES.EMPLOYEE_ID%TYPE, deadline DATE)
RETURN NUMBER IS
NO_CTS NUMBER;
V_MAX NUMBER;
BEGIN
SELECT COUNT(CONTRACT_ID), MAX(WORTH) INTO NO_CTS, V_MAX FROM CONTRACTS
WHERE EMPLOYEE_ID=emp_id AND START_DATE<deadline;
DBMS_OUTPUT.PUT_LINE('Employee with id '||emp_id||' has signed '||NO_CTS||' contracts.');
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN -1;
END;

22. Create a function that returns True if a specified client has any outstanding invoices and if
any, sets the value of an IN OUT parameter to how many there are.
_____________________________________________________________________________________________________________________________ ____________________________________________________________________________________________________________

CREATE OR REPLACE FUNCTION has_outstanding_invoices (cl_id IN


CLIENTS.CLIENT_ID%TYPE, no_inv IN OUT NUMBER)
RETURN BOOLEAN IS
invoices_no NUMBER;
BEGIN
SELECT COUNT(inv.INVOICE_ID) INTO invoices_no FROM INVOICES inv, CONTRACTS ct
WHERE ct.CONTRACT_ID=inv.CONTRACT_ID AND UPPER(STATUS)='OUTSTANDING';
IF invoices_no>0 THEN
no_inv:=invoices_no;
RETURN TRUE;
ELSE
no_inv:=0;
RETURN FALSE;
END IF;
END;
23. Create a package that contains a procedure that changes the manager of a given employee.
__________________________________________________________________________________________________________________________________________________ ________________________________________________________________________________________
CREATE OR REPLACE PACKAGE sample_package IS
FUNCTION is_employee(emp_id IN EMPLOYEES.EMPLOYEE_ID%TYPE) RETURN BOOLEAN;
PROCEDURE change_manager(emp_id IN EMPLOYEES.EMPLOYEE_ID%TYPE, man_id IN
EMPLOYEE.EMPLOYEE_ID%TYPE)
END;

CREATE OR REPLACE PACKAGE BODY sample_package IS


FUNCTION is_employee(emp_id IN EMPLOYEES.EMPLOYEE_ID%TYPE) RETURN BOOLEAN IS
V_AUX VARCHAR2(50);
BEGIN
SELECT FIRST_NAME INTO V_AUX FROM EMPLOYEES WHERE EMPLOYEE_ID=emp_id;
RETURN TRUE;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN FLASE;
END;
PROCEDURE change_manager(emp_id IN EMPLOYEES.EMPLOYEE_ID%TYPE, man_id IN
EMPLOYEE.EMPLOYEE_ID%TYPE) IS
BEGIN
IF is_employee(man_id) THEN
EXECUTE IMMEDIATE 'UPDATE EMPLOYEES SET MANAGER_ID=man_id WHERE
EMPLOYEE_ID=emp_id;';
ELSE
DBMS_OUTPUT.PUT_LINE('The manager you are trying to update is not an employee.');
END;
END;
1. Interacting with Application Builder through APEX
https://iacademy3.oracle.com/ords3/f?p=4000:1:14218326443294::NO:RP:FB_FLOW_ID,F4000_P1_FL
OW:9035,9035

https://iacademy3.oracle.com/ords3/f?p=9035:2:14326400302908::NO:::

1. Create a page that contains a report with all employees, offering the possibility to add a contract
in the name of a chosen employee by clicking on their employee id in the report.
The employee id can be modified in the modal page, offering the possibility to select it from a popup list
of values.
2. Create a new page displaying current clients.