cannot reference to cursor instances oracle pl/sql - oracle

CREATE OR REPLACE PROCEDURE employee_info_all_in_one
(p_id IN NUMBER)
IS
CURSOR c_city IS
(SELECT l.city
FROM employees e
INNER JOIN departments d
ON (e.department_id = d.department_id)
INNER JOIN locations l
ON (l.location_id = d.location_id)
WHERE e.employee_id = p_id);
CURSOR c_manager IS
(SELECT e1.last_name
FROM employees e1
INNER JOIN
employees e2
ON (e1.employee_id = e2.manager_id)
WHERE e2.employee_id = p_id);
CURSOR c_department_name IS
(SELECT department_name
FROM employees e
INNER JOIN
departments d
ON (e.department_id = d.department_id)
WHERE e.employee_id = p_id);
TYPE EmpRecTyp IS RECORD
( v_annual_sal NUMBER(9,2),
v_monthly_sal NUMBER(9,2),
v_last_name VARCHAR2(10),
v_deptno NUMBER(3),
v_length NUMBER(2),
v_tenure NUMBER(5),
v_job_id VARCHAR2(20),
v_hire_date DATE,
v_city VARCHAR(25),
v_commission_pct NUMBER(2,2),
v_phone_number VARCHAR2(20),
v_manager VARCHAR2(20),
v_comm_calc NUMBER(10,2),
v_email VARCHAR2(10),
v_department VARCHAR2(20),
v_count NUMBER(4)
);
TYPE EmpRecTyp IS REF CURSOR;
emp_c_v EmpRecTyp;
BEGIN
DBMS_OUTPUT.PUT_LINE('Welcome to the summary of an employee based on his unique id');
DBMS_OUTPUT.PUT_LINE('============================================================');
SELECT salary, last_name, department_id,
TRUNC(MONTHS_BETWEEN(SYSDATE,hire_date),0), job_id,
hire_date, commission_pct, phone_number, email
INTO emp_c_v.v_monthly_sal, emp_c_v.v_last_name, emp_c_v.v_deptno,
emp_c_v.v_tenure, emp_c_v.v_job_id, emp_c_v.v_hire_date, emp_c_v.v_commission_pct,
emp_c_v.v_phone_number, emp_c_v.v_email
FROM employees
WHERE employee_id = p_id;
emp_c_v.v_count := SQL%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE(emp_c_v.v_count||' row retrieved...');
DBMS_OUTPUT.PUT_LINE('=============================');
emp_c_v.v_annual_sal := emp_c_v.v_monthly_sal * 12;
emp_c_v.v_length := LENGTH(emp_c_v.v_last_name);
DBMS_OUTPUT.PUT_LINE('Employee:-> ' || emp_c_v.v_last_name || ' ,and his name contains: ' || emp_c_v.v_length ||' chars');
DBMS_OUTPUT.PUT_LINE('=============================');
DBMS_OUTPUT.PUT_LINE(q'[Belong's to department: ]' || emp_c_v.v_deptno);
DBMS_OUTPUT.PUT_LINE('=============================');
IF (emp_c_v.v_monthly_sal < emp_c_v.v_annual_sal)
THEN
DBMS_OUTPUT.PUT_LINE('Has a annual salary of:-> ' || emp_c_v.v_annual_sal);
ELSE
DBMS_OUTPUT.PUT_LINE('Something wrong in the formula!');
END IF;
IF emp_c_v.v_commission_pct IS NULL
THEN
DBMS_OUTPUT.PUT_LINE('No Commission added to the annual salary!');
ELSE
DBMS_OUTPUT.PUT_LINE('Commission percentage to the salary is:-> '|| emp_c_v.v_commission_pct ||'%');
emp_c_v.v_comm_calc := (emp_c_v.v_annual_sal * emp_c_v.v_commission_pct) + emp_c_v.v_annual_sal;
DBMS_OUTPUT.PUT_LINE('And calculated with annual salary is:->' ||v_comm_calc);
END IF;
DBMS_OUTPUT.PUT_LINE('Working for:-> '|| emp_c_v.v_tenure || ' months as '|| emp_c_v.v_job_id);
DBMS_OUTPUT.PUT_LINE('=============================');
DBMS_OUTPUT.PUT_LINE('Started in:-> '|| emp_c_v.v_hire_date);
DBMS_OUTPUT.PUT_LINE('=============================');
DBMS_OUTPUT.PUT_LINE('Phone number:-> '||emp_c_v.v_phone_number);
DBMS_OUTPUT.PUT_LINE('=============================');
DBMS_OUTPUT.PUT_LINE('Email:-> '||emp_c_v.v_email);
DBMS_OUTPUT.PUT_LINE('=============================');
OPEN c_city;
FETCH c_city INTO v_city;
IF c_city%FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Location:-> '||emp_c_v.v_city);
ELSE
DBMS_OUTPUT.PUT_LINE('Employee location unknown');
END IF;
CLOSE c_city;
OPEN c_manager;
FETCH c_manager INTO emp_c_v.v_manager;
IF c_manager%FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Is in the eyes of manager:-> '||emp_c_v.v_manager);
ELSE
DBMS_OUTPUT.PUT_LINE('Slave '||emp_c_v.v_last_name||' is free!');
END IF;
CLOSE c_manager;
OPEN c_department_name;
FETCH c_department_name INTO emp_c_v.v_department;
IF c_department_name%FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Department Name:-> '||emp_c_v.v_department);
ELSE
DBMS_OUTPUT.PUT_LINE('Employee ' ||emp_c_v.v_last_name||' belongs to no department!');
END IF;
DBMS_OUTPUT.PUT_LINE('================================');
DBMS_OUTPUT.PUT_LINE('Checking for employee with id '|| p_id ||'..');
IF (check_sal2(p_id) IS NULL)
THEN
DBMS_OUTPUT.PUT_LINE('The function returned NULL due to exception, therefore employee does not exist!');
ELSIF (check_sal2(p_id))
THEN
DBMS_OUTPUT.PUT_LINE('Employees salary > average of department '||emp_c_v.v_deptno||' where he belongs.');
ELSE
DBMS_OUTPUT.PUT_LINE('Salary < average of department '||emp_c_v.v_deptno||', where he belongs.');
END IF;
DBMS_OUTPUT.PUT_LINE('=====================================================');
END;
Initially i had only simple variables (v_...) declared in this sub-program but i wanted to make use of true cursor variables i.e like-pointers? i suppose. So i modified and defined a type of record and referenced a cursor "...IS REF CURSOR" for the variables or fields inside it. But when i compile this whole thing i get the error of invalid reference to variable "emp_c_v", why? I am still in the learning stages so sorry for talking nonsense. Thanks

A cursor is a pointer to a result set (sort of), not to an individual record. You can't ever modify a result set. In this case the pointer wouldn't actually point to anything as there isn't a result set (from a query) for it to point to.
Your code will almost compile if you drop the ref cursor and make your variable a record type; so instead of:
TYPE EmpCurTyp IS REF CURSOR;
emp_c_v EmpCurTyp;
use:
emp_c_v EmpRecTyp;
You've also missed a couple of places when changing your references:
DBMS_OUTPUT.PUT_LINE('And calculated with annual salary is:->' ||v_comm_calc);
and
FETCH c_city INTO v_city;
... both need the emp_c_v. prefix before v_comm_calc and v_city respectively.
I assume you're using this as a learning exercise, otherwise this could all be done much more simply.

Related

PL/SQL Loop issue with Cursor

I am trying to create a PL/SQL script that selects the last name and salary of an employee from the table employees. I have a cursor that stores the data and I fetch the cursor which then inserts the data into a new table called BIG_MONEY. I have a user input that selects the number of employees the loop will run through and the loop ends when it reaches the figure they provided.
SET SERVEROUTPUT ON
DROP TABLE BIG_MONEY;
ACCEPT NumberOfStaff
CREATE TABLE BIG_MONEY (
last_name VARCHAR2(10),
salary NUMBER(7, 2)
);
DECLARE V_EMP_ID employees.employee_id%TYPE;
V_EMP_LASTNAME employees.last_name%TYPE;
V_EMP_SALARY employees.salary%TYPE;
CURSOR EMP_Cursor IS
SELECT employee_id, last_name, salary
FROM employees
ORDER BY salary DESC last_name ASC
BEGIN
OPEN EMP_Cursor;
LOOP
FETCH EMP_Cursor INTO V_EMP_ID, V_EMP_LASTNAME, V_EMP_SALARY;
INSERT INTO BIG_MONEY (last_name, salary)
VALUES (V_EMP_LASTNAME, V_EMP_SALARY)
EXIT WHEN EMP_Cursor%ROWCOUNT = '&NumberOfStaff';
DMBS_OUTPUT.PUT_LINE
('Employee' || TO_CHAR (V_EMP_ID) || 'last name is' || TO_CHAR (V_EMP_LASTNAME)
|| 'and makes' || TO_CHAR (V_EMP_SALARY) || 'a month');
END LOOP;
CLOSE EMP_Cursor;
What am I doing wrong here? I would assume my logic is correct but the syntax is where I'm making a mistake.

What considerations Do You have about my PLSQL package?

I had a little doubts about my code but yesterday I finally understood some points about to how to start coding my final package project. I share this code with the purpose if You want suggest me some change to perform or anything about my package I will appreciate you.
CREATE OR REPLACE PACKAGE BODY emp_upd_pkg IS
-- Function to update commission of employee --
FUNCTION comm_upd(
p_empid employees.employee_id%TYPE)
RETURN employees.commission_pct%TYPE
IS
v_oldcomm employees.commission_pct%TYPE;
v_newcomm employees.commission_pct%TYPE;
BEGIN
-- Valid parameter --
SELECT commission_pct
INTO v_oldcomm
FROM employees
WHERE employee_id = p_empid;
IF
v_oldcomm IS NOT NULL THEN
UPDATE employees
SET commission_pct = commission_pct * 1.1
WHERE employee_id = p_empid
RETURNING commission_pct
INTO v_newcomm;
RETURN v_newcomm;
ELSE
/*UPDATE employees
SET commission_pct = 0.1
WHERE employee_id = p_empid
RETURNING commission_pct
INTO v_newcomm;
RETURN v_newcomm;*/
RETURN (0);
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN (0);
END comm_upd;
-- Function to update salary of employee --
FUNCTION sal_upd(
p_empid employees.employee_id%TYPE)
RETURN employees.salary%TYPE
IS
v_oldsal employees.salary%TYPE;
v_newsal employees.salary%TYPE;
BEGIN
-- Valid parameter --
SELECT salary
INTO v_oldsal
FROM employees
WHERE employee_id = p_empid;
IF
v_oldsal IS NOT NULL THEN
UPDATE employees
SET salary = salary + 100
WHERE employee_id = p_empid
RETURNING salary
INTO v_newsal;
RETURN v_newsal;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN (0);
END sal_upd;
-- Procedure to update comm and sal using package functions --
PROCEDURE commsal_upd(
p_empid employees.employee_id%TYPE)
IS
v_newcomm employees.commission_pct%TYPE;
v_newsal employees.salary%TYPE;
BEGIN
-- Call package functions to update sal and comm of all employees --
DBMS_OUTPUT.PUT_LINE(comm_upd(p_empid));
DBMS_OUTPUT.PUT_LINE(sal_upd(p_empid));
-- Query for final inform --
SELECT commission_pct, salary
INTO v_newcomm, v_newsal
FROM employees
WHERE employee_id = p_empid;
DBMS_OUTPUT.PUT_LINE('THE NEW COMMISSION FOR EMPLOYEE' || p_empid ||
' IS ' || v_newcomm || ' AND THE NEW SALARY IS ' || v_newsal);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO EXISTE EMPLEADO INGRESADO');
END commsal_upd;
END emp_upd_pkg;
Also, I have a little question: When I do use of a function within a procedure, Can I restringe the "RETURN" sentence of the function with the propuse of only send to call Procedure information?
SET SERVEROUTPUT ON
DECLARE
CURSOR cur_empid IS
SELECT employee_id
FROM employees;
TYPE empid_rec IS RECORD(
p_empid employees.employee_id%TYPE);
empid empid_rec;
BEGIN
FOR empid IN cur_empid LOOP
emp_upd_pkg.commsal_upd(empid.employee_id);
EXIT WHEN cur_empid%NOTFOUND;
END LOOP;
END;
/
When I use a simple record to update all employees I receive in console information about RETURN info of functions and info about DBMS... of procedure. Can I change my code to receive only Procedure information on console? Thanks!.
0
24100
THE NEW COMMISSION FOR EMPLOYEE100 IS AND THE NEW SALARY IS 24100
0
17100
THE NEW COMMISSION FOR EMPLOYEE101 IS AND THE NEW SALARY IS 17100
0
17100
THE NEW COMMISSION FOR EMPLOYEE102 IS AND THE NEW SALARY IS 17100
0
9100

PL/SQL inserting a new record exception handling

I have an assignment in Oracle PL/SQL. I have to count the maximum number of employees working under a manager, and if this manager has more than 7 employees working under him I must raise an exception, which gives the message:
('Manager ||manager_name||' has maximium number of employees working under him'.)
Otherwise I must insert a new employee and give the message:
('It was inserted a new employee for the manager ||manager_name).
I have written the code, but I know something is wrong.
create table temp_emp as select * from employees;
select * from temp_emp;
create or replace procedure insert_emp(mngrId IN temp_emp.manager_id%type)
IS
ex_hugemp EXCEPTION;
emp_counter NUMBER;
fname temp_emp.first_name%type;
BEGIN
SELECT COUNT(*) INTO emp_counter
FROM temp_emp
WHERE temp_emp.manager_id=mngrId;
IF emp_counter > 7 THEN
RAISE ex_hugemp;
ELSE
INSERT INTO temp_emp(EMPLOYEE_ID, FIRST_NAME, LAST_NAME, EMAIL, PHONE_NUMBER
,HIRE_DATE, JOB_ID, SALARY, COMMISSION_PCT
,MANAGER_ID,DEPARTMENT_ID)
VALUES(LENGTH(EMPLOYEE_ID)+1, 'KAY', 'HORSTMAN', NULL, NULL
,'28-MAY-2013', 'IT_PROG', 24000, NULL, 103, 60);
DBMS_OUTPUT.PUT_LINE('It was inserted a new employee for the manager '||fname);
END IF;
EXCEPTION
WHEN ex_hugemp THEN
DBMS_OUTPUT.PUT_LINE('Manager '||fname||' has maximium number of employees working under him.');
END;
/
Your variable fname is empty. Fill it:
SELECT first_name
INTO fname
FROM temp_emp
WHERE employee_id = mngrid;
Use for the insert the same mngrid. Why is 103?
What is
LENGTH(EMPLOYEE_ID)+1
First: this will convert employee_id in string, get the length from the string and add 1. Do you really want this?. And second: you cannot use column name in values(). Create sequence (change 1 with your value to start):
CREATE SEQUENCE TEMP_EMP_SEQ START WITH 1;
and than use it in your procedure
temp_emp_seq.nextval
.
CREATE OR REPLACE PROCEDURE insert_emp (mngrid IN temp_emp.manager_id%TYPE) IS
ex_hugemp EXCEPTION;
emp_counter NUMBER;
fname temp_emp.first_name%TYPE;
BEGIN
SELECT first_name
INTO fname
FROM temp_emp
WHERE employee_id = mngrid;
SELECT COUNT (*)
INTO emp_counter
FROM temp_emp
WHERE temp_emp.manager_id = mngrid;
IF emp_counter > 7 THEN
RAISE ex_hugemp;
ELSE
INSERT INTO temp_emp (employee_id, first_name, last_name, email, phone_number, hire_date, job_id, SALARY,COMMISSION_PCT,MANAGER_ID,DEPARTMENT_ID)
VALUES( temp_emp_seq.nextval,'KAY','HORSTMAN',NULL,NULL,TO_DATE('28-05-2013','dd-mm-yyyy'),'IT_PROG',24000,NULL,mngrid,10);
DBMS_OUTPUT.put_line ('It was inserted a new employee for the manager ' || fname);
END IF;
EXCEPTION
WHEN ex_hugemp THEN
DBMS_OUTPUT.put_line ('Manager ' || fname || ' has maximium number of employees working under him.');
END;
/

oracle - write package output results to a file on client side

So i have this:
CREATE OR REPLACE PACKAGE my_first_package
IS
PROCEDURE employee_analysis
(p_id IN NUMBER := 100, /*default formal parameter with no arguments for invokation */
p_percent IN NUMBER := 0.01); /* -||- */
END my_first_package;
CREATE OR REPLACE PACKAGE BODY my_first_package
IS
PROCEDURE employee_analysis
(p_id IN NUMBER := 100,
p_percent IN NUMBER := 0.01)
IS
CURSOR c_city IS
(SELECT l.city
FROM employees e
INNER JOIN departments d
ON (e.department_id = d.department_id)
INNER JOIN locations l
ON (l.location_id = d.location_id)
WHERE e.employee_id = p_id);
CURSOR c_manager IS
(SELECT e1.last_name
FROM employees e1
INNER JOIN
employees e2
ON (e1.employee_id = e2.manager_id)
WHERE e2.employee_id = p_id);
CURSOR c_department_name IS
(SELECT department_name
FROM employees e
INNER JOIN
departments d
ON (e.department_id = d.department_id)
WHERE e.employee_id = p_id);
/*-----------------------------------------------------------------------------*/
v_annual_sal NUMBER(9,2);
v_monthly_sal NUMBER(9,2);
v_last_name VARCHAR2(10);
v_deptno NUMBER(3);
v_length NUMBER(2);
v_tenure NUMBER(5);
v_job_id VARCHAR2(20);
v_hire_date DATE;
v_city VARCHAR(25);
v_commission_pct NUMBER(2,2);
v_phone_number VARCHAR2(20);
v_manager VARCHAR2(20);
v_comm_calc NUMBER(10,2);
v_email VARCHAR2(10);
v_department VARCHAR2(20);
v_count NUMBER(4);
v_old_salary NUMBER(9,2);
v_new_salary NUMBER(9,2);
v_lname VARCHAR2(10);
v_phone_number_format VARCHAR2(25);
v_phone_number_length NUMBER(3);
v_tax NUMBER(8,4);
v_sum_sal_departments NUMBER;
BEGIN
DBMS_OUTPUT.PUT_LINE('Welcome to the summary of an employee based on his unique id');
DBMS_OUTPUT.PUT_LINE('============================================================');
/*-----------------------------------------------------------------------------*/
SELECT salary, last_name, department_id,
TRUNC(MONTHS_BETWEEN(SYSDATE,hire_date),0), job_id,
hire_date, commission_pct, phone_number, email, LENGTH(phone_number)
INTO v_monthly_sal, v_last_name, v_deptno,
v_tenure, v_job_id, v_hire_date, v_commission_pct,
v_phone_number, v_email, v_phone_number_length
FROM employees
WHERE employee_id = p_id;
/*-----------------------------------------------------------------------------*/
v_count := SQL%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE(v_count||' Employee found...');
/*-----------------------------------------------------------------------------*/
v_annual_sal := v_monthly_sal * 12;
v_length := LENGTH(v_last_name);
DBMS_OUTPUT.PUT_LINE('Employee:-> ' || v_last_name || ' ,and his name contains: ' || v_length ||' chars');
DBMS_OUTPUT.PUT_LINE(q'[Belong's to department: ]' || v_deptno);
/*-----------------------------------------------------------------------------*/
IF (v_monthly_sal < v_annual_sal)
THEN
DBMS_OUTPUT.PUT_LINE('Has a annual salary of:-> ' || v_annual_sal);
ELSE
DBMS_OUTPUT.PUT_LINE('Something wrong in the formula!');
END IF;
/*-------------------------------------------------------------------------------*/
IF v_commission_pct IS NULL
THEN
DBMS_OUTPUT.PUT_LINE('No Commission added to the annual salary!');
ELSE
DBMS_OUTPUT.PUT_LINE('Commission percentage to the salary is:-> '|| v_commission_pct ||'%');
v_comm_calc := (v_annual_sal * v_commission_pct) + v_annual_sal;
DBMS_OUTPUT.PUT_LINE('And calculated with annual salary is:-> ' ||v_comm_calc);
END IF;
/*-------------------------------------------------------------------------------*/
DBMS_OUTPUT.PUT_LINE('Working for:-> '|| v_tenure || ' months as '|| v_job_id);
DBMS_OUTPUT.PUT_LINE('Started in:-> '|| v_hire_date);
/*-------------------------------------------------------------------------------*/
IF v_phone_number_length = 12
THEN
v_phone_number_format := '(' || SUBSTR(v_phone_number,1,3) || ')' ||
'-' || SUBSTR(v_phone_number,5,3) ||
'-' || SUBSTR(v_phone_number,9,4);
DBMS_OUTPUT.PUT_LINE('Phone number:-> '|| v_phone_number_format);
ELSIF v_phone_number_length = 18
THEN
v_phone_number_format := '(' || SUBSTR(v_phone_number,1,3) || ')' ||
'-' || SUBSTR(v_phone_number,5,2) ||
'-' || SUBSTR(v_phone_number,8,4) || '-'
|| SUBSTR(v_phone_number,13,6);
DBMS_OUTPUT.PUT_LINE('Phone number:-> '|| v_phone_number_format);
ELSE
DBMS_OUTPUT.PUT_LINE('Phone number digits not in range, check the length of the phone numbers from the table');
END IF;
/*-------------------------------------------------------------------------------*/
DBMS_OUTPUT.PUT_LINE('Email:-> '||v_email);
/*-------------------------------------------------------------------------------*/
OPEN c_city;
FETCH c_city
INTO v_city;
IF c_city%FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Location:-> '||v_city);
ELSE
DBMS_OUTPUT.PUT_LINE('Employee location unknown');
END IF;
CLOSE c_city;
/*-------------------------------------------------------------------------------*/
OPEN c_manager;
FETCH c_manager
INTO v_manager;
IF c_manager%FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Is in the eyes of manager:-> '||v_manager);
ELSE
DBMS_OUTPUT.PUT_LINE('Slave '||v_last_name||' is free!');
END IF;
CLOSE c_manager;
/*-------------------------------------------------------------------------------*/
OPEN c_department_name;
FETCH c_department_name
INTO v_department;
IF c_department_name%FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Department Name:-> '||v_department);
ELSE
DBMS_OUTPUT.PUT_LINE('Employee ' ||v_last_name||' belongs to no department!');
END IF;
/*--------------------------------------------------------------------------------*/
DBMS_OUTPUT.PUT_LINE('Checking the current employee with id:-> '|| p_id ||'..');
IF (check_sal2(p_id) IS NULL)
THEN
DBMS_OUTPUT.PUT_LINE('The function returned NULL due to exception, therefore employee does not exist!');
ELSIF (check_sal2(p_id))
THEN
DBMS_OUTPUT.PUT_LINE('Employees salary > average of department '||v_deptno||' where he belongs.');
ELSE
DBMS_OUTPUT.PUT_LINE('Salary < average of department '||v_deptno||', where he belongs.');
END IF;
/*--------------------------------------------------------------------------------*/
SELECT salary
INTO v_old_salary
FROM employees
WHERE employee_id = p_id;
DBMS_OUTPUT.PUT_LINE('Before the raise of ' || p_percent ||
' %, the salary was:-> '|| v_old_salary);
/*--------------------------------------------------------------------------------*/
IF (p_percent > 0.01)
THEN
DBMS_OUTPUT.PUT_LINE('Maximum increase allowance for the moment is only 0.01 %, thus no increase in salary is made');
ELSIF (p_percent < 0.01)
THEN
DBMS_OUTPUT.PUT_LINE('Minimum percent allowance for the moment is only 0.01 %, thus no increase in salary is made');
ELSE
UPDATE employees
SET salary = salary * (1 + p_percent/100)
WHERE employee_id = p_id;
SELECT last_name, salary
INTO v_lname, v_new_salary
FROM employees
WHERE employee_id = p_id;
DBMS_OUTPUT.PUT_LINE('After the raise of ' || p_percent ||
' %, the salary is:-> '|| v_new_salary);
END IF;
/*--------------------------------------------------------------------------------*/
DBMS_OUTPUT.PUT_LINE('===========================================================');
DBMS_OUTPUT.PUT_LINE('===========================================================');
DBMS_OUTPUT.PUT_LINE('===========================================================');
FOR i IN (SELECT SUM(salary) AS "SUMY", department_id
FROM employees
GROUP BY department_id)
LOOP
IF i.department_id IS NULL
THEN
DBMS_OUTPUT.PUT_LINE('Unknown department '|| i.department_id ||' earns:-> '|| i.sumy);
ELSE
DBMS_OUTPUT.PUT_LINE('Department '|| i.department_id ||' earns:-> '|| i.sumy);
END IF;
END LOOP;
FOR j IN (SELECT SUM(sumy) AS "DEP_SUM"
FROM (SELECT SUM(salary) AS "SUMY"
FROM employees
GROUP BY department_id))
LOOP
v_sum_sal_departments := j.dep_sum;
DBMS_OUTPUT.PUT_LINE('Total income on all departments:-> '|| j.dep_sum);
END LOOP;
SELECT taxes_pkg.tax(salary)
INTO v_tax
FROM employees
WHERE employee_id = p_id;
DBMS_OUTPUT.PUT_LINE('Salary after 0.08 % tax withdrawal:-> '|| v_tax);
FOR k IN (SELECT last_name
FROM employees
WHERE salary = (SELECT MAX(salary)
FROM employees))
LOOP
DBMS_OUTPUT.PUT_LINE('Employee with the highest salary is:-> '||k.last_name);
END LOOP;
FOR k IN (SELECT last_name, hire_date
FROM employees
WHERE hire_date = (SELECT MAX(hire_date)
FROM employees))
LOOP
DBMS_OUTPUT.PUT_LINE('Our newest employees are:-> ' || k.last_name);
END LOOP;
FOR m IN (SELECT last_name
FROM employees
WHERE hire_date = (SELECT MIN(hire_date)
FROM employees))
LOOP
DBMS_OUTPUT.PUT_LINE('Our oldest employees are:-> '||m.last_name);
END LOOP;
/*--------------------------------------------------------------------------------*/
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Employee with id:-> ' || p_id || ' does not exist, check data from your tables!');
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE('Unknown propagation');
END employee_analysis;
END my_first_package;
I seached about something called utl_file package for exporting data from oracle database and so on, but i didn't understand much and didn't found what i was looking for. Basically what i want is, how can i "export" all of the output from the screen after running this useless package above? Is there a way to modify the package add features and stuff to it? It is possible? Thanks...

Loop to check all 14 days in the pay period

Name: Calc_Anniversary
Input: Pay_Date, Hire_Date, Termination_Date
Output: "Y" if is the anniversary of the employee's Hire_Date, "N" if it is not, and "T" if he has been terminated before his anniversary.
Description: Create local variables to hold the month and day of the employee's Date_of_Hire, Termination_Date, and of the processing date using the TO_CHAR function. First check to see if he was terminated before his anniversary. The anniversary could be on any day during the pay period, so there will be a loop to check all 14 days in the pay period to see if one was his anniversary.
CREATE OR replace FUNCTION Calc_anniversary(
incoming_anniversary_date IN VARCHAR2)
RETURN BOOLEAN
IS
hiredate VARCHAR2(20);
terminationdate VARCHAR(20);
employeeid VARCHAR2(38);
paydate NUMBER := 0;
BEGIN
SELECT Count(arndt_raw_time_sheet_data.pay_date)
INTO paydate
FROM arndt_raw_time_sheet_data
WHERE paydate = incoming_anniversary_date;
WHILE paydate <= 14 LOOP
SELECT To_char(employee_id, '999'),
To_char(hire_date, 'DD-MON'),
To_char(termination_date, 'DD-MON')
INTO employeeid, hiredate, terminationdate
FROM employees,
time_sheet
WHERE employees.employee_id = time_sheet.employee_id
AND paydate = pay_date;
IF terminationdate > hiredate THEN
RETURN 'T';
ELSE
IF To_char(SYSDATE, 'DD-MON') = To_char(hiredate, 'DD-MON')THEN
RETURN 'Y';
ELSE
RETURN 'N';
END IF;
END IF;
paydate := paydate + 1;
END LOOP;
END;
Tables I am using
CREATE TABLE Employees ( EMPLOYEE_ID INTEGER,
FIRST_NAME VARCHAR2(15),
LAST_NAME VARCHAR2(25),
ADDRESS_LINE_ONE VARCHAR2(35),
ADDRESS_LINE_TWO VARCHAR2(35),
CITY VARCHAR2(28),
STATE CHAR(2),
ZIP_CODE CHAR(10),
COUNTY VARCHAR2(10),
EMAIL VARCHAR2(16),
PHONE_NUMBER VARCHAR2(12),
SOCIAL_SECURITY_NUMBER VARCHAR2(11),
HIRE_DATE DATE,
TERMINATION_DATE DATE,
DATE_OF_BIRTH DATE,
SPOUSE_ID INTEGER,
MARITAL_STATUS CHAR(1),
ALLOWANCES INTEGER,
PERSONAL_TIME_OFF FLOAT,
CONSTRAINT pk_employee_id PRIMARY KEY (EMPLOYEE_ID),
CONSTRAINT fk_spouse_id FOREIGN KEY (SPOUSE_ID) REFERENCES EMPLOYEES (EMPLOYEE_ID))
/
CREATE TABLE Arndt_Raw_Time_Sheet_data ( EMPLOYEE_ID INTEGER,
PAY_DATE DATE,
HOURS_WORKED FLOAT,
SALES_AMOUNT FLOAT,
CONSTRAINT pk_employee_id_pay_date_time PRIMARY KEY (EMPLOYEE_ID, PAY_DATE),
CONSTRAINT fk_employee_id_time FOREIGN KEY (EMPLOYEE_ID) REFERENCES EMPLOYEES (EMployee_ID));
error FUNCTION Calc_Anniversary compiled
Warning: execution completed with warning
Functions have to return something. It is normal for the RETURN statement to be the last statement in a function.
You have chosen not to do this, and that's why you're getting an error. All your RETURN statements are embedded in conditional branches, so if your logic never executes the loop you will never execute a RETURN.
Your loop logic is confused. You are populating your paydate as a count (so why is it called ""paydate"?) but your initialisation query compares 'paydate' to your parameter incoming_anniversary_date which is a date. Perhaps you meant to compare it to the tabel column pay_date? So who knows what your code is actually doing?
Anyway, the most important thing is to introduce some best practice into your function: you need to populate a variable and restrict yourself to just the one RETURN statement.
return_value char(1);
BEGIN
return_value := 'X';
....
WHILE paydate <= 14 LOOP
....
IF terminationdate > hiredate THEN
return_value := 'T';
ELSE
IF To_char(SYSDATE, 'DD-MON') = To_char(hiredate, 'DD-MON')THEN
return_value := 'Y';
ELSE
return_value := 'N';
END IF;
END IF;
...
END LOOP;
RETURN return_value;
END;
Also, this is wrong:
IF terminationdate > hiredate THEN
You converted those dates to strings, which means that '23-JAN' > '22-DEC'. This is probably not the result you intend.
Oh, and rename your variable paydate to something a bit less confusing, like l_count.
create or replace
FUNCTION Calc_Anniversary(employee IN VARCHAR2)
RETURN VARCHAR2
IS
counter INTEGER;
term_date VARCHAR2(15);
h_date VARCHAR2(15);
p_date DATE;
BEGIN
SELECT TO_CHAR(hire_date, 'DD-MON'), TO_CHAR(termination_date, 'DD-MON'), pay_date INTO h_date, term_date, p_date
FROM employees e, diaz_raw_time_sheet_data d
WHERE e.employee_id = d.employee_id
AND e.employee_id = employee;
FOR counter IN 0 .. 14 LOOP
IF term_date > h_date THEN
RETURN 'T';
ELSIF TO_CHAR(p_date,'DD-MON') = h_date THEN
RETURN 'Y';
END IF;
p_date := p_date - 1;
END LOOP;
IF h_date <> TO_CHAR(p_date, 'DD-MON') THEN
RETURN 'N';
END IF;
END;

Resources