Você está na página 1de 63

Base de Dados ORACLE

Pl-SQL Exerccio das aulas

Captulo PL-SQL
1.1 A Linguagem Pl-SQL
1.2 Utilizao de Procedimentos e Funes
1.3 Estruturas de dados em PL-SQL
1.4 Procedures, Functions e Packages em PL-SQL
1.5 Triggers

Apresentao do Exerccio

Modelo Relacional

DEPT PROJECTS
PROJID
DEPNO

DNAME P_DESC
LOC P_START_DATE
BUDGET_AMOUNT
MAX_NO_STAFF

EMP ASSIGNMENTS
PROJID
EMPNO

EMPNO
DEPNO

JOB A_START_DATE
SAL

MGR A_END_DATE
ENAME BILL_RATE
HIREDATE ASSIGN_TYPE
COMM HOURS

SALGRADE
LOSAL

HISAL

GRADE

Professor Jos Adriano 1


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Dicionrio de Dados

Tabela EMP
Nome coluna Tipo Dados Tamanho Chaves Restries

Empno NUMBER 4 Pr_Key Primary Key


(Num. Empregado)
Ename VARCHAR2 12 Not Null
(Nome Empregado)
Job VARCHAR2 12 Not Null
(Profisso)
Mgr NUMBER 4 Emp_mgr
(Chefe) Emp (empno)
Hirdate DATE Default
(Data admisso) Sysdate
Sal NUMBER 8,2 Between
(Salrio) 500 6000
Comm NUMBER 8,2
(Comisses)
Deptno NUMBER 2 Fr_Key Dept (deptno)
(Num. Departamento)

Tabela DEPT
Nome coluna Tipo Dados Tamanho Chaves Restries

Deptno NUMBER 2 Pr_Key Primary Key


(Num. Departamento)
Dname VARCHAR2 12 Not Null
(Nome departamento)
loc VARCHAR2 12 Not Null
(Localidade)

Tabela SALGRADE
Nome coluna Tipo Dados Tamanho Chaves Restries

Grade NUMBER 2 Pr_Key Primary Key


(Nvel remunerao)
Losal NUMBER 8 Not Null
(Salrio Mnimo)
Hisal NUMBER 8 Not Null
(Salrio Mximo)

Professor Jos Adriano 2


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Tabela ASSIGNMENTS

Nome coluna Tipo Dados Tamanho Chaves Restries

Projid NUMBER 4 Fr_Key Not Null


(Num. Projecto) Projects (projid)
Empno NUMBER 4 Fr_Key Not Null
(Num. Empregado) Emp (empno)
A_start_date DATE Not Null
(Data inicio tarefa)
A_end_date DATE >= A_start_date
(Data final tarefa)
Bill_rate NUMBER 4,2 Not Null
(Taxa Execuo)
Assign_Type VARCHAR2 2
(Tipo Tarefa)
Hours NUMBER 3
(Horas Trabalho)

Tabela PROJECTS

Nome coluna Tipo Dados Tamanho Chaves Restries

Projid NUMBER 4 Pr_Key Primary Key


(Num. Projecto)
P_desc VARCHAR2 30 Not Null
(Descrio projecto)
P_Start_date DATE Not Null
(Data inicio projecto)
P_end_date DATE 4 >= P_start_date
(Data concluso projecto)
Budget_amount NUMBER 7,2
(Valor gasto)
Max_no_staff NUMBER 2
(Membros do staff)

Professor Jos Adriano 3


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Contedo das Tabelas

EMP
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

7369 SMITH CLERK 7902 13-JUN-83 800 20


7499 ALLEN SALESMAN 7698 15-AUG-83 1600 300 30
7521 WARD SALESMAN 7698 26-MAR-84 1250 50 30
7566 JONES MANAGER 7839 31-OCT-83 2975 20
7654 MARTIN SALESMAN 7698 05-DEC-83 1250 1400 30
7698 BLAKE MANAGER 7839 11-JUN-84 2850 30
7782 CLARK MANAGER 7839 14-MAY-84 2450 10
7788 SCOTT ANALYST 7566 05-MAR-84 3000 20
7839 KING PRESIDENT 09-JUL-84 5000 10
7844 TURNER SALESMAN 7698 04-JUL-84 1500 0 30
7876 ADAMS CLERK 7788 04-JUL-84 1100 20
7900 JAMES CLERK 7698 23-JUL-84 950 30
7902 FORD ANALYST 7566 05-DEC-83 3000 20
7934 MILLER CLERK 7782 21-NOV-83 1300 10

DEPT SALGRADE
DEPNO DNAME LOC GRADE LOSAL HISAL

10 ACCOUNTING NEW YORK 1 700 1200


20 RESEARCH DALLAS 2 1201 1400
30 SALES CHICAGO 3 1401 2000
40 OPERATIONS BOSTON 4 2001 3000
5 3001 9999

ASSIGNMENTS
PROJID EMPNO A_START_DATE A_END_DATE BILL_RATE ASSIGN_TYPE HOURS

1 7369 01-JAN-88 03-JAN-88 50 WR 15


1 7902 04-JAN-88 07-JAN-88 55 WR 20
2 7844 01-JAN-89 10-JAN-89 45.5 PF 30

PROJECTS
PROJID P_DESC P_START_DATE P_END_DATE BUDGET_AMOUNT MAX_NO_STAFF

1 WRITE CO30 COURSE 02-JAN-88 07-JAN-89 500 1


2 PROOF READ NOTES 01-JAN-89 10-JAN-89 600 1

Professor Jos Adriano 4


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Criao das Bases de Dados em Oracle


CREATE TABLE dept
( Deptno NUMBER (2)
CONSTRAINT deptno_key PRIMARY KEY,
Dname VARCHAR2 (12) NOT NULL,
Loc VARCHAR2 (12) NOT NULL );

CREATE TABLE projects


( Projid NUMBER (4)
CONSTRAINT Proj_key PRIMARY KEY,
P_desc VARCHAR2 (12),
P_start_date DATE,
P_end_date DATE,
Budget_amount NUMBER (7,2),
Max_no_staff NUMBER (2) );

CREATE TABLE salgrade


( Grade NUMBER (2)
CONSTRAINT grade_key PRIMARY KEY,
Losal NUMBER (8) NOT NULL,
Hisal NUMBER (8) NOT NULL);

CREATE TABLE emp


( Empno NUMBER (4)
CONSTRAINT emp_key PRIMARY KEY,
Ename VARCHAR2 (12) NOT NULL,
Job VARCHAR2 (12) NOT NULL,
Mgr NUMBER (4)
CONSTRAINT emp_mgr
REFERENCES emp (empno),
Hirdate DATE DEFAULT SYSDATE,
Sal NUMBER (8,2)
CONSTRAINT Val_sal
CHECK ( Sal BETWEEN 500 AND 6000),
Comm NUMBER (8,2),
Deptno NUMBER (2),
CONSTRAINT deptno_fr_key
FOREIGN KEY(deptno)
REFERENCES dept (deptno));

Professor Jos Adriano 5


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

CREATE TABLE assignments


( Projid NUMBER (4) NOT NULL
REFERENCES projects (projid),
Empno NUMBER (4) NOT NULL
REFERENCES emp (empno),
A_start_date DATE,
A_end_date DATE,
Bill_rate NUMBER (4,2) NOT NULL,
Assign_Type VARCHAR2 (2),
Hours NUMBER (3),
CONSTRAINT data_cons
CHECK (A_end_date >= A_start_date) );

Professor Jos Adriano 6


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

1.1 A Linguagem PL/SQL


PL/SQL uma linguagem procedimental
PL/SQL baseia-se nos conceitos bsicos do SQL
PL7SQL permite 4 tipos de construes bsicas
Anonymous block
o Conjunto integrado de instrues que funcionam como um bloco,
mas no ficam armazenadas na base de dados
Stored Procedure and function
o Conjunto integrado de instroes que funcionam como um bloco,
e ficam armazenadas na base de dados, de acordo com um nome
o As funes e procedimentos podem sere chamadas para diferentes
aplicaes
o Uma funo retorna um valor
o Um procedimento executa uma srie de aces e pode retornar mais
do que um valor
Package
o Conjunto de procedimentos e funes que constituem uma aplicao
Trigger
o Procedimento associado a uma determinada tabela ou View ou evento.
o Pode ser desencadeado depois de um evento para automatizar um
conjunto de tarefas associadas ao mesmo
o Pode ser chamado antes do evento, para prevenir erros na manipulao
dos dados

Professor Jos Adriano 7


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

FUNES

Definio de Funo
Uma funo PL-SQL um programa desenvolvido nesta linguagem cujo
objectivo e a devoluo de um valor que pode ser de qualquer tipo de
dados.
As funes podem aceitar argumentos de entrada necessrios produo
do resultado de sada.

Estrutura bsica de uma funo sem argumentos

CREATE OR REPLACE FUNCTION <function_name>


RETURN <variable_type> IS

<variable declarations>

BEGIN
<code_here>;
END <function_name>;

Exemplos:
Criar uma funo que retorna uma string

-- Criar a funo

CREATE OR REPLACE FUNCTION simple RETURN VARCHAR2 IS

BEGIN
RETURN 'Simple Function';
END simple;

-- Executar a funo

SELECT simple FROM dual;

Professor Jos Adriano 8


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Criar uma funo para associar introduo de valores num


campo chave

Create function get_empno return number


is
novo_valor number(4);

Begin
select max(empno)+1
into novo_valor
from emp;

return (novo_valor);
end;

Chamada da funo
Select Get_empno from dual;

Estrutura bsica de uma funo com argumentos

Create function Nome_funo(arg1 in tipo_dado_ent,


arg2 in tipo_dado_ent)
return tipo_dado_saida
IS
--Area de definio de variveis
Var_ent_1 tipo_dado;
Var_ent_2 tipo_dado;
Var_saida_3 tipo_dado;

--Bloco de programa
BEGIN
Var_ent_1 := arg1;
Var_ent_2 := arg2;
Var_saida_3 := calculo_de_valor_de_saida;
return(var_saida_3);
END

Professor Jos Adriano 9


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Chamada da Funo

DECLARE
Arg1 tipo_dado;
Arg2 tipo_dado;
BEGIN
HTP.P(nome_funo(:arg1, :arg2));
END;

Exemplos

Criar uma funo para calcular a rea de um quadrado, ao


quadrado, tomando como argumentos de entrada os seus lados

---Bloco simples ou de teste

DECLARE
area number;
l1 number;
l2 number;

BEGIN
l1:= 2;
l2:= 2;
area :=POWER((l1*l2),2);
htp.p(' A area :' || area);
END

---Criar a funo

Create function area_quadrado(lado1 in number, lado2 in number) return number


IS
area number;
l1 number;
l2 number;

BEGIN
l1:= lado1;
l2:= lado2;
area :=POWER((l1*l2),2);
return(area);
END
Professor Jos Adriano 10
Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

---Chamada da Funo

DECLARE
lado1 NUMBER;
lado2 NUMBER;
BEGIN
Htp.p(area_quadrado(:lado1, :lado2));
END;

Exerccio

Sabendo que as formulas para calcular as seguintes reas e volumes so:


rea do tringulo = (base * altura) / 2
rea do trapezio = [(base maior + base menor)*altura] / 2
Volume do cubo = aresta elevada ao cubo
Volume da pirmide = (rea da base * altura) / 3

Professor Jos Adriano 11


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Criar uma funo para retornar o nome de um empregado tendo


como argumento de entrada o seu nmero.

-- Criar funo

create or replace function nome_empregado( numero in number) return varchar2


is
emp_name VARCHAR2(20);
num Number;
BEGIN
num:= numero;
SELECT ename INTO emp_name
FROM emp WHERE empno = num;
return(emp_name);

END;

-- Chamar a funo

DECLARE
numero number;

BEGIN
Htp.p('o nome :' || nome_empregado(:numero));
END

NOTA:
Uma funo pode ser:
Executada de forma independente
select nome_empregado(7902) from dual;
select nome_empregado(:numero) from dual;

Associada a uma varivel de uma outra funo ou procedimento


employee_name := nome_empregado(:numero);

Inserido numa clusula select ou where de uma query ou num INSERT


select job, sal, NOME_EMPREGADO(:numero)
from emp
where ename = NOME_EMPREGADO(:numero);

Inserido num comando INSERT ou UPDATE


INSERT INTO EMP (empno, ename)
VALUES (1222, NOME_EMPREGADO(:numero));

Professor Jos Adriano 12


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Criar uma funo para calcular a diferena entre datas

CREATE OR REPLACE FUNCTION date_diff (max_date DATE, min_date DATE)


RETURN INTEGER
IS
BEGIN
RETURN max_date - min_date;

EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END date_diff;

SELECT object_name, date_diff(last_ddl_time, created) FROM user_objects;

Outra forma

CREATE OR REPLACE FUNCTION date_diff (max_date STRING, min_date STRING)


RETURN INTEGER
IS
BEGIN
RETURN TO_DATE(max_date) - TO_DATE(min_date);

EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END date_diff;

SELECT date_diff('03-01-01', '02-01-01') FROM dual;

Professor Jos Adriano 13


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Criar uma funo para determinar se uma String numrica.

CREATE OR REPLACE FUNCTION is_number(char_in VARCHAR2)


Return BOOLEAN
IS
BEGIN
n := TO_NUMBER(char_in);
RETURN TRUE;

EXCEPTION
WHEN OTHERS THEN
RETURN FALSE;
END is_number

Chamar Funo

DECLARE

BEGIN
IF is_number(:string) THEN
htp.p('TRUE');
ELSE
htp.p('FALSE');
END IF;
END;

Professor Jos Adriano 14


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Criar uma funo para determinar se o primeiro character de uma


string um nmero

CREATE OR REPLACE FUNCTION is_digit (chr_in VARCHAR2) RETURN BOOLEAN


IS
BEGIN
IF (SUBSTR(chr_in, 1, 1) IN ('0','1','2','3','4','5','6','7','8','9')) THEN
RETURN TRUE;
END IF;
EXCEPTION
WHEN OTHERS THEN
RETURN FALSE;
END is_digit;

Chamar Funo (True ou False)


DECLARE

BEGIN
IF is_digit(:chr_in) THEN
Htp.p('TRUE');
end if;
EXCEPTION
WHEN OTHERS THEN
Htp.p('False');
END;

Criar uma funo para gerar Passwords

De comprimento fixo
SELECT DBMS_RANDOM.STRING('X',8)
From Dual;

De comprimento varivel
SELECT
DBMS_RANDOM.STRING('X',TO_NUMBER(SUBSTR(TO_CHAR(DBMS_RANDOM.
NORMAL()),3,1)))
FROM DUAL

Professor Jos Adriano 15


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Criar uma funo para determinar se um nmero par

CREATE OR REPLACE FUNCTION is_even(num_in NUMBER) RETURN BOOLEAN IS


BEGIN
IF MOD(num_in, 2) = 0 THEN
RETURN TRUE;
END IF;
EXCEPTION
WHEN OTHERS THEN
RETURN FALSE;
END is_even;

Chamar Funo para True ou False

DECLARE

BEGIN
IF is_even(:num_in) THEN
Htp.p('TRUE');
end if;

EXCEPTION
WHEN OTHERS THEN
Htp.p('False');

END;

Professor Jos Adriano 16


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Construo de uma FUNCTION com retorno de uma STRING

CREATE OR REPLACE FUNCTION Trab_19 (empid NUMBER)


RETURN VARCHAR2 IS
nome emp.ename%TYPE;
prof emp.job%TYPE;

BEGIN
SELECT ename, job INTO nome, prof FROM emp
WHERE empno = empid;
RETURN ('Empregado ' || empid || ' - ' || UPPER(nome)|| ', ' || UPPER(prof) );
END trab_19;

Chamar funo

DECLARE

BEGIN
HTP.P(trab_19(:empid));
END;

Professor Jos Adriano 17


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

EXERCICIOS:

1. Crie uma funo que calcule o diferencial, percentual, do salrio de


um empregado face ao diferencial total dos salrios.
- O salrio do empregado XPTO representa X% do diferencial total
de salrios.
- Return ( (Salario-min_sal)/(Max_sal-min_sal)*100 )

2. Crie uma funo que permita calcular o desvio do salrio de um


empregado, relativamente mdia dos salrios.
- O desvio padro do salrio do empregado XPTO, relativamente
mdia :
- Return ( (Salario-media_sal)/(Max_sal-min_sal)*100 )

3. Criar uma funo para determinar a diferena entre horas

4. Criar uma funo para determinar a distncia entre pontos, tendo


por base a sua latitude e longitude

Professor Jos Adriano 18


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Exercicio 1. Diferencial de Salarios

CREATE OR REPLACE FUNCTION exerc1 (empid NUMBER)


RETURN NUMBER IS
minsal emp.sal%TYPE;
maxsal emp.sal%TYPE;
jobid emp.job%TYPE;
salario emp.sal%TYPE;

BEGIN

SELECT job, sal INTO jobid, salario FROM emp


WHERE empno = empid;

SELECT MIN(sal), MAX(sal) INTO minsal, maxsal FROM emp


WHERE job = jobid;

RETURN ((salario - minsal) / (maxsal-minsal)*100);


END;

Chamar Funo

DECLARE
empid NUMBER;
BEGIN
empid := :empid;
htp.p('The salary ranking for employee ' || empid
|| ' IS: ' || ROUND(exerc1(empid), 2));
END;

Professor Jos Adriano 19


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Exercicio 2. Desvio Padro do salario

CREATE OR REPLACE FUNCTION exerc2 (empid NUMBER)


RETURN NUMBER IS
medsal emp.sal%TYPE;
salario emp.sal%TYPE;
jobid emp.job%type;
BEGIN

SELECT sal, job INTO salario, jobid FROM emp


WHERE empno = empid;

SELECT AVG(sal) into medsal FROM emp


WHERE job = jobid;
RETURN (((salario - medsal ) /medsal)*100);
END;

DECLARE
empid NUMBER;
BEGIN
empid := :empid;
htp.p ('The average ranking for employee ' || empid
|| ' IS: ' || ROUND(exerc2(empid), 2));
END;

Professor Jos Adriano 20


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Exercicio 3. Criar uma funo para determinar a diferena entre


horas

CREATE OR REPLACE FUNCTION tn_time_diff(DATE_1 IN DATE, DATE_2 IN DATE)


RETURN NUMBER IS
NDATE_1 NUMBER;
NDATE_2 NUMBER;
NSECOND_1 NUMBER(5, 0);
NSECOND_2 NUMBER(5, 0);
BEGIN
-- Get Julian date number from
-- first date (DATE_1)
NDATE_1 := TO_NUMBER(TO_CHAR(DATE_1, 'J'));

-- Get Julian date number from


-- second date (DATE_2)
NDATE_2 := TO_NUMBER(TO_CHAR(DATE_2, 'J'));

-- Get seconds since midnight


-- from first date (DATE_1)
NSECOND_1 := TO_NUMBER(TO_CHAR(DATE_1, 'SSSSS'));

-- Get seconds since midnight


-- from second date (DATE_2)
NSECOND_2 := TO_NUMBER(TO_CHAR(DATE_2, 'SSSSS'));

RETURN (((NDATE_2 - NDATE_1)*86400)+(NSECOND_2 - NSECOND_1));


END tn_time_diff;
/

SELECT tn_time_diff('03-01-02', '03-01-03') FROM dual;

Professor Jos Adriano 21


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Exercicio 4. Criar uma funo para determinar a distncia entre


pontos, tendo por base a sua latitude e longitude

CREATE OR REPLACE FUNCTION calc_distance ( pLat1 NUMBER, pLon1 NUMBER,


pLat2 NUMBER, pLon2 NUMBER)
RETURN NUMBER
IS
-- r is the spherical radius of earth in Kilometers
cSpherRad CONSTANT NUMBER := 6367;

-- The spherical radius of earth in miles is 3956


a NUMBER;
vLat NUMBER;
vLat1Rad NUMBER;
vLat2Rad NUMBER;
vLon NUMBER;
vLon1Rad NUMBER;
vLon2Rad NUMBER;

BEGIN
/*
Most computers require the arguments of trigonometric functions to be
expressed in radians. To convert lon1, lat1 and lon2,lat2 from
degrees,minutes, seconds to radians, first convert them to decimal
degrees. To convert decimal degrees to radians, multiply the number
of degrees by pi/180 = 0.017453293 radians/degrees.
*/

vLat1Rad := pLat1 * 0.017453293;


vLat2Rad := pLat2 * 0.017453293;
vLon1Rad := pLon1 * 0.017453293;
vLon2Rad := pLon2 * 0.017453293;

vLon := vLon2Rad - vLon1Rad;


vLat := vLat2Rad - vLat1Rad;

a := POWER(SIN(vLat/2),2) + COS(vLat1Rad) * COS(vLat2Rad) *


POWER(SIN(vLon/2),2);

Professor Jos Adriano 22


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

/*
The intermediate result c is the great circle distance in radians.
Inverse trigonometric functions return results expressed in radians.
To express c in decimal degrees, multiply the number of radians by
180/pi = 57.295780 degrees/radian.
The great circle distance d will be in the same units as r.
*/

RETURN ROUND(cSpherRad * 2 * ATAN2(SQRT(a), SQRT(1-a)),1);


EXCEPTION
WHEN OTHERS THEN
RETURN 999;
END calc_distance;

Chamar a funo

SELECT calc_distance(1,2,3,4) FROM dual;

Professor Jos Adriano 23


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

PROCEDIMENTOS - PROCEDURE

Crie um procedimento que faa o seguinte.


Se a primeira letra do nome do empregado for vogal chama a funo
diferencial de salrio (exerccio 1)
Se a primeira letra do nome do empregado for constante chama a
funodesvio padro do salrio (exercicio2)

CREATE OR REPLACE PROCEDURE Chama_funcoes As

empid emp.empno%type;
nome emp.ename%type;
prof emp.job%type;

BEGIN
empid := 7902;

Select ename, job into nome, prof


from emp
where emp.empno=empid;

IF (SUBSTR(nome, 1, 1) IN ('A','E','I','O','U')) THEN

Htp.p('The salary ranking for employee ' || empid


|| ' IS: ' || ROUND(exerc1(empid), 2));
ELSE
Htp.p('The average ranking for employee ' || empid
|| ' IS: ' || ROUND(exerc2(empid), 2));
END IF;

END;

Professor Jos Adriano 24


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Crie um procedimento que permita calcular o valor da diria de trabalho


tendo por base o salrio mensal e os dias efectivos de trabalho.

CREATE OR REPLACE PROCEDURE


TRAB_1 (x1 IN NUMBER, x2 IN NUMBER) As
salario_mensal NUMBER(6);
dias_trabalho NUMBER(2);
diaria NUMBER(6,2);

BEGIN
salario_mensal:= x1;
dias_trabalho:= x2;
diaria:= salario_mensal/dias_trabalho;
htp.p ('O Valor da diaria : ' || To_char(diaria));

EXCEPTION
WHEN ZERO_DIVIDE THEN
diaria:=0;
END;

Chamada do procedimento

Begin
Trab_1(:x1, :x2);
End;

Professor Jos Adriano 25


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Crie um Procedimento que permita calcular a mdia ponderada de trs


variveis de entrada, com introduo (via Parametros) dos valores e
respectivas ponderaes:

CREATE OR REPLACE PROCEDURE


EXERC_2 (var1 IN NUMBER, var2 IN NUMBER, var3 IN NUMBER, Valor1 IN NUMBER,
valor2 IN Number, Valor3 IN NUMBER) As
Variavel1 NUMBER(6);
Variavel2 NUMBER(6);
Variavel3 NUMBER(6);
Pond1 NUMBER (6);
Pond2 NUMBER (6);
Pond3 NUMBER (6);
Media Number (8,2);

BEGIN
Variavel1:= var1;
Variavel2:= var2;
Variavel3:= var3;

Pond1:= valor1;
Pond2:= valor2;
Pond3:= valor3;

Media:= ((variavel1*Pond1) + (variavel2*Pond2) +( variavel3*pond3)) / (pond1


+ pond2 + pond3);

-- The following displays output from the PL/SQL block


htp.p ('O Valor da Mdia Ponderada : ' || To_char(Media));

-- The following is an optional exception part that handles erros


EXCEPTION
WHEN ZERO_DIVIDE THEN
Media:=0;
END ;

begin
Exerc_2(:var1, :var2, :var3, :valor1, :valor2, :valor3);
End;

Professor Jos Adriano 26


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Declarao de variaveis a partir de valores da Dase Dados


Calcular o valor de um bnus de 5% do salrio base para um determinado
empregado

CREATE OR REPLACE PROCEDURE


TRAB_4(NUM In NUMBER) AS

Taxa CONSTANT NUMBER(2,2) := 0.05;


Bonus NUMBER(8,2);
Emp_id NUMBER(4);

BEGIN
Emp_id := NUM;

SELECT EMP.Sal*Taxa INTO Bonus


FROM EMP
WHERE Empno = Emp_id;

htp.p ('O Empregado : ' ||TO_CHAR( Emp_id) || 'O Bonus : ' ||


TO_CHAR(Bonus));
END;

BEGIN
TRAB_4(:NUM);
END;

OBS.
Criar uma variante deste exerccio para uma valor de taxa varivel.

Professor Jos Adriano 27


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Exercicios para o trabalho final

TRAB_1
Crie um procedimento PL-SQL que mostre o maior, menor e mdia
de salrios de uma determinada profisso.

Objectivo: Carregar contedos de determinados campos da BD para Memoria.

CREATE OR REPLACE PROCEDURE TRAB_1( prof IN VARCHAR2) AS

Registo_emp emp%ROWTYPE;
profissao VARCHAR2(10);
avg_sal NUMBER;
min_sal NUMBER;
max_sal NUMBER;

BEGIN

profissao := prof;
SELECT AVG(sal), MIN(sal), MAX(sal) INTO avg_sal, min_sal, max_sal
FROM emp
WHERE emp.job = (profissao);

htp.p ('Nome da Profisso: ' || registo_emp.job );


htp.p ('A mdia de salarios da profissao: ' ||
' is: ' || TO_CHAR(avg_sal));
htp.p ('O salrio mnimo da profisso: ' ||
' is: ' || TO_CHAR(min_sal));
htp.p ('O salrio mximo da profisso: ' ||
' is: ' || TO_CHAR(max_sal));
END

---------------------
BEGIN
TRAB_1(:prof);
END;

Professor Jos Adriano 28


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_2
Criar um procedimento que permita carregar em memria a
totalidade de um registo da base de dados, de um qualquer
empregado, e calcule um valor de bonificao de acordo com as
seguintes condies:
- Se o numero de empregado < 100 atribui um bnus de 500;
- Se o numero de empregado > 100 atribui um bnus de 500;
- se o numero de empregado = 100 atribui um bnus de 750;

Objectivo: Carregar, de forma integral, os contedos de um determinado registo da


BD para a Memoria.
Estudo da estrutura IF-THEN-ELSE

CREATE OR REPLACE PROCEDURE


TRAB_2(Num_empregado IN NUMBER) AS

Registo_emp emp%ROWTYPE;
bonus NUMBER(6):= 0;
Emp_id NUMBER(4);

BEGIN
Emp_id := Num_empregado;

SELECT * INTO Registo_emp


FROM Emp
WHERE empno = Emp_id;

IF registo_emp.empno > 100 THEN


bonus := 500;
ELSIF registo_emp.empno < 100 THEN
bonus := 1000;
ELSE
bonus := 750;
END IF;

htp.p ('O valor do Bonus para Empregado ' || registo_emp.ename|| ' is ' ||bonus );

Professor Jos Adriano 29


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

EXCEPTION
When others then
htp.p ('Este empregado no existe');
END;

-------------------------
BEGIN
TRAB_2(:Num_empregado);
END;

Professor Jos Adriano 30


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_3
Crie um procedimento Pl-SQL que permita adicionar um bnus, para um
qualquer empregado da tabela Emp da Base de dados, calculado da seguinte
forma:
- Se empregado tiver at dois anos de casa, calcula um bnus com base numa
taxa que pode variar entre os 0-4% do salrio base;
- Se o empregado tiver entre dois e cinco anos de servio, calcula um bnus
com base numa taxa que pode variar entre os 5-7% do salrio base.
- Se o empregado tiver mais do que cinco anos de servio, calcula um bnus
que pode variar entre os 8-10% do salrio base.

No final escreva o nome do empregado, salrio base, bnus,


Total = salrio+bonus e tempo servio.

Objectivo: Consolidar a estrutura IF_THEN_ELSE


Varios Parametros de entrada

CREATE OR REPLACE
PROCEDURE TRAB_3(Num_empregado IN NUMBER, taxa_Baixa IN NUMBER,
Taxa_media IN NUMBER, Taxa_alta IN NUMBER) AS

Registo_emp Emp%ROWTYPE;
bonus NUMBER(8,2);
Total NUMBER(8,2);
Tempo NUMBER(3);
Taxa_1 NUMBER(2);
Taxa_2 NUMBER(2);
Taxa_3 NUMBER(2);
Emp_id NUMBER(4);

BEGIN

Emp_id := Num_empregado;
Taxa_1 := Taxa_baixa;
Taxa_2 := Taxa_media;
Taxa_3 := Taxa_alta;

SELECT * INTO Registo_emp


FROM Emp
WHERE empno = Emp_id;

Professor Jos Adriano 31


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

IF (MONTHS_BETWEEN(SYSDATE, Registo_emp.hiredate) < 24)


THEN
Tempo:= MONTHS_BETWEEN(SYSDATE, Registo_emp.hiredate);
bonus := registo_emp.sal*Taxa_1;
Total := Registo_emp.sal+bonus;
ELSIF (MONTHS_BETWEEN( SYSDATE, Registo_emp.hiredate) > 24) AND
(MONTHS_BETWEEN (SYSDATE, Registo_emp.Hiredate ) < 60)
THEN
bonus := registo_emp.sal*Taxa_2;
Total := Registo_emp.sal+bonus;
Tempo:= MONTHS_BETWEEN(SYSDATE, Registo_emp.hiredate);
ELSE
bonus := Registo_emp.sal*Taxa_3;
Total := Registo_emp.sal+bonus;
Tempo:= MONTHS_BETWEEN(SYSDATE, Registo_emp.hiredate);
END IF;

htp.p ('Nome Empregado: ' || (Registo_emp.ename) || ' Bonus is ' || (bonus) || '
Tempo Servio:' || (Tempo));
END;

---------------------------
BEGIN
TRAB_3(:Num_empregado, :taxa_baixa, :taxa_media, :taxa_alta);
END;

Professor Jos Adriano 32


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_4
Elabore um procedimento que carregue em memria o registo de
um determinado empregado e que calcule um valor de aumento
de salrio de acordo com as seguintes condies:
- Quando Profissao = Clerk e Salario < 3000 ento aumento = 8%
Seno aumento = 7%
- Quando Profissao = Analista e Salario< 4000 ento aumento = 6%
Seno aumento = 5%
Quando Profissao = Manager e Salario < 3500 ento aumento = 4%
Seno aumento = 3%

Objectivo: Estudo da estrutura CASE

CREATE OR REPLACE PROCEDURE


TRAB_4 (Num_emp IN NUMBER) AS

Registo_emp emp%ROWTYPE ;
salario NUMBER(8,2);
aumento NUMBER(3,2);
emp_id NUMBER(4);

BEGIN
Emp_id := Num_emp;

SELECT * INTO Registo_emp


FROM emp
WHERE emp.empno = emp_id;

CASE
WHEN Registo_emp.job = 'clerk' THEN
IF Registo_emp.sal < 3000 THEN aumento := 0.08;
ELSE aumento :=0.07;
END IF;

WHEN Registo_emp.job = 'analyst' THEN


IF registo_emp.sal < 4000 THEN aumento := 0.06;
ELSE aumento := 0.05;
END IF;

Professor Jos Adriano 33


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

WHEN Registo_emp.job = 'manager' THEN


IF Registo_emp.sal < 3500 THEN aumento :=0.04;
ELSE aumento := 0.03;
END IF;
ELSE
BEGIN
htp.p (' Esta profissao no tem aumentos: ' ||
registo_emp.job);
END;

END CASE;

htp.p ('Aumento de salario do: ' || emp_id || ' is: ' || aumento );
END;

-------------------------
BEGIN
TRAB_4(:num_emp);
END;

Professor Jos Adriano 34


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_5.1
Crie um procedimento que permita mostrar o nome e a profisso
de um determinado empregado, fazendo uso de um cursor.

Objectivo: Captura de um registo com cursores


Obs:
Neste caso o cursor tem o mesmo propsito de uma varivel ROWTYPE na medida
em que obtem apenas um registo.

CREATE OR REPLACE
PROCEDURE TRAB_5 (Numero IN NUMBER) AS

nome emp.ename%TYPE;
profissao emp.job%TYPE;
emp_id NUMBER;

CURSOR Empregado IS
SELECT ename, job
FROM emp
WHERE empno = emp_id;

BEGIN

emp_id := Numero;
OPEN Empregado;
FETCH Empregado INTO nome, profissao;
htp.p (' Nome do empregado: ' || nome);
htp.p (' Profissao: ' || profissao);
CLOSE Empregado;
END

-----------------------
BEGIN
trab_5(:Numero);
END;

Professor Jos Adriano 35


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_5.2
Crie um procedimento que permita mostrar o nome e a profisso e
a localidade do departamento um determinado empregado,
fazendo uso de um cursor.

Objectivo: Cursores com Joins

CREATE OR REPLACE PROCEDURE TRAB_5.1 (Numero IN NUMBER) AS

nome emp1.ename%TYPE;
profissao emp1.job%TYPE;
dloc dept1.loc%type;
emp_id NUMBER;

CURSOR Empregado IS
SELECT ename, job, loc
FROM emp1 inner join dept1 on emp1.deptno = dept1.deptno
WHERE emp1.empno = emp_id;

BEGIN
emp_id := Numero;

OPEN Empregado;
FETCH Empregado INTO nome, profissao, dloc;
htp.p (' Nome do empregado: ' || nome);
htp.p (' Profissao: ' || profissao);
htp.p (' Localidade: ' || dloc);
CLOSE Empregado;
END;

Professor Jos Adriano 36


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_5.3
Crie um procedimento que permita mostrar o nome e a profisso
de todos os empregados, fazendo uso de um cursor.

Objectivo: Captura de varios registos com cursores


Utilizao de estrutura do tipo Rowtype para recolha dos dados;

CREATE OR REPLACE PROCEDURE trab_5a AS

reg_emp emp%ROWTYPE;

CURSOR empregado IS
SELECT emp.ename,emp.job
FROM emp;

BEGIN
OPEN empregado;
LOOP
FETCH empregado INTO reg_emp.ename, reg_emp.job;
EXIT WHEN empregado%NOTFOUND;
htp.p ('O nome '||reg_emp.ename||' e a profisso '||reg_emp.job);
END LOOP;
CLOSE empregado;
END;

------------------------
BEGIN
trab_5a;
END;

Professor Jos Adriano 37


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_6
Crie um procedimento que implemente dois cursores.
O 1 cursor apresenta o nome e a profisso, de todos os
empregados para uma determinada profisso.
O 2 Cursor apresenta o nmero, nome e a profisso de todos os
empregados das profisses C%

Objectivo: Captura de vrios registos com cursores


Implementao de contadores par nmero de linhas

CREATE OR REPLACE PROCEDURE trab_6 (prof IN VARCHAR2) AS


profissao emp.job%TYPE;
reg_emp1 emp%ROWTYPE;
contador1 NUMBER;
reg_emp2 emp%ROWTYPE;
contador2 NUMBER;

CURSOR empregado1 IS
SELECT emp.ename, emp.job
FROM emp
WHERE emp.job=profissao;

CURSOR empregado2 IS
SELECT emp.empno, emp.ename, emp.job
FROM emp
WHERE emp.job LIKE 'C%';

BEGIN
profissao:=prof;

htp.p ('------------- CURSOR 1 -------------');


OPEN empregado1;
LOOP
FETCH empregado1 INTO reg_emp1.ename, reg_emp1.job;
EXIT WHEN empregado1%NOTFOUND;
htp.p (' O Nome '||reg_emp1.ename||' y la profesin es
'||reg_emp1.job);
END LOOP;
contador1:=empregado1%ROWCOUNT;
htp.p (' O nmero de registros transferidos foi '||contador1);
CLOSE empregado1;
Professor Jos Adriano 38
Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

htp.p ('------------- CURSOR 2 -------------');


OPEN empregado2;
LOOP
FETCH empregado2 INTO reg_emp2.empno, reg_emp2.ename, reg_emp2.job;
EXIT WHEN empregado2%NOTFOUND;
HTP.P('El nmero es '||reg_emp2.empno||' el nombre es
'||reg_emp2.ename||' y la profesin es '||reg_emp2.job);
END LOOP;
contador2:=empregado2%ROWCOUNT;
htp.p (' O nmero de registros transferidos foi '||contador2);
CLOSE empregado2;
END;

--------------------------
BEGIN
trab_6(:prof);
END;

Professor Jos Adriano 39


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_7
Criar um procedimento PL-SQL que permita mostrar o nome,
profisso, salrio e o nome do departamento de todos os
empregados de um determinado departamento.

Objectivo: Utilizao de cursores para captura de registos de diferentes tabelas, com


base nos processos de juno

CREATE OR REPLACE PROCEDURE TRAB_7(Dept_num IN Number) AS

Nome emp.ename%TYPE; NOTA.


Prof emp.job%TYPE; Crie uma variante deste exerccio,
Salario emp.sal%TYPE; mas fazendo uso de duas estruturas de
Departamento dept.dname%TYPE; dados do tipo Rowtype para Emp e
Nlinhas NUMBER; Dept.

CURSOR cursor1 IS
Select emp.ename, emp.job, emp.sal, dept.dname
FROM emp, dept
WHERE emp.depno = dept.depno
AND dept.depno = (Dept_num);

BEGIN

OPEN cursor1;
htp.p ('********* Cursor1 *********');
LOOP
FETCH cursor1 INTO Nome, Prof, Salario, Departamento;
EXIT WHEN cursor1%NOTFOUND;
htp.p ('Nome: ' || Nome || ' ' || 'Profissao: ' || Prof
|| ' ' || 'Salario: ' || Salario|| ' ' || 'Departamento: ' || Departamento);
END LOOP;
Nlinhas := cursor1%ROWCOUNT;
htp.p (' Numero empregados: ' || Nlinhas);
CLOSE cursor1;
END;

----------------------------
BEGIN
TRAB_7(:Dept_num);
END;

Professor Jos Adriano 40


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_8
Crie um procedure PL-SQL que permita saber o Nome, Profisso,
Salario e o nome do departamento dos 2 empregados que ganham
mais, num determinado departamento

Objectivo: Utilizao de cursores integrados em ciclos

CREATE OR REPLACE PROCEDURE TRAB_8(Dept_num IN Number) AS

Registo_emp emp%Rowtype;
Registo_dept dept%Rowtype;
Nlinhas NUMBER;
Contador NUMBER;

CURSOR cursor1 IS
Select emp.ename, emp.job, emp.sal, dept.dname
FROM emp, dept
WHERE emp.depno = dept.depno
AND dept.depno = (Dept_num)
Order By emp.sal Desc;

BEGIN
OPEN cursor1;
htp.p ('********* Cursor1 *********');

FOR contador IN 1..2 LOOP


FETCH cursor1 INTO registo_emp.ename, registo_emp.job, registo_emp.sal,
Registo_dept.dname;
EXIT WHEN cursor1%NOTFOUND;
htp.p ('Nome: ' || registo_emp.ename || ' ' || 'Profissao: ' ||
registo_emp.job || ' ' || 'Salario: ' || registo_emp.sal || ' ' || 'Departamento: '
|| Registo_dept.dname);
END LOOP;
Nlinhas := cursor1%ROWCOUNT;
htp.p (' Numero empregados: ' || Nlinhas);
CLOSE cursor1;
END;

----------------
BEGIN
TRAB_8(:Dept_num);
END;
Professor Jos Adriano 41
Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_9
Crie um procedure PL-SQL que permita saber o Nome, e a data de
admisso e o nome do departamento dos empregados mais
antigos de cada departamento.

Objectivo: Estudo de cursores Com subquerys

Create or replace procedure TRAB_9 as


reg_emp emp%rowtype;
reg_dept dept%rowtype;
nlinhas number;

cursor cursor1 is
select emp.ename, emp.hiredate, dept.dname
from emp, dept
where emp.depno=dept.depno
And(emp.depno,emp.hiredate) in(select emp.depno, max(hiredate)
from emp
group by emp.depno );

begin
open cursor1;
htp.p ('********* Cursor1 *********');
loop
fetch cursor1 into reg_emp.ename, reg_emp.hiredate, reg_dept.dname;
exit when cursor1%notfound;
htp.p ('O Empregado: '||reg_emp.ename||', com a data de admissao:
'||reg_emp.hiredate || ' o mais velho do departamento : ' || reg_dept.dname||'.');
end loop;
nlinhas:=cursor1%rowcount;
htp.p ('Total de Empregrados: '||nlinhas);
close cursor1;
end;
------------------
Begin
Trab 9;
End;

Professor Jos Adriano 42


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_10
Crie um procedure PL-SQL que permita fazer a insero de dados
na tabela de Empregados

Objectivo: Insero de dados via Pl-Sql

Create or replace procedure Trab_10 (numero in number,


nome in varchar2,
Dept1 in number,
Prof1 in varchar2,
chefe in varchar2,
data in date,
Com in number,
salario in number)As

BEGIN
INSERT INTO emp (empno, ename, deptno, job, mgr, hiredate, comm, sal)
VALUES (numero, nome, Dept1, Prof1, chefe, data, Com, salario);

exception
when no_data_found then
htp.p('Introduza um Nmero de empregado vlido');

END;

--------
Begin
Trab_10 (:numero, :nome, :Dept1, :Prof1, :chefe, :data, :Com, :salario);
End;

Professor Jos Adriano 43


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_11
Crie um procedure PL-SQL que permita fazer a remoo de dados
na tabela de Empregados

Objectivo: Remoo de dados via Pl-Sql

Create or replace procedure Trab_11 (empid in number) As


registo_emp1 emp%rowtype;
Numero emp.empno%type;

BEGIN
Numero := empid;
Select * into registo_emp1
from emp
where emp.empno= numero;

DELETE FROM emp


WHERE empno = numero;
htp.p(' Empregado: ' || registo_emp1.empno || ', ' ||
registo_emp1.ename || ', ' || ' has been
deleted. ' );

EXCEPTION
WHEN NO_DATA_FOUND THEN
htp.p(' Employee ID: ' || registo_emp1.empno || ' not found' );
END;

-------
Begin
Trab_11(:empid);
End;

Professor Jos Adriano 44


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_12
Crie um procedure PL-SQL que permita fazer a Alterao de dados
na tabela de Departamentos

Objectivo: Alterao de dados via Pl-Sql

Create or replace procedure trab_12(depname in varchar2, deploc in varchar2,


depnum in number) as

begin

update dept
set dept.dname = depname,
dept.loc = deploc
where dept.deptno = Depnum;
htp.p (' Este Departamento foi alterado ' );

exception
when no_data_found then
htp.p (' Este Departamento no existe ' );
end;

-------
begin
trab_12(:depname, :deploc, :depnum);
end;

Professor Jos Adriano 45


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_13
Crie um procedure PL-SQL que permita a utilizao de cursores
variveis REF CURSORESs

Objectivo: Criao de cursores variveis (Ref Cursores)

CREATE OR REPLACE PROCEDURE TRAB_13(num_empregado1 IN NUMBER) AS

TYPE emp_refcur_typ IS REF CURSOR RETURN emp%ROWTYPE;


emp_cursor emp_refcur_typ;

PROCEDURE process_emp_cv (emp_cursor IN emp_refcur_typ) IS


person emp%ROWTYPE;
BEGIN
Htp.p ('Estes so os nomes para o cursor --'||'<br>');
LOOP
FETCH emp_cursor INTO person;
EXIT WHEN emp_cursor%NOTFOUND;
Htp.p (person.ename || ', '|| person.job|| '<br>');
END LOOP;
END;

BEGIN
OPEN emp_cursor FOR
SELECT *
FROM emp
WHERE empno > num_empregado1;
process_emp_cv(emp_cursor);
CLOSE emp_cursor;

OPEN emp_cursor FOR


SELECT *
FROM emp
WHERE ename LIKE 'R%';
process_emp_cv(emp_cursor);
CLOSE emp_cursor;
END;
----------------
BEGIN
TRAB_13(:num_empregado1);
END;
Professor Jos Adriano 46
Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

PL/SQL Collections And Records


Um Record uma estrutura de dados que permite armazenar valores de diferentes
tipos.
Um Array uma estrutura de dados que permite armazenar valores do mesmo tipo.
Em Pl/SQL hexistem 3 diferentes posibilidades de trabalhar com arrays

Associative Array A B C D E [1..5]

Nested Tables A C D [1..N]

VArray A1 A B C D [1..7]

A1. First 1 A1. Last 4 A1.Limite 7

A1.Count 4

A1.EXTEND(1) 5

Arrays associativos, devem ser usados quando temos conhecimento prvio da


dimenso e contedo do array.
Exemplo: Sabemos que os empregados so promovidos 3 vezes na sua carreira e
sabemos priori as respectivas datas de promoo.

Varray (Array variavel), devem ser utilizados quando temos conhecimento prvio
da dimenso do array mas no sabemos qual deber ser o seu contedo, nem
sequer se o mesmo deber ser integralmente preenchido.
Exemplo: Sabemos que os empregados so promovidos 3 vezes na sua carreira,
mas no conhecemos priori quais so as datas das rtespectivas promoes.

Nested Tables, devem ser utilizadas quando no temos conhecimento prvio da


dimenso nem dos conteudos do array.
Exemplo: Sabemos que os empregados podem ser promovidos, mas no sabemos
quantas vezes ao longo das suas carreiras nem sequer as respectivas datas.

Operaes com Arrays


A1.FIRST = 1 A1.LAST = 4
A1.(A1.FIRST) = A A1.(A1.LAST) = D

Professor Jos Adriano 47


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_14
Crie um procedure PL-SQL que permita a utilizao de estruturas de
dados do tipo Record

Objectivo: Criao de estruturas do tipo Record

CREATE OR REPLACE PROCEDURE TRAB_14 (num_empregado2 IN NUMBER, nome IN


VARCHAR2, profissao IN VARCHAR2, gabinete IN NUMBER, edificio IN VARCHAR2) AS

TYPE location_rec IS RECORD


( room_number NUMBER(4),
building VARCHAR2(25) );

TYPE person_rec IS RECORD


( empno emp.empno%TYPE,
ename emp.ename%TYPE,
job emp.job%TYPE,
location location_rec );

person person_rec;

BEGIN

person.empno := num_empregado2;
person.ename := nome;
person.job := profissao;
person.location.room_number := gabinete;
person.location.building := edificio;

htp.p(person.ename || ', ' || person.job);


htp.p( person.location.room_number || '-' ||
person.location.building);
END;

------
begin
trab_14(:num_empregado2, :nome, :profissao, :gabinete, :edificio);
end;

Professor Jos Adriano 48


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_14a
Crie um procedure PL-SQL que permita a transferncia de dados de
um cursor para um record

Objectivo: Passagem de dados de cursores para registos

CREATE OR REPLACE PROCEDURE TRAB_14A AS

TYPE pessoa_rec IS RECORD


( emp_num emp.empno%TYPE,
emp_nome emp.ename%TYPE,
emp_prof emp.job%TYPE,
emp_sal emp.sal%type);

pessoa pessoa_rec;

Cursor Cursor_emp Is
select empno, ename, job, sal
from emp;

BEGIN

open cursor_emp;
loop
fetch cursor_emp into pessoa.emp_num, pessoa.emp_nome, pessoa.emp_prof,
pessoa.emp_sal;
exit when cursor_emp%notfound;

htp.p(pessoa.emp_num || ' - ' || pessoa.emp_nome ||' - ' ||pessoa.emp_prof || '-' ||


pessoa.emp_sal ||'<br>' );
end loop;

END;

---------------
begin
TRAB_14A;
END;

Professor Jos Adriano 49


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_15
Crie um procedure PL-SQL que permita a utilizao de estruturas de
dados do tipo Array .

Objectivo: Criao de estruturas do tipo Array com carregamento fixo dos elementos.

Create or replace procedure Trab_15 As

TYPE job_array IS ARRAY(20) of VARCHAR2(10);


prof job_array;
howmany NUMBER;

BEGIN
prof:= job_array('clerk', 'salesmam', 'manager', 'analyst', 'president');

htp.p(' The number of elements in the array is: ' || prof.COUNT);


htp.p(' The maximum number of elements in the array is: '
|| prof.LIMIT);

IF prof.LIMIT - prof.COUNT >= 1 THEN


prof.EXTEND(1);
prof(6) := 'clerk'; --assignt the value to the element
END IF;

FOR i IN prof.FIRST..prof.LAST LOOP


SELECT COUNT(*) INTO howmany
FROM emp
WHERE job = prof(i);
htp.p('Job ID: ' || RPAD(prof(i), 10) || ' ' ||
'Numbber of employees is: ' || TO_CHAR(howmany));
END LOOP;
htp.p('The number of elements in the array is: ' || prof.COUNT);
END;

--------
Begin
Trab_15;
End;

Professor Jos Adriano 50


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_15a
Crie um procedure PL-SQL que permita a utilizao de estruturas de
dados do tipo VArray.

Objectivo: Criao de estruturas do tipo VArray com carregamento varivel dos


elementos.

Create or replace procedure Trab_15a (num In Number) As

TYPE Nomes_dept IS VARRAY(10) of Dept.deptno%type;


nomes Nomes_dept;
posicao number;
Total NUMBER;
j number :=1;
i number:=1;

BEGIN
nomes:= nomes_dept();

for j in 1..4 loop


nomes.extend(1);
nomes(j):=(num);
HTP.P (nomes(j));
end loop;

htp.p (nomes.count());
htp.p (nomes.first);
htp.p (nomes(nomes.first));
htp.p (nomes.last);
htp.p (nomes(nomes.last));

for i in nomes.first .. nomes.last loop


htp.p( nomes(i));
end loop;

END;
-----------
Begin
Trab_15a (:num);
end;

Professor Jos Adriano 51


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_15b
Carregamento de VARRAY com Campos obtidos a partir de
cursores

Objectivo: Integrao de cursores com arrays

Create or replace procedure Trab_15b As

CURSOR cursor1 IS
SELECT deptno
FROM dept;

dept_rec cursor1%ROWTYPE;

TYPE dept_array IS VARRAY(25) of cursor1%ROWTYPE;


dept_arr dept_array;
howmany NUMBER;
i NUMBER := 1;

BEGIN
dept_arr := dept_array();
OPEN cursor1;
LOOP
FETCH cursor1 INTO dept_rec;
EXIT WHEN cursor1%NOTFOUND;
dept_arr.EXTEND(1);
dept_arr(i) := dept_rec;
i := i + 1;
END LOOP;
CLOSE cursor1;

FOR j IN dept_arr.FIRST..dept_arr.LAST LOOP


Htp.p (dept_arr(j).deptno);
END LOOP;
END;

------------------------
Begin
trab_15b;
END;

Professor Jos Adriano 52


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_15c
Carregamento de VARRAY com registos obtidos a partir de
cursores

Objectivo: Integrao de cursores com arrays

Create or replace procedure Trab_15c As

CURSOR cursor1 IS
SELECT *
FROM dept;

dept_rec cursor1%ROWTYPE;

TYPE dept_array IS VARRAY(25) of cursor1%ROWTYPE;


dept_arr dept_array;
howmany NUMBER;
i NUMBER := 1;

BEGIN
dept_arr := dept_array();
OPEN cursor1;
LOOP
FETCH cursor1 INTO dept_rec;
EXIT WHEN cursor1%NOTFOUND;
dept_arr.EXTEND(1);
dept_arr(i) := dept_rec;
i := i + 1;
END LOOP;
CLOSE cursor1;
FOR j IN dept_arr.FIRST..dept_arr.LAST LOOP
SELECT COUNT(*) INTO howmany
FROM emp
WHERE deptno = dept_arr(j).deptno;

Htp.p ('Job ID: ' || RPAD(dept_arr(j).deptno, 11, ' ') || RPAD(dept_arr(j).loc, 36, ' ') ||
'Number of employees: ' || TO_CHAR(howmany));
END LOOP;
END;
------------------------
Begin
trab_15c;
END;

Professor Jos Adriano 53


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_16
Passagem de parmetros para cursores

Objectivo: Criao de cursores com passagem de parametros

CREATE OR REPLACE PROCEDURE TRAB_16 As

num_empregado emp.empno%TYPE;
data_admissao emp.hiredate%TYPE;
nome emp.ename%TYPE;
profissao emp.job%TYPE;
rowcount NUMBER;
bonusamount NUMBER;
yearsworked NUMBER;

CURSOR cursor1(thismonth NUMBER) IS


SELECT empno, ename, job, hiredate
FROM emp
WHERE EXTRACT(MONTH FROM hiredate) = thismonth;

BEGIN

OPEN cursor1(EXTRACT(MONTH FROM SYSDATE));


Htp.p ('---Today is: ' || TO_CHAR(SYSDATE, 'DL') || '---');
Htp.p ('Employees with yearly bonus amounts: ');

LOOP
FETCH cursor1 INTO num_empregado, nome, profissao, data_admissao;
EXIT WHEN cursor1%NOTFOUND;

yearsworked := ROUND( (MONTHS_BETWEEN(SYSDATE, data_admissao) / 12) );


IF yearsworked > 10 THEN bonusamount := 2000;
ELSIF yearsworked > 8 THEN bonusamount := 1600;
ELSIF yearsworked > 6 THEN bonusamount := 1200;
ELSIF yearsworked > 4 THEN bonusamount := 800;
ELSIF yearsworked > 2 THEN bonusamount := 400;
ELSIF yearsworked > 0 THEN bonusamount := 100;
END IF;

-- display data for each record (row) fetched

Professor Jos Adriano 54


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Htp.p (num_empregado || ' ' || RPAD(nome, 21) || RPAD(profissao, 26) ||


data_admissao || TO_CHAR(bonusamount, '$9,999') );
END LOOP;

rowcount := cursor1%ROWCOUNT;
htp.p ('The number of rows fetched is: ' || rowcount);
CLOSE cursor1;
END;

---------------------------------
BEGIN
trab_16;
END;

Professor Jos Adriano 55


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_16a
Re-escreva o procedure Trab_16 de forma a que o parmetro do
cursor passe a ser um ms qualquer, em deterimento do ms
actual, e apresente apenas a 1 linha do cursor1

Objectivo: Criao de cursores com passagem de parametros

CREATE OR REPLACE PROCEDURE TRAB_16a (mes In NUMBER) As

num_empregado emp.empno%TYPE;
data_admissao emp.hiredate%TYPE;
nome emp.ename%TYPE;
profissao emp.job%TYPE;
rowcount NUMBER;
bonusamount NUMBER;
yearsworked NUMBER;
outro_mes NUMBER;
Contador Number;

CURSOR cursor1(outro_mes NUMBER) IS


SELECT empno, ename, job, hiredate
FROM emp
WHERE EXTRACT(MONTH FROM hiredate) = outro_mes;

BEGIN
Outro_mes := mes;

OPEN cursor1(EXTRACT(MONTH FROM SYSDATE));


Htp.p ('---Today is: ' || TO_CHAR(SYSDATE, 'DL') || '---');
Htp.p ('Employees with yearly bonus amounts: ');

FOR contador IN 1..1 LOOP


FETCH cursor1 INTO num_empregado, nome, profissao, data_admissao;
EXIT WHEN cursor1%NOTFOUND;

yearsworked := ROUND( (MONTHS_BETWEEN(SYSDATE, data_admissao) / 12) );


IF yearsworked > 10 THEN bonusamount := 2000;
ELSIF yearsworked > 8 THEN bonusamount := 1600;
ELSIF yearsworked > 6 THEN bonusamount := 1200;
ELSIF yearsworked > 4 THEN bonusamount := 800;
ELSIF yearsworked > 2 THEN bonusamount := 400;
ELSIF yearsworked > 0 THEN bonusamount := 100;
END IF;

Professor Jos Adriano 56


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

-- display data for each record (row) fetched


Htp.p (num_empregado || ' ' || RPAD(nome, 21) || RPAD(profissao, 26) ||
data_admissao || TO_CHAR(bonusamount, '$9,999') );
END LOOP;

rowcount := cursor1%ROWCOUNT;
htp.p ('The number of rows fetched is: ' || rowcount);
CLOSE cursor1;
END;

-------------------
BEGIN
TRAB_16a (:mes);
END;

Professor Jos Adriano 57


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_17
Utilizao do tipo %ROWTYPE com cursores

Objectivo: Criao de variveis associadas a cursores

CREATE OR REPLACE PROCEDURE trab_17 (num_departamento IN NUMBER) As

CURSOR cursor1 IS
SELECT *
FROM emp
WHERE deptno = num_departamento;

employee_rec cursor1%rowtype;

BEGIN

OPEN cursor1;
LOOP
FETCH cursor1 INTO employee_rec;
EXIT WHEN cursor1%NOTFOUND;

Htp.p (' Department: ' || employee_rec.deptno|| ', Employee ID: ' ||


employee_rec.empno|| ' - ' || employee_rec.ename || ', ' || employee_rec.job);
END LOOP;
CLOSE cursor1;
END

--------------
begin
trab_17 (:num_departamento);
end;

Professor Jos Adriano 58


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_18

Construo de Procedimentos com alterao de dados na tabela

Objectivo: Integrao de consultas com alterao de dados

CREATE OR REPLACE PROCEDURE Trab_19 (emp_id IN NUMBER, bonus_rate IN


NUMBER) AS

emp_comissao emp.comm%TYPE;
emp_sal emp.sal%TYPE;
salary_missing EXCEPTION;

BEGIN

SELECT sal, comm INTO emp_sal, emp_comissao FROM emp


WHERE empno = emp_id;

IF emp_sal IS NULL THEN


RAISE salary_missing;
ELSE
IF emp_comissao IS NULL THEN
UPDATE emp SET sal = sal + sal * bonus_rate
WHERE empno = emp_id;
Htp.p ('Empregado ' || emp_id || ' Recebeu de Bonus: '||
TO_CHAR(emp_sal*bonus_rate) );
ELSE
Htp.p ('Empregado ' || emp_id || ' Nao recebeu bonus, portou-se mal. ' );
END IF;
END IF;

EXCEPTION
WHEN salary_missing THEN
Htp.p ('Emp ' || emp_id || ' nao tem salario');
WHEN OTHERS THEN
NULL;
END;

Professor Jos Adriano 59


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Trs formas diferentes de chamar o procedimento.


--------

BEGIN
Trab_19 (7902, 0.05);
END;

---------

DECLARE
emp_id NUMBER(4);

BEGIN
Trab_19 (:emp_id, 0.5);
END;

----------

BEGIN
Trab_19 (emp_id=>7902, bonus_rate=>0.05);
END;

Professor Jos Adriano 60


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

TRAB_19

Construo de um Package PL/SQL

Objectivo: Construo de Packages

CREATE OR REPLACE PACKAGE emp_actions AS

PROCEDURE Insere
(numero Number, nome VARCHAR2, prof VARCHAR2);

PROCEDURE remove_emp (empid NUMBER);

FUNCTION emp_sal_ranking (empid NUMBER) RETURN NUMBER;

END emp_actions;

Professor Jos Adriano 61


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Create a Package Body

CREATE OR REPLACE PACKAGE BODY emp_actions AS

PROCEDURE Insere
(numero Number, nome VARCHAR2, prof VARCHAR2) AS
BEGIN
INSERT INTO emp (empno, ename, job)
VALUES (numero, nome, prof);
END Insere;

PROCEDURE Remove_Emp (empid NUMBER) IS


nome emp.ename%TYPE;
prof emp.job%TYPE;
BEGIN
SELECT ename, job INTO nome, prof FROM emp
WHERE empno = empid;
DELETE FROM emp
WHERE empno = empid;
Htp.p(' Empregado: ' || TO_CHAR(empid) || ', ' || nome || ', ' || prof||
' has been deleted. ' );

EXCEPTION
WHEN NO_DATA_FOUND THEN
Htp.p (' Employee ID: ' || TO_CHAR(empid) || ' not found' );
END Remove_Emp;

FUNCTION emp_sal_ranking (empid NUMBER) RETURN NUMBER IS


minsal emp.sal%TYPE;
maxsal emp.sal%TYPE;
prof emp.job%TYPE;
salario emp.sal%TYPE;
BEGIN
SELECT job, sal INTO prof, salario FROM emp
WHERE empno = empid;
SELECT MIN(sal), MAX(sal) INTO minsal, maxsal FROM emp
WHERE job = prof;
RETURN ((salario - minsal) / (maxsal-minsal));
END emp_sal_ranking;

END emp_actions;
Professor Jos Adriano 62
Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt
Base de Dados ORACLE
Pl-SQL Exerccio das aulas

Chamada do Package

DECLARE
empid NUMBER;

BEGIN
empid := :empid;
htp.p ('The salary ranking for employee ' || empid
|| ' IS: ' || ROUND(emp_actions.emp_sal_ranking(empid), 2));
Emp_actions.Insere (:numero, :nome, :prof);
Emp_actions.Remove_emp (:empid);
END;

Professor Jos Adriano 63


Escola Superior de Tecnologia e de Gesto de Bragana
Adriano@ipb.pt

Você também pode gostar