Você está na página 1de 49

Linguagem Procedural de

Banco de Dados
PL/SQL
7. Procedures
• Stored Procedure ou simplesmente procedure,
é um algoritmo independente que pode ser
chamado por qualquer aplicação;
• Stored Procedure são armazenadas no SGBD
(no servidor);
• Stored Procedure trocam informações com a
aplicação através de parâmetros;
• Stored Procedure são executadas quando
chamado por uma aplicação;
• Stored Procedure são executadas pelo servidor.
7. Procedures
• Procedures PL/SQL comportam-se muito
semelhantemente aos procedures em outras
linguagens de programação.
• Aqui está um exemplo de um procedure
PL/SQL addtupla1 que, dado um inteiro i,
insere a tupla (i, 'xxx') dentro da relação T2:
CREATE TABLE T2 (
a INTEGER,
b CHAR(10)
);

CREATE OR REPLACE PROCEDURE addtupla1 (i IN NUMBER) AS


BEGIN
INSERT INTO T2 VALUES(i, 'xxx');
END;
/

EXEC addtupla1(1);
7. Procedures
• Sintaxe
CREATE [OR REPLACE] PROCEDURE procedure_name
[(argument [{IN | OUT | IN OUT}] type,
...
argument [{IN | OUT | IN OUT}] type)] {IS | AS}
procedure body
• Cláusulas
• procedure_name - nome do procedimento a ser criado.
• or replace - se já existir um procedimento com esse nome
este será derrubado para que o novo procedimento possa
ser criado.
• argument - são os parâmetros de entrada e saída que
podem ser usados pelo procedimento.
7. Procedures
• Uma procedure é introduzida pelas palavras-
reservadas CREATE PROCEDURE seguidas por
um nome de procedimento e seus
parâmetros.
• Uma alternativa é seguir o comando CREATE
por OR REPLACE.
• A vantagem de fazer assim é que se você já
tiver feito a definição, você não obterá um
erro. Por outro lado, se a definição anterior for
um procedure diferente com o mesmo nome,
você não será alertado, e a procedure antiga
será perdida.
7. Procedures
• Podem existir quaisquer número de
parâmetros, cada um seguido por um modo e
um tipo.

• Os modos possíveis são:


• IN (somente leitura)
• OUT (somente escrita)
• IN OUT (leitura e escrita)
7. Procedures
• Nota
• Diferente do especificador de tipo em uma
declaração de variável PL/SQL, o
especificador de tipo em uma declaração de
parâmetro não deve ter restrições.
• Por exemplo, CHAR(10) e VARCHAR(20) são
ilegais;
• CHAR ou VARCHAR devem ser usadas em
seus lugares.
• O tamanho real de um parâmetro depende
do argumento correspondente que é
passado quando a procedure é invocada.
7. Procedures
• Seguindo os argumentos está a palavra
reservada AS (IS é um sinônimo).

• Então vem o corpo, que é essencialmente um


bloco PL/SQL.

• Repare que a declaração de variáveis é feita


dentro do bloco AS e não do bloco DECLARE.
... AS
<local_var_declarations>
BEGIN
<procedure_body>
END;
/
7. Procedures
• Para executar uma procedure, devemos utilizar
a instrução EXEC precedida pelo nome da
procedure com os seus respectivos
argumentos.
EXEC addtupla1(2);

• Ou utilizar uma outra instrução PL/SQL, na


qual a procedure é invocada como uma
instrução executável.
BEGIN
addtupla1(3);
END;
/
7. Procedures
• A procedure a seguir também insere uma tupla
em T2, mas ele toma ambos os componentes
como argumentos:
CREATE OR REPLACE PROCEDURE addtupla2( x T2.a%TYPE, y T2.b%TYPE)
AS
BEGIN
INSERT INTO T2(a, b) values (x, y);
END;
/

• Agora para adicionar uma tupla (99, ‘abc’) a


T2:
BEGIN
addtupla2(10, ‘abc’);
END;
/
-- OU
EXEC addtupla2(10, ‘abc’);
7. Procedures
• O código a seguir ilustra o uso de um
parâmetro OUT:
CREATE TABLE T3 (
a INTEGER,
b INTEGER
);

CREATE PROCEDURE addtupla3(a NUMBER, b OUT NUMBER) AS


BEGIN
b := 4;
INSERT INTO T3 VALUES(a, b);
END;
/
--------------------------------------------------------------
DECLARE
v NUMBER;
BEGIN
addtupla3(10, v);
DBMS_OUTPUT.PUT_LINE('Valor da variavel de saida: ' || v);
END;
/
7. Procedures
• Note que atribuir valores para parâmetros
declarados como OUT ou INOUT faz com que
os argumentos de entrada correspondentes
sejam escritos.
• Devido a isso, o argumento de entrada para
um parâmetro OUT ou INOUT deve ser alguma
coisa com um "value", tal como uma variável
como v no exemplo anterior.
• Uma constante ou um argumento literal não
deve ser passado para um parâmetro OUT ou
INOUT.
7. Procedures
• Para descobrir quais procedures e funções
você criou, use a seguinte consulta SQL:
SELECT
object_type,
object_name
FROM
user_objects
WHERE
object_type = 'PROCEDURE'
OR object_type = 'FUNCTION';

• Para excluir uma stored procedure / function:


drop procedure <procedure_name >;
drop function <function_name>;
7. Procedures (Exercício)
• Exercício 1
• Procedimento para leitura dos dados em uma
tabela.
Tabela: PESSOA ( cod NUMERICO, nome TEXTO)
Parâmetros:
Entrada: codigo NUMERICO
Saída: pessoa TEXTO
7. Procedures (Exercício)
CREATE TABLE PESSOA (
COD NUMBER(2),
NOME VARCHAR2(10)
);

INSERT INTO PESSOA VALUES (1, 'ANA');


INSERT INTO PESSOA VALUES (2, 'BIA');
INSERT INTO PESSOA VALUES (3, 'MARA');
COMMIT;
7. Procedures (Exercício)
• Exercício 2
• Procedimento para atualização dos dados em uma
tabela.

Tabela: PESSOA ( cod NUMERICO, nome TEXTO)


Parâmetros:
Entrada: codigo NUMERICO, nome TEXTO
7. Procedures (Exercício)
CREATE TABLE PESSOA (
COD NUMBER(2),
NOME VARCHAR2(10)
);

INSERT INTO PESSOA VALUES (1, 'ANA');


INSERT INTO PESSOA VALUES (2, 'BIA');
INSERT INTO PESSOA VALUES (3, 'MARA');
COMMIT;
7. Procedures (Exercício)
• Exercício 3
• Construir um procedimento para ser processado
no servidor e chamado por um aplicativo, com o
objetivo de calcular o desconto de uma venda
realizada, obtendo o percentual de desconto em
uma tabela de descontos.

Tabela: DESCONTO ( cod_produto NUMERICO, perc_desconto NUMERICO)


Parâmetros:
Entrada: cod_prod NUMERICO, valor_venda NUMERICO
Saída: novo_valor_venda NUMERICO
7. Procedures (Exercício)
CREATE TABLE DESCONTO (
cod_produto NUMBER PRIMARY KEY,
perc_desconto NUMBER
);

INSERT INTO DESCONTO VALUES (101, 10);


INSERT INTO DESCONTO VALUES (102, 15);
COMMIT;
7. Procedures (Exercício)
• Exercício 4
• Construir um procedimento para ser processado
no servidor e chamado por um aplicativo, com o
objetivo de atualizar o estoque de um produto
para uma venda.

Tabela: PRODUTO ( cod NUMERICO, nome TEXTO, qtd NUMERICO,


preco_unitario NUMERICO , local_fab TEXTO)
Parâmetros:
Entrada: cod_prod NUMERICO, quant_vendida NUMERICO
Saída: status TEXTO
7. Procedures (exemplo)
CREATE TABLE PRODUTO (
cod NUMBER PRIMARY KEY,
nome VARCHAR2(50),
qtd NUMBER,
preco_unitario NUMBER,
local_fab VARCHAR2(50)
);

INSERT INTO PRODUTO VALUES (1001, 'Carteira de couro', 3, 15.00, 'Ch


ina');
COMMIT;
8. Triggers
• É um procedimento associado a uma operação
e a uma tabela;

• Entra em ação automaticamente quando a


operação é feita por uma aplicação ou pelo
usuário via SQL.

• É executado no servidor e armazenado no


SGBD;

• Não troca informações naturalmente com a


aplicação;
8. Triggers
• É um procedimento associado a uma operação
e a uma tabela;

• Entra em ação automaticamente quando a


operação é feita por uma aplicação ou pelo
usuário via SQL.

• É executado no servidor e armazenado no


SGBD;

• Não troca informações naturalmente com a


aplicação;
8. Triggers
• Triggers são construções especiais do PL/SQL
similares a procedures.

• Contudo, um procedure é executada


explicitamente de um outro bloco via uma
chamada de procedimento, enquanto um
trigger é executado implicitamente sempre
que um evento engatilhado acontece.

• O evento engatilhado é um comando de


INSERT, DELETE ou UPDATE.
8. Triggers
• Abaixo está a sintaxe para a criação de um
trigger no Oracle:

CREATE [OR REPLACE]TRIGGER <trigger_name>


{BEFORE|AFTER} {INSERT|DELETE|UPDATE}
ON <table_name>
[FOR EACH ROW
[WHEN (<trigger_condition>)]
]
<trigger_body>
8. Triggers
• Podemos apenas criar triggers BEFORE e
AFTER para tabelas.

• Devemos especificar até três eventos


engatilhados usando a palavra OR.

• Além disso, UPDATE pode ser opcionalmente


seguido pela palavra-reservada OF e a lista de
atributos em <table_name>.
8. Triggers
• Se presente, a cláusula OF define que o evento
será apenas uma atualização dos atributos
listados depois de OF.

• Alguns exemplos:
• ... INSERT ON R ...
• ... INSERT OR DELETE OR UPDATE ON R ...
• ... UPDATE OF A, B OR INSERT ON R ...
8. Triggers
• Se FOR EACH ROW for especificado, o trigger é
row-level;
• Do contrário, o trigger será statement-level.
• Para um trigger row-level, uma restrição pode
ser especificada na cláusula WHEN, envolvida
por parênteses.
• A restrição do trigger é uma condição SQL que
deve ser satisfeita para que o Oracle dispare o
trigger. Esta condição não pode conter
subconsultas.
• Sem a cláusula WHEN, um trigger é disparado
por todo evento engatilhado.
8. Triggers
• <trigger_body> é um bloco PL/SQL, e não uma
sequência de instruções SQL.

• A Oracle colocou certas restrições no que você


pode fazer em <trigger_body>, a fim de evitar
situações onde um trigger efetua uma ação
que dispara um segundo trigger, que então
dispararia um terceiro, e assim em diante, o
que poderia potencialmente criar um laço
infinito.
8. Triggers
• As restrições em um <trigger_body> inclui:
– Você não pode modificar a mesma relação
cuja modificação gerou o evento que
disparou o trigger.
– Você não pode modificar uma relação
conectada à relação que está "sofrendo" o
trigger por uma outra restrição tal como
uma restrição de chave estrangeira.
8. Triggers
• Sintaxe do Oracle para criação de um trigger
através de um exemplo baseado nas duas
tabelas a seguir:
CREATE TABLE T4 (
a INTEGER,
b CHAR(10)
);

CREATE TABLE T5 (
c CHAR(10),
d INTEGER
);
8. Triggers
• Criamos um trigger que deve inserir uma tupla
em T5 quando uma tupla for inserida em T4.
• Especificamente, o trigger checa se a nova
tupla tem um primeiro componente menor ou
igual a 10, e se sim insere a tupla oposta em
T5:
CREATE TRIGGER trig1
AFTER INSERT ON T4
FOR EACH ROW
WHEN (NEW.a <= 10)
BEGIN
INSERT INTO T5 VALUES(:NEW.b, :NEW.a);
END;
/
8. Triggers
• As variáveis especiais NEW e OLD estão
disponíveis para fazerem referência às tuplas
nova e velha respectivamente.
• No corpo do trigger, NEW e OLD deve ser
precedidas pelo caractere dois pontos (":"),
mas na cláusula WHEN, elas não tem um dois
pontos precedendo- as!
• Executar a instrução CREATE TRIGGER apenas
cria o trigger mas não o executa.
• Apenas um evento engatilhado, tal como uma
inserção em T4 neste exemplo, faz com que o
trigger seja disparado.
8. Triggers
• Para ver informações sobre triggers, utilize as
consultas abaixo:
SELECT trigger_name FROM user_triggers;

SELECT trigger_type, table_name, triggering_event FROM user_triggers


WHERE trigger_name = '<trigger_name>';

• Para apagar uma trigger:


DROP trigger <trigger_name>;

• Para desabilitar ou habilitar uma trigger:


ALTER TRIGGER <trigger_name> {DISABLE|ENABLE};
8. Triggers
• Para ver informações sobre triggers, utilize as
consultas abaixo:
SELECT trigger_name FROM user_triggers;

SELECT trigger_type, table_name, triggering_event FROM user_triggers


WHERE trigger_name = '<trigger_name>';

• Para apagar uma trigger:


DROP trigger <trigger_name>;

• Para desabilitar ou habilitar uma trigger:


ALTER TRIGGER <trigger_name> {DISABLE|ENABLE};
8. Triggers (Exercício)
• Exercício 1
• Criar um procedimento que seja ativado
automaticamente quando uma operação de
delete ocorrer na tabela EMPREGADO.
• Esse procedimento deverá registrar em uma tabela
HIST_EMPREGADO o usuário que está executando
a operação e a data.
Tabelas:
Empregado (matric NUMERICO, nome TEXTO,
salario NUMERICO, dept NUMERICO);

Hist_Empregado (usuario TEXTO, data_delecao DATA);


8. Triggers (exemplo)
CREATE TABLE Empregado (
matric NUMBER,
nome VARCHAR2(50),
salario NUMBER,
dept NUMBER);

CREATE TABLE Hist_Empregado (


usuario VARCHAR2(50),
data_delecao DATE);

INSERT INTO EMPREGADO VALUES (1001, 'Carlos', 5000, 10);


INSERT INTO EMPREGADO VALUES (1002, 'Ana Clara', 6000, 15);
INSERT INTO EMPREGADO VALUES (1003, 'Laura', 12000, 20);
COMMIT;
8. Triggers (Exercício)
• Exercício 2
• Criar um procedimento automático que proíba o
cadastramento de empregados com salário maior
que R$ 15.000
8. Triggers (Exercício)
• Exercício 3
• Criar um procedimento automático para registrar
em HIST_VENDA, as operações de DELETE,
INSERT e UPDATE que ocorrerem na tabela
VENDA, registrando o código do cliente, o
produto, a quantidade, o usuário que fez a
operação e o tipo da operação.
Tabelas:
Venda (cod_cli NUMERICO, cod_pro NUMERICO ,
quantidade NUMERICO);

Hist_Venda (cn TEXTO, pn TEXTO, qtd NUMERICO,


usu TEXTO, oper TEXTO);
8. Triggers (exemplo)
CREATE TABLE Venda (
cod_cli NUMBER,
cod_pro NUMBER ,
quantidade NUMBER
);

CREATE TABLE Hist_Venda (


num_cli VARCHAR2(10),
num_prod VARCHAR2(10),
qtd NUMBER,
usu VARCHAR2(15),
oper VARCHAR2(10)
);
8. Triggers (Exercício)
• Exercício 4
• Criar um procedimento automático para registrar
na tabela DELEÇÃO, o usuário, o número de linhas
que ele deletar da tabela ALUNO e a data da
operação.
Dicas:
o Tabela associada ao Trigger: ALUNO.
o Operação que ativa o Trigger: DELETE.
o Momento que o Trigger entra em ação: AFTER.
o Para cada linha que o DELETE atuar: FOR EACH ROW.

Tabelas:
Aluno (matricula NUMERICO , nome TEXTO, codigo_curso TEXTO);
Delecao (usuario TEXTO, qtd NUMERICO, data DATA);
8. Triggers (exemplo)
CREATE TABLE aluno (
matricula NUMBER ,
nome VARCHAR2(20),
codigo_curso VARCHAR2(2));

CREATE TABLE delecao (


usuario VARCHAR2(10),
qtd NUMBER,
data DATE);

INSERT INTO ALUNO VALUES (1001, 'John', '12');


INSERT INTO ALUNO VALUES (1002, 'John', '12');
INSERT INTO ALUNO VALUES (1003, 'John', '12');
INSERT INTO ALUNO VALUES (1004, 'John', '12');
INSERT INTO ALUNO VALUES (1005, 'John', '12');
INSERT INTO ALUNO VALUES (1006, 'John', '12');
INSERT INTO ALUNO VALUES (1007, 'John', '12');
INSERT INTO ALUNO VALUES (1008, 'John', '12');
INSERT INTO ALUNO VALUES (1009, 'John', '12');
INSERT INTO ALUNO VALUES (1010, 'John', '12');
COMMIT;

SELECT * FROM ALUNO;


SELECT * FROM DELECAO;
Trabalho de Casa
Tarefa 1:
Fazer um gatilho na tabela movimento que dispare ao ser inserido
um novo registro na tabela e atualize o saldo da conta corrente do
cliente na tabela conta_corrente.

Para realizar o trabalho crie as tabelas a seguir e popule a tabela de


conta corrente utilizando os comandos do próximo slide:
Trabalho de Casa
Tarefa 1:
CREATE TABLE conta_corrente (
nr NUMBER(6) PRIMARY KEY,
nome VARCHAR2(40),
CPF CHAR(11),
saldo NUMBER(11,2)
);

CREATE TABLE mov_cc (


nr NUMBER(9) PRIMARY KEY,
nr_cc NUMBER(6) REFERENCES conta_corrente(nr),
tipo CHAR(1) NOT NULL,
valor NUMBER(11,2)
);

INSERT INTO conta_corrente VALUES (101,'Carlos Rodrigues','12345678901',1020.45);


INSERT INTO conta_corrente VALUES (111,'Jose Antonio Silva','67890154368',2045);
INSERT INTO conta_corrente VALUES (121,'Carla Santos' ,'45698712345',3120.89);
INSERT INTO conta_corrente VALUES (131,'Roberto Leitão','12345678901',120);
INSERT INTO conta_corrente VALUES (141,'Alberto Cesar','12345678901',2110.20);
INSERT INTO conta_corrente VALUES (151,'Caio Domingues','12345678901',1000);
Trabalho de Casa
Tarefa 2:
Fazer os gatilhos de DELETE e UPDATE para a situação do exercício
anterior.
Trabalho de Casa
Tarefa 3:
Baseando-se na estrutura das tabelas PRODUTO e MOV_PROD faça
um conjunto de gatilhos que mantenha atualizada a quantidade
em estoque do produto na tabela produto ao serem inseridos,
eliminados ou alterados dados na tabela de movimento.

As alterações em MOV_PROD poderão contemplar mais de uma


coluna no mesmo comando.

Os tipos possíveis de movimentos são E ou S representando


Entrada ou Saída de mercadorias respectivamente.

Para realizar o trabalho crie as tabelas a seguir e popule a tabela de


produtos utilizando os comandos do próximo slide:
Trabalho de Casa
Tarefa 3:
CREATE TABLE produto (
cod NUMBER(6) PRIMARY KEY,
nome VARCHAR2(40),
unid CHAR(20),
qtd_estoque NUMBER(12)
);

CREATE TABLE mov_prod (


nr NUMBER(9) PRIMARY KEY,
id_prod NUMBER(6) REFERENCES produto(cod),
tipo CHAR(1) NOT NULL,
qtd NUMBER(11)
);

INSERT INTO produto VALUES(101,'Sabão de Coco','Barra',153);


INSERT INTO produto VALUES(102,'Sabão em Pó','Kg',56);
INSERT INTO produto VALUES(103,'Desinfetante','Lt',89);
INSERT INTO produto VALUES(104,'Detergente','Lt',47);
Trabalho de Casa
Tarefa 4:
Criar uma procedure que deverá receber o código de um cliente e a
partir deste dado retornar o seu nome e seu e‐mail.

Os dados deverão ser obtidos a partir de uma tabela chamada


CLIENTE com as seguintes colunas:
(COD_CLI, NOME_CLI, EMAIL_CLI).

Exemplo:

Parâmetros:
Entrada: codigo NUMERICO
Saída: cliente TEXTO, email TEXTO
Trabalho de Casa
Tarefa 5:
Criar uma procedure que deverá receber o CPF de uma pessoa sem
formatação (apenas números) e a partir deste dado retornar o seu
CPF formatado.

Exemplo:
ENTRADA: 12345678910
SAIDA: 123.456.789-10

Dica:
utilize a função substr.

Parâmetros:
Entrada: cpf_semformat TEXTO
Saída: cpf_comformat TEXTO

Você também pode gostar