-------------------------------------------------------- -- DDL for Table PERSONS_JN -------------------------------------------------------- CREATE TABLE "HR"."PERSONS_JN" ( "PJN_ID" NUMBER, "PJN_PER_NAME" VARCHAR2(20 BYTE), "PJN_PER_BIRTHDAY" DATE, "PJN_PER_ID" NUMBER, "PJN_PER_GEN_NAME" VARCHAR2(20 BYTE), "PJN_VALID_FROM" DATE, "PJN_VALID_TO" DATE, "PJN_ACTION" VARCHAR2(20 BYTE), "PJN_EDUCATIONS" "HR"."EDUCATION" , "PJN_TRG_TABLE" VARCHAR2(20 BYTE) ) NESTED TABLE "PJN_EDUCATIONS" STORE AS "PJN_NT_EDUCATIONS" CREATE UNIQUE INDEX "HR"."SYS_C0017903" ON "HR"."PERSONS_JN" ("SYS_NC0000900010$") ALTER TABLE "HR"."PERSONS_JN" ADD UNIQUE ("PJN_EDUCATIONS"); -------------------------------------------------------- -- DDL for Package PCK_PERSON -------------------------------------------------------- CREATE OR REPLACE PACKAGE "HR"."PCK_PERSON" AS /* TODO enter package declarations (types, exceptions, methods etc) here */ procedure next; procedure refresh_cache; procedure get_cache_data ( per_name in varchar2 ); function get_data (v_per_name varchar2) return persons%rowtype result_cache; procedure add_education ( P_PER_NAME IN VARCHAR2 , P_NEW_EDUCATION IN VARCHAR2 ); procedure add_education ( P_PER_ID IN number, P_NEW_EDUCATION IN VARCHAR2 ); procedure print (v_per_name varchar2); procedure write_jn( p_action in varchar2, p_table in varchar2, p_per_rec in persons%rowtype default null, p_per_id in number, p_edu_name in varchar2 default null ); END PCK_PERSON; / -------------------------------------------------------- -- DDL for Package Body PCK_PERSON -------------------------------------------------------- CREATE OR REPLACE PACKAGE BODY "HR"."PCK_PERSON" AS cursor c_list is (select * from persons); type person_table_type is table of persons%rowtype index by varchar2(20); v_per person_table_type; v_last_refresh date := sysdate; procedure get_cache_data ( per_name in varchar2) as begin if v_last_refresh + to_dsinterval('0 00:05:00') < sysdate then refresh_cache; end if; dbms_output.put_line(v_per(per_name).per_birthday); end; function get_data (v_per_name varchar2) return persons%rowtype result_cache relies_on (persons) as v_per_rec persons%rowtype; begin select * into v_per_rec from persons where per_name = v_per_name; return v_per_rec; end; procedure print (v_per_name varchar2) as v_per_rec persons%rowtype; begin v_per_rec := get_data(v_per_name); dbms_output.put_line(v_per_rec.per_birthday); end; procedure next as v_person persons%rowtype; begin fetch c_list into v_person; if c_list%notfound then close c_list; open c_list; fetch c_list into v_person; end if; dbms_output.put_line(v_person.per_name); end; procedure add_education ( P_PER_ID IN number, P_NEW_EDUCATION IN VARCHAR2 ) as v_edu_id number; v_per_id number; e_integrity_violated exception; pragma exception_init (e_integrity_violated, -2291); BEGIN /* begin select per_id into v_per_id from persons where per_id = p_per_id; exception when no_data_found then raise_application_error(-20028, 'no person found'); end; */ select edu_id into v_edu_id from educations where edu_name = p_new_education; insert into person_x_education ( exp_id, exp_per_id, exp_edu_id ) values ( wifi_seq.nextval, p_per_id, v_edu_id ); exception when no_data_found then raise_application_error(-20015, 'no such education'); when e_integrity_violated then raise pck_declarations.e_no_person_found; when dup_val_on_index then raise_application_error(-20031, 'education already assigned'); END add_education; procedure add_education ( P_PER_NAME IN VARCHAR2 , P_NEW_EDUCATION IN VARCHAR2 ) AS v_per_id number; BEGIN select per_id into v_per_id from persons where per_name = p_per_name; add_education(v_per_id, P_NEW_EDUCATION); exception when no_data_found then raise pck_declarations.e_no_person_found; END add_education; procedure refresh_cache as begin v_per.delete; for r in (select * from persons) loop v_per(r.per_name) := r; end loop; v_last_refresh := sysdate; end; procedure write_jn( p_action in varchar2, p_table in varchar2, p_per_rec in persons%rowtype default null, p_per_id in number, p_edu_name in varchar2 default null ) as v_date date := sysdate; v_educations education := education(); v_del_edu education := education(); cursor c_per_edu(cp_per_id in number) is select edu_name from educations join person_x_education on edu_id = exp_edu_id where exp_per_id = cp_per_id; begin if p_table != 'person_x_education' then open c_per_edu(p_per_id); fetch c_per_edu bulk collect into v_educations; close c_per_edu; end if; if p_edu_name is not null then select pjn_educations into v_educations from persons_jn where pjn_per_id = p_per_id and pjn_id = (select max(pjn_id) from persons_jn where pjn_per_id = p_per_id); if p_action = 'I' then v_educations.extend; v_educations(v_educations.last) := p_edu_name; elsif p_action = 'D' then v_del_edu.extend; v_del_edu(1) := p_edu_name; v_educations := v_educations multiset except v_del_edu; end if; end if; if p_action in ('D', 'U') then update persons_jn set pjn_valid_to = v_date where pjn_per_id = p_per_id and pjn_valid_to is null; /*if SQL%rowcount != 1 then raise_application_error(-20666, 'something very wrong'); end if;*/ end if; insert into persons_jn ( PJN_ID, PJN_PER_NAME, PJN_PER_BIRTHDAY, PJN_PER_ID, PJN_PER_GEN_NAME, PJN_VALID_FROM, PJN_VALID_TO, PJN_ACTION, PJN_EDUCATIONS, PJN_TRG_TABLE ) values ( wifi_seq.nextval, p_per_rec.per_name, p_per_rec.per_birthday, p_per_id, (select gen_name from gender where gen_id = p_per_rec.per_gen_id), v_date, null, p_action, v_educations, p_table ); end; begin open c_list; refresh_cache; END PCK_PERSON; /