Tema PL SQL 2022 Pag01 A 15
Tema PL SQL 2022 Pag01 A 15
• Declarações
Variáveis e constantes devem ser declaradas antes que possam ser referenciadas em outras instruções,
incluindo outras declarações declarativas. Exemplos de declarações:
vStaffNo VARCHAR2(5);
vRent NUMBER (6, 2) NOT NULL := 600;
MAX_PROPERTIES CONSTANT NUMBER := 100;
Também é possível declarar uma variável para ser do mesmo tipo que uma coluna numa tabela
especificada ou outra variável usando o atributo%TYPE:
vStaffNo Staff.staffNo%TYPE;
Da mesma forma, podemos declarar que uma variável é do mesmo tipo que uma linha inteira de uma
tabela ou vista, usando o atributo%ROWTYPE. Nesse caso, os campos no registo obtêm seus nomes e tipos
de dados das colunas na tabela ou vista:
vStaffRec Staff%ROWTYPE;
%TYPE e %ROWTYPE não são SQL standard.
• Atribuições
Na parte executável de um bloco PL/SQL, as variáveis podem ser atribuídas de duas maneiras: usando
a instrução de atribuição normal (:=) ou como o resultado de uma instrução SQL, SELECT ou FETCH.
Exemplos:
vStaffNo := ‘SG14’;
vRent := 500;
SELECT COUNT (*) INTO x FROM PropertyForRent WHERE staffNo = vStaffNo;
No terceiro caso, a variável x é definida como o resultado da instrução SELECT (nesse caso, igual ao
número de propriedades geridas pelo membro do staff SG14).
Observe que, no SQL standard, uma atribuição usa a palavra-chave SET no início da linha com o
símbolo “=”, em vez do “: =”. Por exemplo:
SET vStaffNo = ‘SG14’
• Instruções de CONTROL
O PL/SQL suporta os mecanismos habituais de fluxo de controle condicional, iterativo e sequencial:
• Instrução condicional IF
• Instrução condicional CASE
• Instrução iteração (LOOP)
• Instrução iteração (WHILE e REPEAT)
• Instrução iteração (FOR)
• Excepções em PL/SQL
Uma excepção é um identificador em PL/SQL criado durante a execução de um bloco que finaliza
seu corpo principal de acções. Um bloco sempre termina quando uma excepção é gerada, embora o
manipulador de excepções possa executar algumas acções finais. Uma excepção pode ser levantada
automaticamente pelo Oracle - por exemplo, a excepção NO_DATA_FOUND é levantada sempre que
nenhuma linha é recuperada da base de dados numa instrução SELECT. Também é possível que uma
excepção seja levantada explicitamente usando a instrução RAISE. Para lidar com excepções levantadas,
são especificadas rotinas separadas denominadas manipuladores de excepção (handlers).
Uma excepção definida pelo utilizador é definida na parte declarativa de um bloco PL/SQL. Na parte
executável, uma verificação é feita para a condição de excepção e, se encontrada, a excepção é gerada. O
manipulador de excepções propriamente dito é definido no final do bloco PL/SQL.
Sintaxe:
DECLARE
past_due EXCEPTION;
BEGIN
... ...
IF ... THEN
RAISE past_due; - esse não é tratado
END IF;
...
EXCEPTION
WHEN past_due THEN - não suporta excepções
HANDLE
...
WHEN OTHERS THEN
...
END;
• Excepções Predefinidas
– DUP_VAL_ON_INDEX – valor de índice duplicado
– LOGIN_DENIED – ocorre na tentativa de conexão com o BD com um utilizador/senha
inválido
– INVALID_NUMBER – ocorre na tentativa de converter uma string para um número, quando
a string não representa um número válido
– NO_DATA_FOUND – comando SELECT/INTO não retornou linha alguma
– TOO_MANY_ROWS – comando SELECT/INTO retornou mais de uma linha
– TIMEOUT_ON_RESOURCE – ocorre quando acontecer um timeout enquanto aguarda-se
um recurso
– NO_LOGGED_ON – ocorre na tentativa de acessar a base de dados sem que se esteja
conectado a ele
– OTHERS “Espera uma mensagem de erro” – trata outros erros, usando as funções
SQL_CODE (número do erro) e
SQLERRM (texto do erro)
Exemplo:
DECLARE
nome_nulo EXCEPTION; *criação da exception*
PRAGMA EXCEPTION_INIT (nome_nulo, -1400); *relaciona o número do erro com a exception*
BEGIN
…
RAISE_APPLICATION_ERROR (-1400,’Nome nulo’); *provoca o erro, mostrando a
mensagem e o erro*
…
EXCEPTION
when nome_nulo then
…; *tratamento do erro*
when others then
…;
END;
• Cursores em PL/SQL
Uma instrução SELECT pode ser usada se a consulta retornar uma e apenas uma linha. Para manipular
uma consulta que possa retornar um número arbitrário de linhas (ou seja, zero, uma ou mais linhas), o
PL/SQL usa cursores para permitir que as linhas de um resultado da consulta sejam acessadas uma de cada
vez. Com efeito, o cursor actua como um ponteiro para uma linha específica da consulta resultado. O cursor
pode ser avançado por 1 para acessar a próxima linha. Um cursor deve ser declarado e aberto antes de poder
ser usado, e deve ser fechado para desativá-lo depois que ele não for mais necessário. Depois que o cursor
for aberto, as linhas da consulta resultado podem ser recuperadas uma de cada vez, usando uma instrução
FETCH, ao contrário de uma instrução SELECT.
O SQL também pode ser incorporado em linguagens de programação de alto nível e os cursores
também são usados para tratar consultas que podem retornar um número arbitrário de linhas.
Sintaxe:
CURSOR cursor_name [(parameter[, parameter]...)] IS select_statement;
Exemplo I
DECLARE
my_sal emp.sal%TYPE;
factor INTEGER :=2;
CURSOR c1(p_Job varchar2) IS
SELECT factor*sal
FROM emp
WHERE job=p_Job;
BEGIN
...
OPEN c1(‘ANALISTA’);
LOOP
FETCH c1 INTO my_sal;
EXIT WHEN c1%NOT FOUND;
...
END LOOP;
CLOSE c1;
END;
Exemplo II
DECLARE
Cursor c_cliente IS
Select * from Clientes order by Nome_Cli;
PROCEDURE
REPLACE - indica que caso a procedure exista ela será eliminada e substituída pela nova versão criada
pelo comando;
nome_procedure indica o nome da procedure
argumento, parâmetro da procedure
IN, indica que deve especificar o valor deste parâmetro na chamada da procedure
OUT, indica que a procedure irá retornar um valor para este parâmetro
IN OUT, através deste parâmetro deve-se especificar um valor para a procedure e este voltará
modificado
Datatype, tipo de dado do parâmetro
IS | AS, é onde se faz a declaração das variáveis ou constantes locais
BEGIN comandos END é o bloco PL/SQL, indica as acções que serão executadas por aquela procedure.
Exemplo:
CREATE OR REPLACE PROCEDURE AlimentaHistorico (ultima_turma IN NUMBER, ultimo_aluno
IN NUMBER)
IS
BEGIN
DELETE historico; /*comentario: elimina registos actuais*/
FOR i IN 1.. ultima_turma LOOP
FOR j IN 1 .. ultimo_aluno LOOP
INSERT INTO historico (cod_turma, matricula) VALUES (i, j);
END LOOP;
END LOOP;
COMMIT;
END;
/
A rotina tem 2 parâmetros de entrada.
SELECT object_name
FROM user_objects
WHERE object_type = ‘PROCEDURE’;
– Para verificar o estado da procedure através de uma simples consulta:
Durante a criação da procedure pode ocorrer algum erro. Nesse caso será mostrada uma mensagem
semelhante a esta:
Aviso: Procedimento criado com erros de compilação
Ou
MGR-00072: Warning: Procedure alimentahistorico created with compilation errors
Nesse caso o erro pode ser verificado através do SHOW ERROR que lista a linha/coluna onde o erro
ocorreu.
O comando SHOW ERROR sem parâmetros adicionais mostra os erros da última compilação.
Por exemplo:
SHOW ERROR alimentahistorico
Ou
SHOW ERROR PROCEDURE alimentahistorico
Ou
SHOW ERROR
FUNCTIONS
Para criar uma function no SQL*Plus:
Ou
BEGIN
<seccao_de_execucao>
[EXCEPTION
<tratamento_de_excepcoes>]
END [<nome_da_funcao>];
• Exemplo:
CREATE OR REPLACE FUNCTION ValorEmDolar (meticais IN NUMBER, cotacao IN
NUMBER)
RETURN NUMBER
IS
BEGIN
RETURN meticais/cotacao;
END;
• Uma função pode ser activada a partir de um comando SQL do tipo DML nas cláusulas WHERE,
HAVING, ORDER BY, GROUP BY em SELECT; VALUES em INSERT; SET em UPDATE e
WHERE em DELETE. Nestes casos a função não pode ter comandos SQL.
• Apagar uma função
DROP FUNCTION nome_funçao;
Para executar:
– Exec Retorna_Info_Curso (40)
– Exec Retorna_Info_Curso (32)
– Exec Retorna_Info_Curso (99)
Analise os resultados
• Crie uma procedure para inserir um instrutor. Use sequência para gerar o código
do instrutor.
DROP SEQUENCE Gera_Cod_instrutor;
CREATE SEQUENCE Gera_Cod_instrutor start with 50;
• Criar uma função que retorne informação de um curso. Use exception para
controlar os erros.
exception
when no_data_found then
return ('Nenhum curso possui carga horária especificada');
when too_many_rows then
return ('Muitos cursos possuem carga horária especificada');
when others then
msg := 'Erro desconhecido: ' || to_char(sqlcode);
return (msg);
end;