28
PL\SQL programmu paketes Programmu pakete ir datu bāzes shēmas objekts, kurš grupē loģiski saistītus: 1) PL/SQL tipus; 2) mainīgos; 3) konstantes; 4) apakšprogrammas; 5) kursorus; 6) izņēmumu situācijas (exceptions). Pakete tiek kompilēta un glabāta datu bāzē un daudzi lietojumi var izmantot paketes saturu. Lietotāja shēma Citi shēmas objekti 1

PL/SQL programmu paketes (packages) file · Web view(ne vienmēr ir). Ja paketē tiek definēti kursori un apakšprogrammas, tad tiek veidots arī paketes ķermenis,

  • Upload
    buique

  • View
    215

  • Download
    0

Embed Size (px)

Citation preview

Programmu pakete B

Paketes specifikācija

Paketes ķermenis

Programmu pakete A

Paketes specifikācija

Paketes ķermenis

PL\SQL programmu paketesProgrammu pakete ir datu bāzes shēmas objekts, kurš grupē loģiski saistītus:

1) PL/SQL tipus;

2) mainīgos;

3) konstantes;

4) apakšprogrammas;

5) kursorus;

6) izņēmumu situācijas (exceptions).

Pakete tiek kompilēta un glabāta datu bāzē un daudzi lietojumi var izmantot

paketes saturu.

Lietotāja shēma

Citi shēmas objekti

1

Programmu paketes specifikācija un ķermenisPaketi veido:

1) specifikācija (vienmēr ir), kurā tiek definēti elementi, kuri ir pieejami arī no paketes ārpuses (ārējām programmām);

2) ķermenis (ne vienmēr ir). Ja paketē tiek definēti kursori un apakšprogrammas, tad tiek veidots arī paketes ķermenis, kurā:

- tiek definēts kods apakšprogrammām;- tiek definēti vaicājumi publiskajiemm kursoriem; - tiek definēti elementi, kuri nevar tikt izmantoti ārpus paketes, bet tiek izmantoti tikai paketes ietvaros;- var būt arī inicializācijas daļa, kurā tiek veikta mainīgo inicializācija un citas vienreizējas tikai sākumā veicamas darbības.

Paketes ķermenī var veikt izmaiņas bez specifikācijas maiņas.

In either the package specification or package body, you can map a package subprogram to an external Java or C subprogram by using a call specification, which maps the external subprogram name, parameter types, and return type to their SQL counterparts.

The AUTHID clause of the package specification determines whether the subprograms and cursors in the package run with the privileges of their definer (the default) or invoker, and whether their unqualified references to schema objects are resolved in the schema of the definer or invoker.

2

Paketes publiskie un privātie elementi

Paketes elementi (mainīgie, programmas) var būt:

1) PUBLIC tipa un tiek definēti paketes specifikācijā;

2) PRIVATE tipa un tiek definēti paketes ķermenī. No ārējām programmām uz

tiem nevar veikt atsauces.

Ja PRIVATE tipa funkcija izsauc PRIVATE tipa procedūru, procedūrai jābūt

definētai pirms funkcijas.

Paketes ķermenis

Dati - PRIVATE Dati - PUBLIC

Procedūra - PRIVATE

Datu tips - PRIVATE

Procedūra - PUBLIC

Datu tips - PUBLIC

Funkcija - PUBLICFunkcija - PRIVATE

Ārējā programma

3

Programmu pakešu lietošanas priekšrocības

1. Modularitāte.

2. Vieglāka lietojumu veidošana.

3. Realizēšanas detaļu noslēpšana.

4. Papildus funkcionalitāte (globālie mainīgie).

5. Labāka veiktspēja (s;akumā pakete tiek ielādēta operatīvajā atmiņā).

4

Programmu paketes specifikācijaProgrammas paketes specifikācija definē publiskos (PUBLIC) paketes elementus:1) datu tipus;2) mainīgos;3) konstantes;4) apakšprogrammas;5) kursorus;6) izņēmuma situācijas;7) indeksu tabulu jeb associatīvo masīvu tipus;8) mainīgos, kuru vērtībām jāsaglabājas sesijas laikā starp atsevišķu apakšprogrammu izsaukumiem (globālie mainīgie);9) apakšprogrammas, kuras nolasa un ieraksta PUBLIC tipa mainīgo vērtības ("get" and "set" subprograms), lai paketes lietotājiem neļautu tiešu pieeju PUBLIC tipa mainīgajiem; 5) apakšprogrammas, kuras izsauc viena otru; 6) pārslogotās (overloaded) apakšprogrammas (vienādi nosaukumi, bet dažādi ieejas parametri).

create or replace package PAKETES_NOSAUKUMS isglobālo mainīgo definējumi;konstantes;tipa definējumi rakstiem;tipa definējumi indeksētajām tabulām (index-by table);tipa definējumi masīviem;tipa definējumi iekļautām tabulām (nested tabeles); īpašo situāciju (exception) definējumi;kursoru definējumi;

procedure PROCEDŪRAS_NOSAUKUMS_1 (parametri un tipi);procedure PROCEDŪRAS_NOSAUKUMS_2 (parametri un tipi);function FUNKCIJAS_NOSAUKUMS (parametri un tipi) return tips;end PAKETES_NOSAUKUMS;

Raksta tipa, konstantes, mainīgā un īpašās sistuācijas definēšana paketes specifikācijā.

create or replace package PAKETE_1 astype TPS_1 is record(MINUTES smallint, STUNDAS smallint); konstante_1 CONSTANT real := 10.00;skaits int;NEPIETIEKAMS_DAUDZUMS exception;

end PAKETE_1;

5

Programmu paketes specifikācijas izmantošanas piemērs

create or replace package PAKETE_2 is type TIPS_2 is table of integer index by varchar(15);end PAKETE_2;

create or replace procedure IZVADE(aa PAKETE_2.TIPS_2) is i varchar2(15);begin i := aa.FIRST; while i is not NULL loop DBMS_OUTPUT.PUT_LINE (aa(i) || ' ' || i); i := aa.NEXT(i); end loop;end;

declare aa PAKETE_2.TIPS_2;begin aa('nulle') := 0; aa('viens') := 1; aa('divi') := 2; IZVADE(aa);end;

Rezultāts:2 divi0 nulle1 viens

6

Programmu paketes ķermenis

Paketes ķermenis (body) tiek definēts sekojoši:

create or replace body PAKETES_NOSAUKUMS as

mainīgo un tipu definēšana; -- lokālie mainīgie

SELECT vaicājuma definēšana kursoriem;

PROCEDURE … ; -- procedūras algoritma definējums

PROCEDURE … ; -- procedūras algoritma definējums

FUNCTION . . . ; -- funkcijas algoritma definējums

end PAKETES_NOSAUKUMS;

7

Programmu paketes struktūras piemērs

Paketes specifikācijas definējums:

create or replace package PAKETE_1 as

PUBLIC tipa mainīgie un tipi (globālie mainīgie un tipi) procedure PROCEDŪRA_1 (parametrs_11 IN NUMBER, parametrs_12 IN NUMBER); procedure PROCEDŪRA_2 (parametrs_21 IN NUMBER, parametrs_22 IN NUMBER);

end PAKETE_1;

Paketes ķermeņa definējums:

create or replace package body PAKETE_1 as

PRIVATE tipa manīgie un tipi (lokālie mainīgie un tipi)

procedure PROCEDŪRA_1 (parametrs_11 IN NUMBER, parametrs_12 IN NUMBER) is begin . . . end PROCEDŪRA_1;

procedure PROCEDŪRA_2 (parametrs_21 IN NUMBER, parametrs_22 IN NUMBER) is begin . . . end PROCEDŪRA_2;

Paketes inicializācijas daļabegin . . .

end PAKETE_1;

8

PL/SQL programmu paketes ar funkciju definēšana un izmantošana

create or replace package PROGR_PAKETE_A astype KURS_MAIN_TIPS is REF CURSOR;function FIRMU_DATI return KURS_MAIN_TIPS;end PROGR_PAKETE_A;

create or replace package body PROGR_PAKETE_A asfunction FIRMU_DATI return KURS_MAIN_TIPS is

kurs_main_a KURS_MAIN_TIPS;raksts FIRMAS%rowtype;

begin open kurs_main_a for select * from FIRMAS;

fetch kurs_main_a into raksts;return kurs_main_a;

end;end PROGR_PAKETE_A;

declaretype KURS_MAIN_TIPS is REF CURSOR;kurs_main_a KURS_MAIN_TIPS;type TAB_AR_KOL_TIPS is table of FIRMAS%rowtype;tab TAB_AR_KOL_TIPS := TAB_AR_KOL_TIPS();

beginkurs_main_a := PROGR_PAKETE_A.FIRMU_DATI();tab.extend;fetch kurs_main_a into tab(1);tab.extend;fetch kurs_main_a into tab(2);close kurs_main_a;DBMS_OUTPUT.PUT_LINE(tab(1).F_NUM || ' ' || tab(1).F_NOS || ' ' || tab(1).DIBIN_DAT);DBMS_OUTPUT.PUT_LINE(tab(2).F_NUM || ' ' || tab(2).F_NOS || ' ' || tab(2).DIBIN_DAT);

end;

2 CCC 23-JAN-063 AAA 06-DEC-07

FIRMASF_NUM F_NOS DIBIN_DAT1 BBB 2005-FEB-152 CCC 2006-JAN-233 AAA 2007-DEC-6

9

Ārēji definēto un iekšēji definēto datu izmantošana programmu paketēdeclare

X PAKETE_1.TABULAS_TIPS_1 := PAKETE_1.TABULAS_TIPS_1(1, 1);w number(16,6) := 0;

beginX(1) := 3;X(2) := 3;PAKETE_1.PROCEDURA_1(X, w);

end;

create or replace package PAKETE_1 astype TABULAS_TIPS_1 is table of NUMBER(16,6);X1 TABULAS_TIPS_1 := TABULAS_TIPS_1(2, 2);w number(16,6);procedure PROCEDURA_1(X IN TABULAS_TIPS_1, w OUT number);end PAKETE_1;

create or replace package body PAKETE_1 asprocedure PROCEDURA_1 (X IN TABULAS_TIPS_1, w OUT number) isbegin-- Aprēķins ar ārējiem (parametru) datiemw := 3* X(1)*X(1) + 7*X(2)*X(2);DBMS_OUTPUT.PUT_LINE(' X(1) = ' || X(1) || ' X(2) = ' || X(2) || ' w = ' || w);-- Aprēķins ar paketē definētiem datiemw := 3* X1(1)*X1(1) + 7*X1(2)*X1(2);DBMS_OUTPUT.PUT_LINE(' X1(1) = ' || X1(1) || ' X1(2) = ' || X1(2) || ' w = ' || w);end PROCEDURA_1;end PAKETE_1;

X(1) = 3 X(2) = 3 w = 90X1(1) = 2 X1(2) = 2 w = 40

10

Programmu paketes objektu izsaukšana Lai atsauktos uz programmu paketes objektu, jānorāda pakete un attiecīgā objekta nosaukums ar parametriem (ja tādi ir):

PAKETES_NOSAUKUMS.PROCEDŪRAS_NOSAUKUMS(parametru_saraksts);

Var eksistēt vairākas procedūras ar vienu nosaukumu un dažādiem ieejas parametriem (overloaded). Tas ir ērti darbībai ar funkciju, var norādīt konkrētajā situācijā vēlamos ieejas parametrus.

11

Programmu paketē definēto datu izmaiņadeclare

w number(16,6) := 0;begin

PAKETE_1.X(1) := 4;PAKETE_1.X(2) := 4;PAKETE_1.PROCEDURA_1(PAKETE_1.X, w);

end;

create or replace package PAKETE_1 astype TABULAS_TIPS_1 is table of NUMBER(16,6);X TABULAS_TIPS_1 := TABULAS_TIPS_1(2, 2);w number(16,6);procedure PROCEDURA_1(X IN TABULAS_TIPS_1, w OUT number);end PAKETE_1;

create or replace package body PAKETE_1 asprocedure PROCEDURA_1 (X IN TABULAS_TIPS_1, w OUT number) isbeginw := 3* X(1)*X(1) + 7*X(2)*X(2);DBMS_OUTPUT.PUT_LINE(' X(1) = ' || X(1) || ' X(2) = ' || X(2) || ' w = ' || w);end PROCEDURA_1;end PAKETE_1;

X(1) = 4 X(2) = 4 w = 160

12

Programmu paketes aktualizācija un inicializācija (initialization)

Pirmo reizi izsaucot paketi seansā tā tiek sagatavota jeb aktualizēta jeb konkretizēta (instantiated) lietošanai seansā. Pakete tiek nolasīta no diska atmiņas un tiek palaists tās p-kods. Visiem mainīgiem tiek izdalīta atmiņa. Lai tas automātiski notiktu, paketes ķermenim pievieno inicializācijas (initialization) daļu, novietojot to aiz visu objektu definējumiem. Šī daļa tiek veidota kā anonīmais PL/SQL bloks. Tā izpildās sesijā tikai vienreiz un:

1) automātiski piešķir norādītajiem mainīgiem un konstantēm to sākotnējās vērtības;

2) izpilda inicializājas daļas programmas kodu.

If a PL/SQL package declares at least one variable, constant, or cursor, then the package is stateful; otherwise, it is stateless.Each session that references a package item has its own instantiation of that package. If the package is stateful, the instantiation includes its state.

13

Programmu paketes inicializācijas daļas izmantošana declare

m1 number(16,6);m2 number(16,6);

beginm1 := PAKETE_1.X(1);m2 := PAKETE_1.X(2);DBMS_OUTPUT.PUT_LINE(' X(1) = ' || m1 || ' X(2) = ' || m2);

end;

create or replace package PAKETE_1 astype TABULAS_TIPS_1 is table of NUMBER(16,6);X TABULAS_TIPS_1 := TABULAS_TIPS_1(0, 0);w number(16,6);procedure PROCEDURA_1(X IN TABULAS_TIPS_1, w OUT number);end PAKETE_1;

create or replace package body PAKETE_1 asprocedure PROCEDURA_1 (X IN TABULAS_TIPS_1, w OUT number) isbeginw := 3* X(1)*X(1) + 7*X(2)*X(2);DBMS_OUTPUT.PUT_LINE(' X(1) = ' || X(1) || ' X(2) = ' || X(2) || ' w = ' || w);end PROCEDURA_1;-- Programmu paketes inicializācijabeginX(1) := 5;X(2) := 5;end PAKETE_1;

X(1) = 5 X(2) = 5

14

Lokālo mainīgo definēšana programmu paketes ķermenī

declarem1 number(16,6);m2 number(16,6);

beginm1 := PAKETE_1.X2(1); Error!m2 := PAKETE_1.X2(2); Error!

end;

create or replace package PAKETE_1 astype TABULAS_TIPS_1 is table of NUMBER(16,6);X TABULAS_TIPS_1 := TABULAS_TIPS_1(0, 0);w number(16,6);procedure PROCEDURA_1(X IN TABULAS_TIPS_1, w OUT number);procedure PROCEDURA_2;end PAKETE_1;

create or replace package body PAKETE_1 astype TABULAS_TIPS_2 is table of NUMBER(16,6);X2 TABULAS_TIPS_2 := TABULAS_TIPS_2(3, 3);w2 number(16,6);procedure PROCEDURA_1 (X IN TABULAS_TIPS_1, w OUT number) isbeginw := 3* X(1)*X(1) + 7*X(2)*X(2);DBMS_OUTPUT.PUT_LINE(' X(1) = ' || X(1) || ' X(2) = ' || X(2) || ' w = ' || w);end PROCEDURA_1;

procedure PROCEDURA_2 isbeginw2 := 3* X2(1)*X2(1) + 7*X2(2)*X2(2);DBMS_OUTPUT.PUT_LINE(' X2(1) = ' || X2(1) || ' X2(2) = ' || X2(2) || ' w2 = ' || w2);end PROCEDURA_2;end PAKETE_1;

beginPAKETE_1.PROCEDURA_2;

end;

X2(1) = 3 X2(2) = 3 w2 = 90

15

Programmu paketes piemērs (Oracle dokumentācija)Example creates a table, log, and a package, emp_admin, and then invokes package subprograms from an anonymous block. The package has both specification and body.The specification declares a public type, cursor, and exception, and three public subprograms. One public subprogram is overloaded (for information about overloaded subprograms. The body declares a private variable, defines the public cursor and subprograms that the specification declares, declares and defines a private function, and has an initialization part.The initialization part (which runs only the first time the anonymous block references the package) inserts one row into the table log and initializes the private variable number_hired to zero. Every time the package procedure hire_employee is invoked, it updates the private variable number_hired.

create table EMPLOYEES(LAST_NAME varchar2(20),FIRST_NAME varchar2(20),EMAIL varchar2(30),PHONE_NUMBER varchar2(11), JOB_ID varchar2(20), SALARY number(8,2), COMMISSION_PCT number, MANAGER_ID number, DEPARTMENT_ID number);

create table ZURNALS( DATE_OF)ACTION date, USER_ID varchar2(20), PACKAGE_NAME varchar2(30));

Programmu paketes specifikācija

create or replace package EMP_ADMIN as-- Publisku raksta tipa, kursora un izņēmuma situācijas definēšana.type EmpRecTyp is record(emp_id NUMBER, sal NUMBER);cursor desc_salary return EmpRecTyp;INVALID_SALARY exception;-- Publisku apakšprogrammu definēšana.function Hire_Employee (LAST_NAME varchar2, FIRST_NAME varchar2, EMAIL varchar2, PHONE_NUMBER varchar2, JOB_ID varchar2, SALARY number, COMMISSION_PCT number, MANAGER_ID number, DEPARTMENT_ID number) return number;-- Pārslogotās Overload preceding public subprogram: PROCEDURE fire_employee (emp_id NUMBER); PROCEDURE fire_employee (emp_email VARCHAR2);

PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER); FUNCTION nth_highest_salary (n NUMBER) RETURN EmpRecTyp;END emp_admin;

16

Programmu paketes ķermenis

CREATE OR REPLACE PACKAGE BODY emp_admin AS number_hired NUMBER; -- private variable, visible only in this package

-- Kursora definēšana cursor Desc_Salary return EmpRecTyp is select EMPLOYEE_ID, SALARY from EMPLOYEES order by SALARY DESC;

-- Define subprograms declared in package specification:

FUNCTION hire_employee ( last_name VARCHAR2, first_name VARCHAR2, email VARCHAR2, phone_number VARCHAR2, job_id VARCHAR2, salary NUMBER, commission_pct NUMBER, manager_id NUMBER, department_id NUMBER) RETURN NUMBER IS new_emp_id NUMBER; BEGIN new_emp_id := employees_seq.NEXTVAL; INSERT INTO employees(employee_id, last_name, first_name, email, phone_number, hire_date, job_id, salary, commission_pct, manager_id, department_id) VALUES ( new_emp_id, hire_employee.last_name, hire_employee.first_name, hire_employee.email, hire_employee.phone_number, SYSDATE, hire_employee.job_id, hire_employee.salary, hire_employee.commission_pct, hire_employee.manager_id, hire_employee.department_id); number_hired := number_hired + 1; DBMS_OUTPUT.PUT_LINE('The number of employees hired is ' || TO_CHAR(number_hired)); RETURN new_emp_id; END hire_employee;

procedure Fire_Employee (emp_id NUMBER) is begin DELETE FROM employees WHERE employee_id = emp_id; end Fire_Employee;

PROCEDURE fire_employee (emp_email VARCHAR2) IS BEGIN

17

DELETE FROM employees WHERE email = emp_email; END fire_employee;

-- Define private function, available only inside package:

FUNCTION sal_ok (jobid VARCHAR2, sal NUMBER ) RETURN BOOLEAN IS min_sal NUMBER; max_sal NUMBER; BEGIN SELECT MIN(salary), MAX(salary) INTO min_sal, max_sal FROM employees WHERE job_id = jobid; RETURN (sal >= min_sal) AND (sal <= max_sal); END sal_ok;

PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) IS sal NUMBER(8,2); jobid VARCHAR2(10); BEGIN SELECT job_id, salary INTO jobid, sal FROM employees WHERE employee_id = emp_id;

IF sal_ok(jobid, sal + amount) THEN -- Invoke private function UPDATE employees SET salary = salary + amount WHERE employee_id = emp_id; ELSE RAISE invalid_salary; END IF; EXCEPTION WHEN invalid_salary THEN DBMS_OUTPUT.PUT_LINE ('The salary is out of the specified range.'); END raise_salary;

FUNCTION nth_highest_salary (n NUMBER) RETURN EmpRecTyp IS emp_rec EmpRecTyp; BEGIN OPEN desc_salary; FOR i IN 1..n LOOP FETCH desc_salary INTO emp_rec; END LOOP; CLOSE desc_salary; RETURN emp_rec; END nth_highest_salary;-- Programmu paketes ķermeņa daļas inicializēšanabegin insert into ZURNALS (date_of_action, user_id, package_name) VALUES (SYSDATE, USER, 'EMP_ADMIN'); number_hired := 0;end Emp_Admin;

18

Paketes apakšprogrammu izsaukšana.

DECLARE new_emp_id NUMBER(6);BEGIN new_emp_id := emp_admin.hire_employee ('Belden', 'Enrique', 'EBELDEN', '555.111.2222', 'ST_CLERK', 2500, .1, 101, 110); DBMS_OUTPUT.PUT_LINE ('The employee id is ' || TO_CHAR(new_emp_id)); emp_admin.raise_salary (new_emp_id, 100); DBMS_OUTPUT.PUT_LINE ('The 10th highest salary is '|| TO_CHAR (emp_admin.nth_highest_salary(10).sal) || ', belonging to employee: ' || TO_CHAR (emp_admin.nth_highest_salary(10).emp_id)); emp_admin.fire_employee(new_emp_id); -- You can also delete the newly added employee as follows: -- emp_admin.fire_employee('EBELDEN');END;

Result is similar to:

The number of employees hired is 1The employee id is 212The 10th highest salary is 12075, belonging to employee: 168There are now 107 employees.

19