extract(year from current_timestamp)
Suchts das Beispiel, ist fast das selbe nur als Prozedur:
Schreiben Sie eine Prozedur die die Email Adresse eines Mitarbeiters (falls leer) ändert auf
Lösung von Juri Schreib
CREATE OR REPLACE TRIGGER "Testerino_1"
BEFORE UPDATE OF HIRE_DATE ON employees FOR EACH ROW
BEGIN
IF extract(year from current_timestamp) - extract(year from :OLD.HIRE_DATE) > 40 THEN
RAISE_APPLICATION_ERROR(-20202,'Der Arbeiter ist bereits mehr als 40 Jahre angestellt!');
END IF;
END;
Lösung von Juri Schreib
CREATE OR REPLACE FUNCTION FUNCTION1
(
JOB_ID in jobs.job_id%type
, JOB_TITLE in jobs.job_title%type
, MIN_SALARY in jobs.min_salary%type
, MAX_SALARY IN jobs.max_salary%type
, EMPLOYEE_ID IN employee.employee_id%type
) RETURN VARCHAR2 AS
BEGIN
insert into jobs values ( job_id, job_tile, min_salary, max_salary);
if sql%rowcount < 1 then
RAISE_APPLICATION_ERROR(-20202,'Es wurde kein neuer job erstellt!');
end if;
update employees
set job_id = JOB_ID
where employee_id = EMPLOYEE_ID;
if sql%rowcount < 1 then
RAISE_APPLICATION_ERROR(-2,'Der neue Job konnte dem Employee nicht zugewiesen werden!');
end if;
return null;
END FUNCTION1;
Lösung von Juri Schreib
create or replace procedure test as
cursor dep_cur is
select location_id
from departments;
cursor emp_cur is
select employee_id
from employee;
v_dep varchar2(255);
v_emp varchar2(255);
BEGIN
OPEN dep_cur;
LOOP
open emp_cur;
loop
UPDATE EMPLOYEES
set phone_number = (v_dep || '.' || v_emp)
where employee_id = v_emp;
END LOOP;
CLOSE emp_cur;
END LOOP;
CLOSE dep_cur;
END;
Lösung von Juri Schreib
CREATE OR REPLACE FUNCTION FUNCTION2
(
MANAGER_ID IN Departments.manager_id%type
) RETURN boolean as
manager_departments Number;
BEGIN
select sum(department_id)
into manager_departments
from departments
where manager_id = manager_id;
if manager_departments > 1 then
return true;
else
return false;
end if;
END FUNCTION2;
Lösung vn Juri Schreib
create or replace PROCEDURE TEST3 AS
cursor employee_cur is
select *
from employees;
v_employee employee_cur%ROWTYPE;
v_job jobs%ROWTYPE;
BEGIN
OPEN employee_cur;
LOOP
FETCH employee_cur INTO v_employee;
EXIT WHEN employee_cur%NOTFOUND;
select *
into v_job
from jobs
where JOB_ID = v_employee.job_id;
if v_employee.salary > v_job.max_salaray then
SET_SALARY( v_employee.employee_id, v_employee.salary * 0.95);
DBMS_OUTPUT.PUT_LINE('Gehalt von ' || v_employee.first_name || ' ' || v_employee.last_name || ' ist zu hoch und wird Korrigiert');
elsif v_employee.salary < v_job.min_salaray then
DBMS_OUTPUT.PUT_LINE('Gehalt von ' || v_employee.first_name || ' ' || v_employee.last_name || ' ist zu niedrig');
end if;
END LOOP;
CLOSE employee_cur;
NULL;
END TEST3;
Lösung von Manuel Reinsberger
--------------- SHOW_EMPLOYEE_JOB_AND_HISTORY
-- Test Data
--
-- Test with employee_id 100000 and it will return an empty cursor, with employee_id 101 it will show a cursor with two entries
CREATE OR REPLACE FUNCTION SHOW_EMPLOYEE_JOB_AND_HISTORY (
employee_id_ job_history.employee_id%TYPE
) RETURN SYS_REFCURSOR AS
jobs SYS_REFCURSOR;
BEGIN
IF employee_id_ IS NULL THEN
RAISE_APPLICATION_ERROR(-20041, 'Employee ID must not be null');
END IF;
OPEN jobs FOR SELECT employee_id, start_date, end_date, job_id, department_id
FROM job_history
WHERE employee_id = employee_id_;
RETURN jobs;
END SHOW_EMPLOYEE_JOB_AND_HISTORY;
Lösung von Manuel Reinsberger
--------------- CHECK_EMPLOYEE_SALARY
-- Test Data
--
-- UPDATE employees SET salary = 17000 WHERE employee_ID = 102;
--
-- SELECT salary FROM employees WHERE employee_id = 102;
-- This will show that the salary is 17000
--
-- After executing the function it will return 1 to signal that the salary is in range and
-- SELECT salary FROM employees WHERE employee_id = 102;
-- shows that the salary has successfully been changed to 17850
--
-- UPDATE employees SET salary = 17 WHERE employee_ID = 102;
--
-- This will not even work since the trigger prevents updating to lower values
--
-- UPDATE employees SET salary = 99999 WHERE employee_ID = 102;
--
-- After executing the function it will return 0 to signal that the salary is NOT in range and
-- SELECT salary FROM employees WHERE employee_id = 102;
-- shows that the salary has not been changed from 17
create or replace FUNCTION CHECK_EMPLOYEE_SALARY (
employee_id_ employees.employee_id%TYPE
) RETURN DECIMAL AS
min_sal jobs.min_salary%TYPE;
max_sal jobs.max_salary%TYPE;
sal employees.salary%TYPE;
BEGIN
IF employee_id_ IS NULL THEN
RAISE_APPLICATION_ERROR(-20021, 'employee_id_ must not be null');
END IF;
BEGIN
SELECT min_salary, max_salary, salary INTO min_sal, max_sal, sal
FROM employees INNER JOIN jobs ON (employees.job_id = jobs.job_id)
WHERE employee_id = employee_id_;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20020, 'Employee not found');
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20099, 'SEVERE SERVER ERROR');
END;
IF sal < min_sal THEN
RETURN 0;
END IF;
IF sal > max_sal THEN
RETURN 0;
END IF;
if (sal*1.05) > max_sal THEN
sal := max_sal;
ELSE
sal := sal*1.05;
DBMS_OUTPUT.PUT_LINE('v_Return = ' || sal);
END IF;
UPDATE employees SET salary = sal WHERE employee_id = employee_id_;
IF sql%ROWCOUNT != 1 THEN
RAISE_APPLICATION_ERROR(-20021, 'Employee salary could not be changed');
END IF;
RETURN 1;
END CHECK_EMPLOYEE_SALARY;
Lösung von Manuel Reinsberger
--------------- EMPLOYEE_NOT_LESS_THAN_MIN
-- Test data
--
-- UPDATE employees SET salary = 17 WHERE employee_id = 102;
-- This will blow up with the error that 'Employee salary must be larger than min salary for their job'
-- UPDATE employees SET salary = 17000 WHERE employee_id = 102;
-- This will work and NOT throw anything
CREATE OR REPLACE TRIGGER EMPLOYEE_NOT_LESS_THAN_MIN
BEFORE UPDATE OF SALARY ON EMPLOYEES
FOR EACH ROW
DECLARE
min_sal jobs.min_salary%TYPE;
BEGIN
IF :new.job_id IS NULL OR LENGTH(:new.job_id) = 0 THEN
RAISE_APPLICATION_ERROR(-20051, 'Employee must have job');
END IF;
BEGIN
SELECT min_salary INTO min_sal FROM jobs WHERE job_id = :new.job_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20011, 'Job not found');
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20099, 'SEVERE SERVER ERROR');
END;
IF :new.salary < min_sal THEN
RAISE_APPLICATION_ERROR(-20003, 'Employee salary must be larger than min salary for their job');
END IF;
END;
Lösung von Manuel Reinsberger
--------------- CREATE_EMAIL_FOR_EMPLOYEES
-- Test data
--
-- Try with employee_id = 102 now and it won't change anything
--
-- UPDATE employees SET email = ' ' WHERE employee_id = 102;
--
-- Try with employee_id = 102 now and it will change it to 'Lex@De Haan.Executive'
create or replace PROCEDURE CREATE_EMAIL_FOR_EMPLOYEES
(
employee_id_ IN employees.employee_id%type
) AS
cur_email employees.email%type;
f_name employees.first_name%TYPE;
l_name employees.last_name%TYPE;
d_name departments.department_name%TYPE;
BEGIN
IF employee_id_ IS NULL THEN
RAISE_APPLICATION_ERROR(-20001, 'employee_id_ must not be null');
END IF;
BEGIN
SELECT email, first_name, last_name, department_name INTO cur_email, f_name, l_name, d_name
FROM employees INNER JOIN departments ON (employees.department_id = departments.department_id)
WHERE employee_id = employee_id_;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20011, 'Employee not found');
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20099, 'SEVERE SERVER ERROR');
END;
IF cur_email = ' ' THEN
IF f_name IS NULL OR length(f_name) = 0 THEN
RAISE_APPLICATION_ERROR(-20011, 'Employee has no first name');
END IF;
IF l_name IS NULL OR length(l_name) = 0 THEN
RAISE_APPLICATION_ERROR(-20012, 'Employee has no last name');
END IF;
IF d_name IS NULL OR length(d_name) = 0 THEN
RAISE_APPLICATION_ERROR(-20013, 'Employee has no department');
END IF;
UPDATE employees SET email = concat(concat(concat(concat(f_name, '@'), l_name), '.'), d_name) WHERE employee_id = employee_id_;
IF sql%ROWCOUNT != 1 THEN
RAISE_APPLICATION_ERROR(-20014, 'Employee email could not be changed');
END IF;
END IF;
END CREATE_EMAIL_FOR_EMPLOYEES;
-- Test Case
INSERT INTO EMPLOYEES VALUES (999,'Max','Mustermann',null,'147','2016-1-1',10,0,0,100,90);
-- Übung
create or replace TRIGGER test1
AFTER INSERT ON EMPLOYEES FOR EACH ROW
DECLARE
v_max_salary jobs.max_salary%type;
BEGIN
select max_salary
into v_max_salary
from jobs
where job_id = :NEW.job_id;
UPDATE EMPLOYEES
set salary = v_max_salary
where employee_id = :NEW.employee_id;
END;
Lösung von Juri Schreib
create or replace TRIGGER test2
AFTER INSERT ON EMPLOYEES FOR EACH ROW
DECLARE
pragma autonomous_transaction;
v_employee employees%rowtype;
v_dep_name departments.department_name%type;
BEGIN
select *
into v_employee
from employees
where employee_id = :NEW.employee_id;
select DEPARTMENT_NAME
into v_dep_name
from departments
where department_id = v_employee.department_id;
if v_employee.email = '' then
UPDATE EMPLOYEES
set email = (v_employee.first_name || '.' || v_employee.last_name || '@' || v_dep_name)
where employee_id = v_employee.employee_id;
end if;
END;
CREATE OR REPLACE TRIGGER check_max_salaray
BEFORE INSERT ON employees
v_max_salary jobs.max_salary%type;
BEGIN
if new.job_id is null then
RAISE_APPLICATION_ERROR(-20001, "job_id should be defined");
end if;
if new.salary is null then
RAISE_APPLICATION_ERROR(-20001, "Salary should be defined");
end if;
select max_salary
from jobs
into v_max_salary
where new.job_id = job_id;
if v_max_salary is null or v_max_salary%rowxount > 1 then
RAISE_APPLICATION_ERROR(-20001, "Could not retrive the max salaray for the job id" || job_id);
if v_max_salary is not new.salary then
RAISE_APPLICATION_ERROR(-20001, "max_salary is " || new.salary || ", but should be " || v_max_salary);
end if;
END;
ALTER TRIGGER check_max_salaray DISABLE;
create or replace PROCEDURE inc_salary AS
v_salary employees.salary%type;
v_hire_date employees.hire_date%type;
v_hire_age Number;
BEGIN
select salary
into v_salary
from employees
where employee_id = 110;
if v_salray is null then
RAISE_APPLICATION_ERROR(-20001, 'salry must not be null');
end if;
select hire_date
into v_hire_date
from employees
where employee_id = 110;
if v_hire_date is null then
RAISE_APPLICATION_ERROR(-20002, 'hire_date must not be null');
end if;
v_hire_age := extract(year from current_timestamp) - extract(year from v_hire_date);
if v_hire_age > 7 then
update employees
set salary = v_salary * 1.25
where employee_id = 110;
elsif v_hire_age > 4 then
update employees
set salary = v_salary * 1.12
where employee_id = 110;
else
update employees
set salary = v_salary * 1.07
where employee_id = 110;
end if;
EXCEPTION
when OTHERS
if v_salray is null then
RAISE_APPLICATION_ERROR(-20420, 'internal server error');
end if;
END;
-- Test Case
select salaray
from employees
where employee_id = 110
-- Dann die Prozdur durchlaufen
-- Und prüfen ob sich der Betrag erhöht hat