Aplicaţi Profesionale în Bazele de Date Orientate pe Obiecte
- Anul 1 Master Laborator 3 (Oracle 10g Forms Developer)
1. În forma F_EMP, scrieţi un trigger care populează câmpurile min_salary,
max_salary ale blocului BL_JOBS (care, dacă nu există, va fi creat) cu maximul şi minimul salariilor pentru job-ul respectiv din EMPLOYEES_PNU. Obs: POST-QUERY la nivelul blocului BL_JOBS SELECT MIN(salary), MAX(salary) INTO :bl_jobs.min_salary, :bl_jobs.max_salary FROM employees_pnu WHERE job_id = : bl_jobs.job_id GROUP BY job_id; Asiguraţi-vă că trigger-ul a funcţionat, observând valoarea maximă şi minimă a salariului pentru job-ul FI_MGR în câmpurile blocului BL_JOBS, iar apoi în tabel. Pentru aceasta, în SQL*Plus se dă comanda: select * from jobs_pnu where job_id ='FI_MGR'; 2. Asiguraţi-vă că Exit_Button nu are efect în modul Enter Query. Obs: În proprietăţile trigger-ului WHEN-BUTTON-PRESSED asupra butonului, setăm Fire in Enter- Query Mode la valoarea No. 3. Ajustaţi interfaţa de cereri implicită, astfel: deschideţi forma F_EMP; adăugaţi un check box numit Case_Sensitive în blocul CONTROL din formă pentru ca utilizatorul să poată specifica dacă un query asupra numelui angajaţilor să fie sau nu case-sensitive. (Se va crea trigger-ul When_Checkbox_Changed asupra lui Control.Case_Sensitive). Obiectul creat se va afla pe Toolbar. Eticheta sa va fi “Cautare case-sensitive dupa nume?”. Valoarea Checked va fi considerată 1, valoarea Unchecked 0. Se presupune că valoarea iniţială este 1 (bifat). Proprietatea Mouse Navigate va avea valoarea No. Obs: WHEN-CHECKBOX-CHANGED la nivelul lui Case_Sensitive IF :control.case_sensitive = 1 THEN SET_ITEM_PROPERTY( 'bl_emp.last_name' , case_insensitive_query , property_false ); ELSE SET_ITEM_PROPERTY( 'bl_emp.last_name' , case_insensitive_query , property_true ); END IF; 4. Adăugaţi un check box CONTROL.Exact_Match pentru ca utilizatorul să poată specifica dacă o condiţie dintr-un query asupra numelui unui angajat trebuie sau nu să se potriveasca exact cu valoarea din tabel (dacă este acceptata o potrivire inexactă, valoarea căutată poate fi parte din valoarea din tabel). (Se va crea trigger-ul Pre-Query asupra blocului BL_EMP ). Setaţi propretăţile noului item ca la exerciţiul precedent. Obs: PRE-QUERY la nivelul blocului BL_EMP IF :control.exact_match = 0 THEN :bl_emp.last_name := '%' || :bl_emp.last_name || '%'; END IF; 5. În forma F_DEP, determinaţi ca ID_LOV să se afişeze ori de câte ori utilizatorul introduce o valoare location_id necorespunzătoare. Obs: Proprietatea Validate from list a item-ului location_id va avea valoarea Yes. 6. În forma F_EMP, scrieţi un trigger de validare pentru a verifica dacă hire_date nu este ulterioară datei curente. (Se va crea triggerul When-Validate-Item asupra item-lui hire_date). Obs: WHEN_VALIDATE_ITEM la nivelul item-ului hire_date IF :bl_emp.hire_date > sysdate THEN MESSAGE ( ' Data angajarii invalida! ' ); RAISE form_trigger_failure; END IF; 7. În forma F_EMP, scrieţi un trigger de validare pentru a verifica dacă pentru angajaţii având job-ul SA_REP comisionul nu este null. (Se va crea triggerul When-Validate-Record asupra blocului bl_emp). Când este necesar un trigger When-Validate-Item şi când este adecvat unul When-Validate-Record? IF UPPER(:bl_emp.job_id) ='SA_REP' AND :bl_emp.commission_pct IS NULL THEN MESSAGE ( ' Reprezentantii de vanzari trebuie sa aiba comision! ' ); RAISE form_trigger_failure; END IF; 8. În forma F_EMP, creaţi un trigger pentru a scrie valorile corecte pentru last_name, job_id, manager_id oricând apare o validare asupra lui employee_id. Trigger-ul va eşua dacă angajatul nu este găsit. (When-Validate-Item asupra lui BL_EMP.employee_id). Obs: WHEN_VALIDATE_ITEM la nivelul lui "employee_id" SELECT last_name, job_id, manager_id INTO :bl_emp.last_name, :bl_emp.job_id, :bl_emp.manager_id FROM employees_pnu WHERE employee_id = :bl_emp.employee_id; EXCEPTION WHEN NO_DATA_FOUND THEN MESSAGE ( ' Cod invalid ' ); RAISE form_trigger_failure; 9. Scrieţi un trigger When-New-Form-Instance asupra formei F_EMP pentru a executa un query nerestricţionat la pornirea formei. Obs: WHEN_NEW_FORM_INSTANCE la nivelul formei execute_query; 10. În blocul BL_EMP setaţi proprietatea enabled = No pentru item-ul employee_id. 11. a) Creaţi o secvenţă pentru a genera valori pentru employee_id. b) Modificaţi trigger-ul de la exerciţiul 8 astfel încât să acţioneze doar dacă item- ul employee_id este enabled. c) În forma F_EMP, scrieţi un trigger tranzacţional asupra blocului BL_EMP care populează câmpul employee_id cu următoarea valoare a secvenţei. (Pre- Insert asupra blocului BL_EMP) a) În SQL*Plus, se dă comanda: CREATE SEQUENCE seq_emp_pnu START WITH 900 INCREMENT BY 1 MAXVALUE 1000 NOCYCLE;
b) if get_item_property('bl_emp.employee_id', enabled) = 'true' then ...
c) PRE_INSERT la nivelul blocului bl_emp
SELECT seq_emp_pnu.nextval INTO :bl_emp.employee_id FROM dual; EXCEPTION WHEN OTHERS THEN MESSAGE ( ' Exceptie ' ); RAISE form_trigger_failure; 12. Creaţi un trigger similar asupra blocului BL_DEP din forma F_DEP care atribuie lui department_id o valoare când este salvată o înregistrare. (se consideră codul noii înregistrări = codul maxim al înregistrărilor existente + 1). Setaţi proprietăţile Required şi Enabled =No pentru BL_DEP.department_id. 13. În forma F_EMP, creaţi trei variabile globale numite GLOBAL.INSERT, GLOBAL.UPDATE, GLOBAL.DELETE, care vor indica respectiv numărul de inserări, actalizări şi ştergeri. Creaţi trigger-ii Post-Insert, Post-Update şi Post- Delete pentru a iniţializa şi incrementa valoarea fiecărei variabile globale. Obs: POST_INSERT la nivel de formă default_value( '0', 'global.insert' ); --se declara si se -- initializeaza variabila globala insert :global.insert := :global.insert + 1; --procedati asemanator pentru celelalte doua variabile globale, -- in trigger-ii corespunzatori 14. Creaţi o procedură numită HANDLE_MESSAGE, cu două argumente. Primul argument va fi numărul mesajului, iar al doilea va fi un indicator de eroare boolean. Această procedură foloseşte cele trei variabile globale pentru a afişa un mesaj de salvare particularizat, iar apoi şterge variabilele globale. Apelaţi procedura când apare o eroare; parametrii vor fi codul erorii şi TRUE. Apelaţi procedura când apare un mesaj; parametrii vor fi codul mesajului şi FALSE. procedure handle_message ( nr_mesaj number, ind_eroare boolean ) is begin if nr_mesaj in (40400, 40406, 40407) then default_value ( ' 0 ', ' global.insert ' ); default_value ( ' 0 ', ' global.update ' ); default_value ( ' 0 ', ' global.delete ' ); message ( ' S-au salvat: ' || :global.insert || ' inreg. introduse ' || :global.update || ' inreg. actualizate ' || :global.delete || ' inreg. sterse '); erase ( ' global.insert ' ); erase ( ' global.update ' ); erase ( ' global.delete ' ); elsif ind_eroare = true then message ( ' A aparut eroarea ' || error_text ); else message ( message_text ); end if; end;
Obs: ON_ERROR la nivel de formă
handle_message ( error_code, true ); ON_MESSAGE la nivel de formă handle_message ( message_code, false );