24
Facultatea de Cibernetică, Statistică şi Informatică Economică SGBD Oracle – seminarul 2 VARIABILE 1. Declarare şi iniţializare declararea variabilelor se realizează în zona declarativă (delimitată prin DECLARE) a blocului (sau sub-blocului); iniţializarea se poate face la declarare sau în zona de execuţie (între BEGIN şi END); variabilele vor fi vizibile în restul blocului, respectiv şi în blocurile incluse în el, mai puţin în sub-blocurile în care numele lor este redefinit (ca în majoritatea limbajelor de programare structurate, semnificaţia unui nume definit de utilizator într-un bloc/sub-bloc este dată de cea mai apropiată declaraţie anterioară locului folosirii); toate variabilele PL/SQL au un tip de dată, restricţii şi un şir valid de valori; declararea şi iniţializarea se realizează astfel: nume_variabila [CONSTANT] TIP_DATA [NOT NULL] [:= | DEFAULT expresie] constantele trebuie obligatoriu iniţializate, iar ulterior nu îşi vor putea schimba valoarea; variabilele NOT NULL trebuie obligatoriu iniţializate, iar ulterior nu vor putea primi valoarea NULL; se foloseşte următoarea convenţie de notare: c_nume Constanta v_nume Variabila g_nume VarGlobala (variabilă globală definită în zona de specificaţii a pachetului de programe şi valabilă pentru toate subprogramele pachetului). 2. Tipuri de variabile Variabile PL/SQL Scalare Compozite 1

Seminar 2 SGBD

Embed Size (px)

DESCRIPTION

Seminar 2 SGBD (cu explicatii)

Citation preview

Seminar 2

Facultatea de Cibernetic, Statistic i Informatic Economic

SGBD Oracle seminarul 2

VARIABILE1. Declarare i iniializare declararea variabilelor se realizeaz n zona declarativ (delimitat prin DECLARE) a blocului (sau sub-blocului); iniializarea se poate face la declarare sau n zona de execuie (ntre BEGIN i END); variabilele vor fi vizibile n restul blocului, respectiv i n blocurile incluse n el, mai puin n sub-blocurile n care numele lor este redefinit (ca n majoritatea limbajelor de programare structurate, semnificaia unui nume definit de utilizator ntr-un bloc/sub-bloc este dat de cea mai apropiat declaraie anterioar locului folosirii); toate variabilele PL/SQL au un tip de dat, restricii i un ir valid de valori; declararea i iniializarea se realizeaz astfel:

nume_variabila [CONSTANT] TIP_DATA [NOT NULL] [:= | DEFAULT expresie]

constantele trebuie obligatoriu iniializate, iar ulterior nu i vor putea schimba valoarea; variabilele NOT NULL trebuie obligatoriu iniializate, iar ulterior nu vor putea primi valoarea NULL; se folosete urmtoarea convenie de notare:

c_nume Constanta

v_nume Variabila

g_nume VarGlobala (variabil global definit n zona de specificaii a pachetului de programe i valabil pentru toate subprogramele pachetului).2. Tipuri de variabileVariabile PL/SQL

Scalare Compozite

Referin LOB (Large Objects): NCLOB, CLOB, BLOB, BFILE ObiectVariabile non-PL/SQL: variabile de mediu (BIND VARIABLES)

a) Variabile Scalare:Tipurile scalare conin valori simple (o variabila scalar poate conine la un moment dat o singur valoare simpl) i corespund n principal tipurilor pe care le pot avea coloanele tabelelor.

char (lung_max) - lungime fix de max 32.767 bytes

varchar2 (lung_max) lungime variabil de max 32.767 bytes

long [ir de caractere de lungime variabil 2GB] number (precizie,scal)

boolean (true, false, null)

date

binary_integer i pls_integer (numere ntregi ntre -2147483647 i 2147483647)

binary_float i binary_double (pentru numere reale n varianta Oracle 10g)

timestamp (pentru fraciuni de secund)Exemple:

v_functie varchar2(9);

v_numar binary_integer:=0;

v_totalsal number(9,2):=0;

v_datainceput date:=sysdate+7;

c_taxa constant number(3,2):=8.25;

v_valid boolean not null:=true;

Afiarea variabilelor PL/SQL se realizeaz prin intermediul funciei PUT_LINE din pachetului DBMS_OUTPUT. Se poate utiliza operatorul de concatenare ( || ) pentru a afia mai multe mesaje sau variabile pe aceeai linie.DBMS_OUTPUT.PUT_LINE ('VALOAREA VARIABILEI ESTE:' ||variabila);

Popularea variabilelor cu valori din tabelele bazei de date

Se utilizeaz comanda SELECT cu clauza INTO pentru popularea variabilelor PL/SQL cu valori ale atributelor din tabele;

Sa se afiseze salariul angajatului cu id-ul 100.

set serveroutput on

DECLARE

v_salariu number(5);

BEGIN

SELECT salariul INTO v_salariu FROM angajati WHERE id_angajat=100;DBMS_OUTPUT.PUT_LINE('Salariul angajatului cu id-ul 100 este='||v_salariu);END;

/

Exemplu:

--se afiseaza numele angajatului cu codul 100

SET SERVEROUTPUT ONDECLARE v_nume VARCHAR2(20);BEGIN SELECT nume INTO v_nume FROM angajati WHERE id_angajat = 100; DBMS_OUTPUT.PUT_LINE('NUMELE ANGAJATULUI ESTE:' || v_nume);END;/

cererile SELECT din cadrul blocurilor PL/SQL trebuie s furnizeze o singur linie rezultat (n caz contrar se semnaleaz eroare).Exemplu:

Sa se afiseze numele angajatului care are functia 'IT_PROG'.

set serveroutput on

DECLARE

v_angajat varchar2(25);

BEGIN

--sunt mai multi angajati cu functia de IT_PROG

SELECT nume INTO v_angajat FROM angajati WHERE id_functie=upper('IT_PROG'); --upper inseamna ca regaseste acele cuvinte scrise cu litere de tipar, pt ca SQL nu face diferenta intre ele

DBMS_OUTPUT.PUT_LINE('Numele angajatului care are functia IT_PROG este '||v_angajat);

END;

/

Ne da eroare pt ca sunt mai multe tupluri care au aceeeasi functie.

3. Atributul %TYPE

Atribuie unei variabile tipul altei variabile sau tipul de date specific unei coloane din tabel.

Declararea unei variabile cu %TYPE:variabilatabel.nume_coloan%TYPE;

sau

variabila1tip_dat;

variabila2variabila1%TYPE;

Exemplu:

--afiseaza numele si prenumele angajatului cu codul 100.

DECLARE

v_nume angajati.nume%TYPE;

v_prenume angajati.prenume%TYPE;

BEGIN

SELECT nume, prenume

INTO v_nume, v_prenume

FROM angajati

WHERE id_angajat = 100;

DBMS_OUTPUT.PUT_LINE('NUMELE ANGAJATULUI ESTE:' || v_nume||' '||v_prenume);

END;

/Observaie: Restricia NOT NULL a unei coloane nu se aplic i variabilei declarate prin folosirea atributului %TYPE.

4. Variabile de mediu sau variabile de legtur ale aplicaiilor gazd (BIND VARIABLES) sunt variabile de legtur cu aplicaia n care ruleaz motorul PL/SQL;

trebuie declarate n aplicaie (n mediul gazd) i pot fi accesate i modificate n cadrul blocurilor PL/SQL; dup terminarea execuiei blocului PL/SQL, variabila rmne n mediul gazd cu valoarea primit n urma rulrii blocului (i poate fi pasat altui bloc, realiznd astfel transmiterea de valori ntre blocurile PL/SQL); nu pot fi utilizate n cadrul procedurilor, funciilor sau pachetelor;

se declar n afara blocului PL/SQL cu ajutorul cuvntului cheie VARIABLE:VARIABLE g_numevariabil TIP

pentru declararea unei variabile host de tip NUMBER nu se specific precizia i scala;

pentru utilizarea lor n cadrul unui bloc PL/SQL sau ntr-o fraz SQL din afara blocului se prefixeaz cu :

:host_variabila:=v_variabila;

se afieaz n afara blocului cu ajutorul comenzii PRINT (la afiare variabila nu se va prefixa cu :)

PRINT g_numevariabil

Exemple:

--se afieaz mesajul: Bloc PL/SQLVARIABLE g_mesaj varchar2(30)

BEGIN

:g_mesaj:='Bloc PL/SQL';

END;

/

PRINT g_mesaj

SET SERVEROUTPUT ONVARIABLE g_comenzi varchar2(30)

BEGINselect count(*) into :g_comenzifrom comenziwhere modalitate = 'online';END;/PRINT g_comenzi

Exemplu:

Sa se afiseze mesajul "Ana are mere"

--se foloseste o variabila de mediu(variabila de legatura)

--o declaram in afara blocului PL/SQL

set serveroutput on

VARIABLE g_mesaj varchar2(30)

BEGIN

--pentru a utiliza aceasta variabila de mediu declarata in afara blocului trebuie sa prefixam cu ":"

:g_mesaj:='Ana are mere';

END;

/

--pentru a afisa aceasta variabila de mediu folosim comanda PRINT in afara bloculuiPRINT g_mesaj

Sa se afiseze mesajul "Mi-e foarte somn"

set serveroutput on

--declaram variabila in care stocam mesajul, este mereu in afara blocului

VARIABLE g_mesaj varchar2(30)

BEGIN

--in interiorul blocului trebuie sa prefixam cu : numele variabilei pentru a putea fi accesata:g_mesaj:='Mi-e foarte somn';

END;

/Observaie: Se poate auto-afia variabila prin setarea AUTOPRINT ONExemplu:

--se selecteaza produsele si pretul acestora pentru acele produse care au pretul < pretul mediu al produsului cu codul 3133 fara a utiliza un select imbricat

SET SERVEROUTPUT ON

SET AUTOPRINT ON

VARIABLE g_pret number

BEGIN

select avg(pret) into :g_pret

from rand_comenzi

where id_produs = 3133;

END;

/

select * from rand_comenzi where pret< :g_pret;5. Variabile de substituie de regul, variabilele de substituie sunt folosite pentru a transmite valori dinspre mediul SQL*Plus spre comenzile SQL sau blocurile PL/SQL, n timp ce variabilele de legtur (bind variables) sunt folosite pentru a transmite valori n sens invers sau pentru a transfera valori ntre blocuri PL/SQL lansate succesiv (primul bloc seteaz variabila, urmtorul o consult); prin variabile de substituie se pot transmite valori comenzilor SQL sau blocurilor PL/SQL lansate (folosind "&" sau "&&"); se pot invoca din comenzile SQL sau din blocurile PL/SQL prin "&nume_variabila" sau "&&nume_variabila"; sunt locale sesiunii SQL n care au fost declarate; n mediul SQL variabilele de substituie pot fi uor citite prin introducerea de valori de la tastatur (utiliznd ACCEPT), se pot defini (cu DEFINE) sau afia pe ecran (cu PROMPT); Exemple:--se afiseaza numarul de comenzi ale angajatului al carui cod este introdus de utilizator prin intermediul variabilei de substitutie &id_angajatDECLAREv_nr_comenzi number(2);BEGINselect count(nr_comanda) into v_nr_comenzi from comenziwhere id_angajat=&id_angajat;dbms_output.put_line('Angajatul are: '|| v_nr_comenzi||' comenzi');END;/Observaie: ntr-un bloc PL/SQL se pot utiliza toate tipurile de variabile, respectnd ns caracteristicile i regulile de utilizare ale acestora. n exemplul urmtor se utilizaz att variabila de substituie s_nume definit i iniializat prin comanda DEFINE, ct i variabila de legtur g_salariul, dar i variabila local v_prenume de acelai tip cu coloana nume din tabela Angajati. Variabila de substituie definit cu DEFINE va fi implicit de tipul CHAR:

-- se afiseaza salariul si prenumele angajatului cu numele AbelSET SERVEROUTPUT ON

VARIABLE g_salariul number

DEFINE s_nume=Abel

DECLARE

v_prenume angajati.nume%type;

BEGIN

select prenume,salariul into v_prenume, :g_salariul

from angajati where nume='&s_nume';DBMS_OUTPUT.PUT_LINE ('Prenumele angajatului este: '||v_prenume);

END;

/

print g_salariul Sa se afiseze denumirea produsului din categoria software1 care are id-ul dat de la tastatura.

set serveroutput on

VARIABLE g_denumire_produs varchar2(25)

DEFINE v_categorie_produs=software1

BEGIN--pt a indroduce o valoare de la tastatura, se foloseste caracterul '&' plasat in fata numelui

SELECT denumire_produs INTO :g_denumire_produs FROM produse WHERE categorie='&v_categorie_produs' AND id_produs=&id_produs;

END;

/

PRINT g_denumire_produsEXERCIII PROPUSESpecificai ce se va afia la rularea urmtorului bloc PL/SQL:

DECLARE

v_var1 NUMBER :=100;

v_var2 NUMBER;

v_var3 NUMBER := v_var2;

v_var4 VARCHAR(20) := 'variabila PL/SQL';

v_var5 NUMBER NOT NULL := v_var1;

c_const1 CONSTANT DATE := TO_DATE('12/02/2007','dd/mm/yyyy');

c_const2 CONSTANT NUMBER NOT NULL := 2;

c_const3 CONSTANT NUMBER := NULL;

v_var6 NUMBER DEFAULT NULL;BEGIN

DBMS_OUTPUT.PUT_LINE('variabila 1 = '||v_var1);

DBMS_OUTPUT.PUT_LINE('variabila 2 = '||v_var2);

DBMS_OUTPUT.PUT_LINE('variabila 3 = '||v_var3);

DBMS_OUTPUT.PUT_LINE('variabila 4 = '||v_var4);

DBMS_OUTPUT.PUT_LINE('variabila 5 = '||v_var5);

DBMS_OUTPUT.PUT_LINE('constanta 1 = '||c_const1);

DBMS_OUTPUT.PUT_LINE('constanta 2 = '||c_const2);

DBMS_OUTPUT.PUT_LINE('constanta 3 = '||c_const3);

DBMS_OUTPUT.PUT_LINE('variabila 6 = '||v_var6);

END;

/

Specificai ce se va afia la rularea urmtorului bloc PL/SQL (care conine blocuri imbricate, ilustrnd domeniul de vizibilitate al unor variabile care au acelai nume):

DECLARE

var NUMBER;

BEGIN

var := 1;

DBMS_OUTPUT.PUT_LINE(var);

DECLARE

var NUMBER;

BEGIN

var :=2;

DBMS_OUTPUT.PUT_LINE(var);END bloc1;DBMS_OUTPUT.PUT_LINE(var);

DECLARE

var NUMBER;

BEGIN

var :=3;

DBMS_OUTPUT.PUT_LINE(var);

DECLARE

var NUMBER;

BEGIN

var :=4;

DBMS_OUTPUT.PUT_LINE(var);DBMS_OUTPUT.PUT_LINE(bloc2.var);END bloc3;

DBMS_OUTPUT.PUT_LINE(var);END bloc2;

DBMS_OUTPUT.PUT_LINE(var);END;

/

Specificai ce se va afia la rularea urmtorului bloc PL/SQLDECLARE

stoc NUMBER(3):=600;

mesaj VARCHAR2(50):='Produsul 101';

BEGIN

DECLARE

stoc NUMBER(3):=10;

mesaj VARCHAR2(50):='Produsul 102';

um VARCHAR2(10):= ' bucati ';

BEGIN

stoc:= stoc+1;

mesaj:='Stocul pentru '||mesaj||' este de: '||stoc||um;

DBMS_OUTPUT.PUT_LINE(mesaj);

END;

stoc:= stoc+100;

mesaj:='Stocul pentru '||mesaj||' este de: '||stoc||um;

DBMS_OUTPUT.PUT_LINE(mesaj);

END;

/S se calculeze suma a dou numere, iar rezultatul s se divid cu 3. Numerele se vor introduce de la tastatur.

VARIABLE g_rezultat number

ACCEPT p_num1 PROMPT 'Introducei primul numr:'

ACCEPT p_num2 PROMPT 'Introducei al doilea numr:'

DECLAREv_num1 number(9,2):=&p_num1;

v_num2 number(9,2):=&p_num2;

BEGIN:g_rezultat:=(v_num1+v_num2)/3;

END;

/

PRINT g_rezultat

Sa se calculeze produsul a 2 numere, date de la tastatura.

--punem rezultatul intr-o variabila de legatura pe care o vom afisa in afara blocului cu PRINT

VARIABLE g_rezultat number

--introducem cele doua numere de la tastatura

ACCEPT factor1 PROMPT 'Introduceti primul factor'

ACCEPT factor2 PROMPT 'Introduceti al doilea factor'

DECLARE

factor1 number(3):=&factor1;

--se foloseste & ca prefix pt factor1, pt ca in momentul executiei sa memoreze in factor1 valoarea pe care am introdus-o noi de la tastatura

factor2 number(3):=&factor2;

BEGIN

:g_rezultat:=factor1*factor2;

end;

/

PRINT g_rezultat Sa se afiseze salariul angajatului cu id-ul introdus de la tastatura.

--folosim o variabila de legatura in care sa punem salariul si o afisam in afara blocului cu PRINT

VARIABLE g_salariul number

--trebuie sa introducem id-ul angajatului

ACCEPT v_id PROMPT 'Introduceti id-ul angajatului'

DECLARE

v_id number(3):=&v_id;

BEGIN

SELECT salariul INTO :g_salariul FROM angajati WHERE id_angajat=v_id;

END;

/

PRINT g_salariul

Sa se afiseze salariul angajatului cu numele si prenumele introduse de la tastatura.

--folosim o variabila de legatura in care sa punem salariul si o afisam in afara blocului cu PRINT

VARIABLE g_salariul number

--trebuie sa introducem numele si prenumele angajatului

ACCEPT v_nume PROMPT 'Introduceti numele angajatului'

ACCEPT v_prenume PROMPT 'Introduceti prenumele angajatului'

DECLARE

v_nume varchar2(25):='&v_nume';

v_prenume varchar2(25):='&v_prenume';

BEGIN

SELECT salariul INTO :g_salariul FROM angajati WHERE nume='&v_nume' and prenume='&v_prenume';

END;

/

PRINT g_salariulS se afieze salariul mrit cu un procent. Salariul i procentul se dau de la tastatur

ACCEPT p_sal PROMPT 'Introducei salariul:'

ACCEPT p_procent PROMPT 'Introducei procentul:'

DECLAREv_sal number:=&p_sal;

v_procent number:=&p_procent;

BEGINdbms_output.put_line(to_char(nvl(v_sal,0)*(1+nvl(v_procent,0)/100)));

END;

/TEM: S se afieze cota de TVA pentru o anumit valoare introdus de la tastatur.INTERACIUNEA CU SERVERUL ORACLE PRIN COMENZI SQLInteraciunea se realizeaz prin intermediul comenzilor DDL (Data Definition Language), DCL (Data Control Lnaguage), DML (Data Manipulation Language), TPL (Transaction Processing Language) astfel:

PL/SQL nu suport comenzi DDL sau DCL n cadrul unui bloc. Pentru executarea acestor comenzi se utilizeaza comanda EXECUTE IMMEDIATE:Comenzi DDL/DCLExecutie

CREATE, ALTER, DROP

GRANT, REVOKEEXECUTE IMMEDIATE 'CREATE TABLE.... '

PL/SQL suport toate comenzile din limbajul de manipulare a datelor (DML) i din cel de control al tranzaciilor (TPL). Un bloc PL/SQL nu e o tranzacie. Comenzile Commit/ Rollback/ Savepoint sunt independente de bloc dar pot s apar n interiorul su.

Comenzi DML/TPLExecutie

SELECT, INSERT, UPDATE, DELETE, MERGE

COMMIT, ROLLBACK, SAVEPOINTSe executa normal in cadrul blocului

Pot aparea n bloc dar au efect asupra tuturor tranzaciilor din interiorul i din afara acestuia.

Exemple:Se creeaz tabela prod n cadrul unui bloc PL/SQL:

SET SERVEROUTPUT ON

--comenzi LDD

begin

--execute immediate 'DROP table prod';

execute immediate 'CREATE table prod AS SELECT * FROM produse where 1=2';

end;

/ Sa se creeze tabela STS in cadrul unui bloc.

set serveroutput on

BEGIN

--PL/SQL nu permite folosirea comenzilor LDD, prin urmare se foloseste sintaxa EXECUTE IMMEDIATE--id_trupa si nume_trupa sunt numele coloanelor saleEXECUTE IMMEDIATE 'CREATE TABLE STS(id_trupa number(3), nume_trupa varchar2(25))';

END;

/

select * from STS;

Se adaug n tabela prod nregistrri din tabela produse:

--comenzi LMD

--comenzi LMDdeclare v_codp produse.id_produs%type;v_denp produse.denumire_produs%type;v_cat produse.categorie%type;v_des produse.descriere%type;beginSELECT id_produs, denumire_produs, categorie, descriere INTO v_codp, v_denp, v_cat, v_des FROM produse where id_produs=3133;INSERT INTO prod (id_produs, denumire_produs, categorie, descriere) VALUES (v_codp, v_denp, v_cat, v_des);DBMS_OUTPUT.PUT_LINE ('S-a adaugat in tabela prod produsul: '||v_codp||' '||v_denp||' '||v_cat);end;/select * from prod; Sa se adauge in tabela STS in cadrul unui bloc valorile 101,'Fantasticii'.

set serveroutput on

begin

--comanda INSERT este o comanda LMD, deci este permisa de pl/sql

insert into sts values (101,'Fantasticii');

end;

/

select * from sts;

Sa se creeze tabela angajati5 pe baza tabelei angajati.

set serveroutput on

begin

execute immediate 'create table angajati5 as select * from angajati';

end;

/

select * from angajati5;

Sa se adauge in tabela STS inregistrarile coloanelor id_angajat si nume pt id-ul 100.set serveroutput on

DECLARE

--declaram variabilele in care sa se stocheze valorile pt id_angajat si nume

--folosim %TYPE pentru ca variabele noastre sa preia tipul coloanelor id_angajat, respectiv nume, trebuie sa indicam si tabela din care acestea fac parte

v_id angajati.id_angajat%TYPE;

v_nume angajati.nume%TYPE;

BEGIN

--comenzile LMD INSERT si SELECT sunt permise in blocul PL/SQLSELECT id_angajat, nume INTO v_id,v_nume from angajati WHERE id_angajat=100;

INSERT INTO STS(id_trupa,nume_trupa) VALUES(v_id,v_nume);

end;

/

Pentru o mai mare flexibilitate se poate declara o variabil de tip ir de caractere care s primeasc comanda DDL care va fi executat prin Execute Immediate:

Exemple:

Se creeaz tabela emp_sal prin intermediul unei variabile de tip Varchar2. La creare, n tabela emp_sal se va aduga o nou nregistrare.

SET SERVEROUTPUT ON

VARIABLE G_EID NUMBER

DECLARE

V_SIR VARCHAR2(200);

BEGIN

:G_EID:=110;

V_SIR:='CREATE table emp_sal AS SELECT id_angajat, nume, prenume, salariul

FROM angajati where id_angajat='||:G_EID;

DBMS_OUTPUT.PUT_LINE (V_SIR);

EXECUTE IMMEDIATE V_SIR;

END;

/

select * from emp_sal;

Se adaug o nou coloan STOC n tabela produse:

DECLAREV_SIR VARCHAR2(200);BEGINV_SIR:='ALTER TABLE PRODUSE ADD (STOC NUMBER (7))';DBMS_OUTPUT.PUT_LINE (V_SIR);EXECUTE IMMEDIATE V_SIR;END;/select * from PRODUSE;

Manipularea datelor in PL/SQL se face prin instruciunile DML (INSERT, UPDATE, DELETE) care pot fi lansate fr restricii n PL/SQL.

Exemple: Comanda INSERT

Se adaug o nou nregistrare n tabela emp_sal:

BEGININSERT INTO emp_sal (id_angajat, nume, prenume, salariul)VALUES (200, 'Pop', 'Marian', 7500);END;/select * from emp_sal;Se adaug o nou nregistrare n tabela produse prin introducerea valorilor cu ajutorul variabilelor de substituie:

BEGININSERT INTO produse (id_produs, denumire_produs, categorie, stoc)VALUES (&id, '&denumire', '&categorie', &stoc);END;/select * from produse;

Comanda UPDATESe mrete cu un procent salariul angajailor din tabela emp_sal care au n prezent salariul mai mic dect o anumit valoare:DECLAREv_procent number:=0.1;v_prag angajati.salariul%type:=10000;BEGINUPDATE emp_salSET salariul=salariul*(1+v_procent)WHERE salariul