Professional Documents
Culture Documents
ÍNDICE
ASSUNTO: PAG
1. CONCEITO....................................................................................................................... 81
2. ESTRUTURA....................................................................................................................81
3. ARQUITETURA................................................................................................................82
4. COMPONENTES DA LINGUAGEM.................................................................................82
IDENTIFICADORES................................................................................................................ 82
PALAVRAS RESERVADAS................................................................................................... 82
LITERAIS................................................................................................................................ 82
COMENTÁRIOS:..................................................................................................................... 83
5. DECLARAÇÕES..............................................................................................................83
TIPOS DE VARIAVEIS............................................................................................................ 83
VARIÁVEIS SIMPLES................................................................................................ 83
ATRIBUTOS ESPECIAIS........................................................................................... 84
PROBLEMA PROPOSTO........................................................................................... 85
RESOLUÇÃO 1:...........................................................................................................85
RESOLUÇÃO 2............................................................................................................86
VARIÁVEIS COMPOSTAS......................................................................................... 86
PROBLEMA PROPOSTO........................................................................................... 88
RESOLUÇÃO:..............................................................................................................88
CONSTANTES........................................................................................................... 88
CONVERSÃO DE TIPO DE VARIÁVEL.................................................................................89
EXEMPLOS DE DECLARAÇÕES.......................................................................................... 89
VARIÁVEIS ESPECIAIS............................................................................................. 89
ATRIBUTOS PARA CURSOR....................................................................................90
PROBLEMA PROPOSTO........................................................................................... 91
RESOLUÇÃO:..............................................................................................................91
6. ATRIBUIÇÕES................................................................................................................. 92
7. FUNÇÕES PRÉ-DEFINIDAS............................................................................................92
CONTROLE DE ERROS......................................................................................................... 92
SQLCODE.................................................................................................................. 92
SQLERRM.................................................................................................................. 92
NUMÉRICAS........................................................................................................................... 93
ABS............................................................................................................................ 93
CEIL............................................................................................................................ 93
COS............................................................................................................................ 93
COSH......................................................................................................................... 93
EXP............................................................................................................................ 93
FLOOR....................................................................................................................... 93
LN............................................................................................................................... 93
LOG............................................................................................................................ 94
MOD........................................................................................................................... 94
POWER...................................................................................................................... 94
ROUND....................................................................................................................... 94
SIGN........................................................................................................................... 94
SIN.............................................................................................................................. 94
SINH........................................................................................................................... 94
SQRT.......................................................................................................................... 94
TAN............................................................................................................................ 95
__________________________________________________________________________________________
__________________________________________________________________________________________
TANH.......................................................................................................................... 95
TRUNC....................................................................................................................... 95
CARACTERES........................................................................................................................ 95
ASCII.......................................................................................................................... 95
CHR............................................................................................................................ 95
CONCAT..................................................................................................................... 95
INITCAP...................................................................................................................... 95
INSTR......................................................................................................................... 95
LENGTH..................................................................................................................... 96
LOWER....................................................................................................................... 96
LPAD.......................................................................................................................... 96
LTRIM......................................................................................................................... 96
REPLACE................................................................................................................... 96
RPAD.......................................................................................................................... 96
RTRIM........................................................................................................................ 96
SOUNDEX.................................................................................................................. 97
SUBSTR..................................................................................................................... 97
TRANSLATE............................................................................................................... 97
UPPER....................................................................................................................... 97
DATAS.................................................................................................................................... 97
ADD_MONTHS........................................................................................................... 97
LAST_DAY................................................................................................................. 97
MONTHS_BETWEEN................................................................................................. 97
NEW_TIME................................................................................................................. 98
NEXT_DAY................................................................................................................. 98
SYSDATE................................................................................................................... 98
ROUND....................................................................................................................... 98
TRUNC....................................................................................................................... 98
CONVERSÃO......................................................................................................................... 99
CHARTOROWID........................................................................................................ 99
HEXTORAW............................................................................................................... 99
RAWTOHEX............................................................................................................... 99
ROWIDTOCHAR........................................................................................................ 99
TO_CHAR................................................................................................................... 99
MISCELÂNEA....................................................................................................................... 100
DECLARE................................................................................................................. 100
GREATEST.............................................................................................................. 101
LEAST...................................................................................................................... 101
NVL........................................................................................................................... 101
UID........................................................................................................................... 101
USER........................................................................................................................ 101
USERENV................................................................................................................ 101
VSIZE....................................................................................................................... 101
PROBLEMA PROPOSTO:........................................................................................ 102
RESOLUÇÃO.............................................................................................................102
8. COMANDOS................................................................................................................... 103
LABELS................................................................................................................................ 103
EXIT....................................................................................................................................... 103
IF THEN ELSE...................................................................................................................... 104
LOOP.................................................................................................................................... 105
PROBLEMA PROPOSTO:........................................................................................ 106
RESOLUÇÃO.............................................................................................................106
WHILE LOOP........................................................................................................................ 107
PROBLEMA PROPOSTO:........................................................................................ 107
RESOLUÇÃO:............................................................................................................107
FOR LOOP............................................................................................................................ 108
GOTO.................................................................................................................................... 109
NULL..................................................................................................................................... 109
__________________________________________________________________________________________
__________________________________________________________________________________________
11. SUBPROGRAMAS.......................................................................................................117
PROCEDURES..................................................................................................................... 118
DECLARAÇÕES FORWARD............................................................................................... 119
STORED SUBPROGRAMS.................................................................................................. 120
CHAMADAS DE UM STORED PROGRAM..............................................................120
CRIANDO UM STORED SUBPROGRAM................................................................120
__________________________________________________________________________________________
__________________________________________________________________________________________
1. CONCEITO
A PL/SQL é uma linguagem procedural do ORACLE, extensão ao SQL. Este capítulo da apostila tem
o objetivo de dar uma visão geral da linguagem e suas potencialidades. Através de exemplos simples
veremos a aplicabilidade da linguagem. No fim do capítulo estão transcritos os principais comandos e
sua sintaxe. Com a PL/SQL pode-se usar comandos SQL para manipular os dados da base
ORACLE e fluxos de controle para processar os dados. Pode-se declarar constantes e variáveis,
definir subprogramas (procedures ou funções) e controlar erros de execução.
2. ESTRUTURA
A PL/SQL é uma estrutura em blocos, ou seja, as unidades básicas (procedures, funções, etc.)
podem conter qualquer número de sub-blocos. Um bloco permite que se façam declarações
associadas ao bloco e que deixam de existir quando o bloco termina.
DECLARE
<declarações> ______________ opcional
BEGIN
<lógica> ___________________ obrigatória
EXCEPTION
<erros> _____________ opcional
END;
A ordem das partes é lógica, ou seja, primeiro deve-se efetuar as declarações, para depois utilizar (na
lógica) as variáveis criadas. As exceções ocorridas durante a execução podem ser resolvidas na
parte referente a erros.
Exemplo:
DECLARE
w_salario NUMBER(5);
BEGIN
SELECT vl_sal INTO w_salario FROM func
WHERE cd_mat = 150
FOR UPDATE OF;
COMMIT;
END;
__________________________________________________________________________________________
81
__________________________________________________________________________________________
3. ARQUITETURA
O módulo executável da PL/SQL pode ser instalado no RDBMS ou em softwares aplicativos tais
como: SQL*REPORT, SQL*FORMS, SQL*MENU. Estes dois ambientes (RDBMS e aplicativos) são
independentes. No ambiente instalado, a PL/SQL aceita como entrada qualquer bloco ou
subprograma escrito na linguagem. Quando a instalação é feita no RDBMS, é possível a inclusão de
rotinas em PL/SQL nos aplicativos das host languages. É possível ainda, a compilação separada de
subprogramas e armazenamento na base de dados ORACLE, que serão lidos a tempo de execução.
Um Subprograma explicitamente criado usando uma ferramenta do ORACLE é chamado de “stored
subprogram”, que uma vez compilado e armazenado no dicionário de dados, poderá ser chamado por
qualquer número de aplicações conectadas à base de dados.
4. COMPONENTES DA LINGUAGEM
IDENTIFICADORES
Consiste de uma letra opcionalmente seguida de números, “$”, ”_” ou “#”. As letras podem ser
minúsculas ou maiúsculas.
PALAVRAS RESERVADAS
Palavras que possuam um significado especial para a SQL.
Ex.: BEGIN
END
LITERAIS
É uma representação explícita de um número, caracter, string ou boleano, não representado por um
identificador.
Ex.:
Numéricos Caracteres Strings Boleanos
030 ‘Z’ ‘10-NOV-91’ TRUE
6 ‘%’ ‘hello,world’ FALSE
-14 ‘7’
+32767 ‘.‘
12.0 ‘.‘
.5 ‘z’
‘2E5 ‘(‘
-9.5E-3
__________________________________________________________________________________________
82
__________________________________________________________________________________________
COMENTÁRIOS:
O início do comentário é marcado por dois hífens em qualquer ponto da linha. O restante da linha é
considerado comentário. Para comentários que ultrapassem uma linha, pode-se usar a notação /*
(inicio) e */(fim).
Ex.:
SELECT vl_sal INTO w_salario – obtêm o salário atual
/* calculo da
bonificação */
IF w_salario > 50000
5. DECLARAÇÕES
TIPOS DE VARIAVEIS
Cada constante ou variável possui um tipo que especifica o formato de armazenamento, restrições e
intervalo de valores. O dado pode ser simples ou composto.
SUBTIPOS – São associados aos tipos com uma restrição, que indiquem um subconjunto de
valores.
VARIÁVEIS SIMPLES
sintaxe: binary_integer
NUMBER numérico, para armazenamento de valores em ponto flutuante com precisão de até 38
dígitos.
sintaxe: long
__________________________________________________________________________________________
83
__________________________________________________________________________________________
sintaxe: date
sintaxe: rowid
formato: BBBBBBBBB.RRRR.FFFF
onde:
BBBBBBBBB - bloco dentro do arquivo (database file)
RRRR - row dentro do bloco ( primeira row é 0)
FFFF - número do arquivo (database file)
ATRIBUTOS ESPECIAIS
As variáveis PL/SQL e constantes possuem atributos, que são propriedades que permitem a
referência ao tipo e estrutura do objeto sem necessidade de repetição de sua definição. As tabelas e
colunas do database possuem atributos similares, que podemos usar para facilitar a manutenção.
%TYPE este atributo copia os atributos de uma variável, constante ou coluna do database. É
particularmente usado quando declaramos variáveis que pertençam as colunas do database.
sintaxe: <variável>/<constante>/<coluna>%TYPE
Ex.:
DECLARE
W_CODIGO NUMBER(3)
W_CODIGO2 W_CODIGO%TYPE; - variável de tipo idêntico a código
W_COD_DEP DEPTO.CD_DEPTO%TYPE
/* variável de tipo idêntico à variável da base de dados cd_depto */
__________________________________________________________________________________________
84
__________________________________________________________________________________________
%ROWTYPE este atributo gera um tipo de registro que representa uma linha da tabela. O registro
pode armazenar uma linha de dados selecionados da tabela ou recebidos de um cursor (fetched).
sintaxe: <tabela>/<cursor>%ROWTYPE
Ex.:
DECLARE
W_DEP_ROW DEPTO%ROWTYPE; - variável do tipo row
W_MAT NUMBER(3);
CURSOR W_C1 Ls - cursor com apenas 2 colunas
SELECT CD_DEPTO,NM_DEPTO
FROM DEPTO; - colunas da tabela
W_C1_ROW WC1%ROWTYPE; - possui as mesmas colunas de
W_C1
BEGIN
PROBLEMA PROPOSTO
Suponhamos a existência de uma tabela (RESULTADO) com o layout (VALOR N (30), ORDEM
N(5)). Deseja-se preenchê-la a partir da tabela funcionário, com a matrícula do funcionário (ordem) e
a expressão trunc(nr_git*vl_sal/nr_cargo) na coluna valor.
RESOLUÇÃO 1:
DECLARE
w_reg_func FUNC%ROWTYPE;
CURSOR w_c1 lS
SELECT * FROM func ORDER BY cd_mat;
BEGIN
OPEN w_c1;
LOOP
FETCH w_c1 INTO w_reg_func;
EXIT WHEN w_c1%NOTFOUND;
INSERT INTO resultado (ordem,valor)
VALUES (w_reg_func.cd_mat,
trunc(w_reg_func.nr_git * w_reg_func.vl_sal / w_reg_func.nr_cargo));
ENDLOOP;
CLOSE w_c1;
END;
__________________________________________________________________________________________
85
__________________________________________________________________________________________
RESOLUÇÃO 2
DECLARE
CURSOR w_c1 lS
SELECT cd_mat, nr_git, vl_sal, nr_cargo FROM func;
w_reg_func w_c1%ROWTYPE;
BEGIN
OPEN w_c1;
LOOP
FETCH w_c1 INTO w_reg_func;
EXIT WHEN w_c1%NOTFOUND;
INSERT INTO resultado (ordem,valor)
VALUES (w_reg_func.cd_mat,
trunc(w_reg_func.nr_git * w_reg_func.vl_sal / w_reg_func.nr_cargo));
END LOOP;
CLOSE w_c1;
END
VARIÁVEIS COMPOSTAS
TABLE - tabelas na PL/SQL podem ter somente uma coluna e uma primary key, nenhuma das
quais nomeadas. A declaração cria um tipo de variável. Deve ser feita uma declaração de variável
com o tipo criado posteriormente para uso.
Ex.:
DECLARE
TYPE tab IS TABLE OF char(10)
INDEX BY BINARY_INTEGER;
teste TAB;
__________________________________________________________________________________________
86
__________________________________________________________________________________________
Ex.:
DECLARE
TYPE registro IS RECORD
(depto CHAR(03) NOT NULL,
nome DEPTO. NM_DEPTO%TYPE);
outro_reg REGISTRO;
reg_teste REGISTRO;
...........
REG_TESTE.DEPTO := ‘A00’;
SELECT cd_depto, nm_depto INTO outro_reg FROM DEPTO
WHERE cd_depto = ‘D11’;
Ex.:
DECLARE
TYPE tab is table of CHAR(2) INDEX BY BINARY_INTEGER;
TYPE registro IS RECORD (a1 TAB, a2 CHAR(1));
teste REGISTRO;
BEGIN
teste.a1 (1) := ‘aa’;
teste.a1 (2) := ‘bb’;
teste.a1 (3) := ‘cc’;
__________________________________________________________________________________________
87
__________________________________________________________________________________________
PROBLEMA PROPOSTO
Deseja-se saber, para cada cargo, a quantidade de funcionários por departamento. O nome do cargo
deve ser apresentado no resultado.
RESOLUÇÃO:
DECLARE
TYPE t_cargo IS TABLE OF char(25)
INDEX BY BINARY_INTEGER;
TYPE t_codigo IS TABLE OF number(3)
INDEX BY BINARY_INTEGER;
cargo T_CARGO;
cod_cargo T_CODIGO;
CURSOR w_c1 IS
SELECT func.cd_depto, nr_cargo, nm_depto, count(*) conta
FROM func, depto
WHERE func.cd_depto = depto.cd_depto
GROUP BY func.cd_depto, nm_depto, nr_cargo;
w_c1_row w_c1%ROWTYPE;
BEGIN
cod_cargo(1) := 42;
cargo(1) := ‘OPERADOR’
cod_cargo(2) := 43;
cargo(2) := ‘DIGITADOR’
.
.
.
OPEN w_c1;
LOOP
FETCH w_c1 INTO w_c1_row;
EXIT WHEN w_c1%NOTFOUND;
FOR i IN 1..12 LOOP
IF cod_cargo(i) =w_c1_row.nr_cargo
THEN
INSERT INTO saida
(valor, texto, qtd)
VALUES
(w_c1_row.cd_depto, to_char(w_c1_row.nr_cargo)ll’ ‘ll
cargo(i),w_c1_row.conta);
EXIT;
END IF;
END LOOP;
END LOOP;
END;
CONSTANTES
A declaração de uma constante é semelhante à declaração de uma variável, exceto que devemos
adicionar a palavra chave CONSTANT e, imediatamente, associar um valor inicial. Seu valor não
poderá ser alterado durante o programa.
Ex.:
DECLARE
W_TESTE CONSTANT REAL := 3.14159;
W_TESTE1 CONSTANT REAL DEFAULT := 3.14159;
__________________________________________________________________________________________
88
__________________________________________________________________________________________
TO_CHAR TO_DATE
TO_VARCHAR2 TO_NUMBER
CHARTOROWID ROWIDTOCHAR
HEXTORAW RAWTOHEX
TO_BINARY_INTEGER
EXEMPLOS DE DECLARAÇÕES
DECLARE
W_DATA DATE; - variável de tipo data
W_CONTADOR SMALLINT := 0; - variável iniciada com zero
W_CODIGO CHAR(O3)NOT NULL := ‘A00’ - variável c/ restrição
W_TESTE CONSTANT REAL := 3.14159; - /* constante de tipo real - o valor
inicial é obrigatório */
W_CODIGO2 W_CODIGO%TYPE := ‘B01’ - variável de tipo idêntico a código
W_COD_DEP DEPTO.CD_DEPTO%TYPE - variável de tipo idêntico a variável da
da base de dados cd_depto
W_DEP_ROW DEPTO%ROWTYPE - variável tipo row
BEGIN
SELECT *
INTO W_DEP_ROW
FROM DEPTO
WHERE cd_depto = ‘A00’;
IF W_DEP_ROW.cd_DEPTO = ‘A00’
THEN
W_CONTADOR := WHERE_CONTADOR + 1;
END IF;
END
VARIÁVEIS ESPECIAIS
Ex.:
DECLARE
erro_matrícula EXCEPTION;
__________________________________________________________________________________________
89
__________________________________________________________________________________________
sintaxe:
CURSOR <nome cursor>[(<parâmetro> <tipo>[,<parâmetro <tipo>...])]
RETURN<tipo>/<variável%TYPE/<table.column>%TYPE/<table>%rowtype
IS <comando SELECT >;
onde:
1. A cláusula RETURN define o tipo de dado do resultado de um cursor.
2. Pode-se usar o atributo %ROWTYPE para representar uma linha em uma tabela da base.
3. Pode-se usar %TYPE para representar o tipo de uma variável, constante ou coluna da
base.
4. Um cursor deve estar associado a um comando SELECT com mesmo número, tipo e
ordem de elementos selecionados que os da cláusula RETURN.
Ex.:
DECLARE
CURSOR w_c1 IS SELECT cd_mat, vl_sal FROM func;
CURSOR w_c2 (dat_ini DATE) IS
SELECT cd_mat, nm_func FROM func
WHERE de_nasc > dat_ini;
%FOUND - indica se o último FETCH retornou uma linha ou não, para cursores explícitos. E se
alguma row foi afetada pelo último comando INSERT, UPDATE ou DELETE para cursores
implícitos.
Ex.:
LOOP
FETCH w_c1 INTO w_c1_row;
IF w_c1%FOUND
THEN
%NOTFOUND - indica se o último FETCH retornou uma row ou não, para cursores explícitos. E se
alguma row foi afetada pelo último comando INSERT, UPDATE ou DELETE para cursores
implícitos.
sintaxe: <cursor>%NOTFOUND
SQL%NOTFOUND
Ex.:
LOOP
FETCH w_c1 INTO w_c1_row;
IF w_c1%NOTFOUND
THEN
EXIT;
...
END LOOP;
__________________________________________________________________________________________
90
__________________________________________________________________________________________
%ISOPEN - permite que se verifique se um cursor está aberto ou não. No caso de cursores
implícitos o resultado será sempre FALSE, uma vez que o Oracle fecha o cursor após uma
operação.
sintaxe: <cursor>%ISOPEN
SQL%ISOPEN
Ex.:
IF NOT (w_c1%ISOPEN)
THEN
...
%ROWCOUNT - indica o número de rows lidas para o cursor associado (para cursores explícitos)
ou o número de rows afetadas no último comando INSERT, UPDATE, DELETE ou SELECT (para
cursores implícitos). Após a abertura do cursor, o valor de ROWCOUNT é zero. O número só será
incrementado SE O ÚLTIMO FETCH retornou uma row.
sintaxe: <cursor>%ROWCOUNT
SQL %ROWCOUNT
Ex.:
LOOP
FETCH w_c1 INTO w_c1_row;
IF w_c1% ROWCOUNT
THEN
...
PROBLEMA PROPOSTO
Deseja-se calcular e emitir a folha de pagamento de uma empresa. Em função da necessidade de se
emitir vários relatórios sobre o cálculo efetuado, será gerada uma tabela intermediária com os
resultados para posterior impressão.
RESOLUÇÃO:
DECLARE
CURSOR w_c1 IS SELECT cd_mat, vl_sal, vl_sal * .10 fgts FROM func;
w_c1_row w_c1 %ROWTYPE;
w_vl_lim NUMBER(15,2) :=&1;
w_vl_ir NUMBER(15,2) := 0;
w_vl_inss NUMBER(15,2) := 0
tabela inválida EXCEPTION;
PROCEDURE ir (val_sal IN NUMBER, val_ir OUT NUMBER) IS
BEGIN
IF val_sal < 300.00 THEN
val_ir := 0;
ELSIF val_sal BETWEEN 300.01 AND 1000.00 THEN
val_ir := val_sal *10;
ELSIF val_sal BETWEEN 1000.01 AND 3000.00 THEN
val_ir := val_sal *20;
ELSE
val_ir := val_sal *30;
END IF;
END;
FUNCTION inss (val_sal IN NUMBER, val_lim IN NUMBER) RETURN NUMBER
IS
val_inss NUMNER(15,2);
__________________________________________________________________________________________
91
__________________________________________________________________________________________
BEGIN
val_inss := val_sal *.08;
IF val_inss := > val_lim THEN
val_inss := val_lim;
END IF;
RETURN val_inss;
END inss;
BEGIN
DELETE FROM folha;
COMMIT;
OPEN w_c1;
LOOP
FETCH w_c1 INTO w_c1_row;
EXIT WHEN w_c1%NOTFOUND;
ir(w_c1_row.vl_sal, w_vl_ir);
w_vl_inss := inss(w_c1_row.vl_sal,w_vl_lim);
INSERT INTO folha (cd_mat, vl_sal, vl_ir, vl_inss, vl_fgts)
VALUES (w_c1_row.cd_mat, w_c1_row.vl_sal, w_vl_ir, w_vl_inss,
w_c1_row.fgts);
END LOOP;
CLOSE w_c1;
COMMIT;
END;
6. ATRIBUIÇÕES
As variáveis e constantes são inicializadas cada vez que é iniciado o bloco em que elas estão
declaradas. Por default, as variáveis são inicializadas com “NULL”. É importante, portanto que as
variáveis antes de serem usadas sejam inicializadas.
Ex.:
sim_não boolean;
...
sim_não := (contador > 500);
7. FUNÇÕES PRÉ-DEFINIDAS
A PL/SQL permite a utilização de diversas funções pré-definidas para manipulação dos dados. Pode-
se usá-las onde expressões do mesmo tipo são permitidas.
CONTROLE DE ERROS
SQLCODE
Função numérica que retorna o código do erro associado à última exceção.
SQLERRM
Função string que retorna a mensagem de erro associado ao último SQLCODE.
__________________________________________________________________________________________
92
__________________________________________________________________________________________
NUMÉRICAS
ABS
Retorna o valor absoluto do argumento.
CEIL
Retorna o menor inteiro maior ou igual ao argumento.
COS
Retorna o coseno do argumento, que deve ser expresso em radianos.
Obs.: se <n> estiver em graus, basta que seja dividido por 57.29578 para ser convertido para
radianos.
COSH
Retorna o coseno hiperbólico do argumento.
EXP
Retorna e elevado à n-esima potência, onde e (~2.71828) é a base do logaritmo neperiano.
FLOOR
Retorna o maior inteiro menor ou igual ao argumento.
LN
Retorna o logaritmo natural do argumento, que deve ser maior que zero.
__________________________________________________________________________________________
93
__________________________________________________________________________________________
LOG
Retorna o logaritmo de <n> na base <m>, sendo que <m> deve ser maior que 1 e <n> deve ser maior
que 1 e <n> deve ser maior que zero.
MOD
Retorna o resto da divisão de <m> por <n>. Se <n> for zero, <m> é retornado.
POWER
Retorna o número <m> elevado à <n>-ésima potência. Se <m> for negativo, <n> deve ser inteiro.
ROUND
Retorna <m> arredondado para <n> casas decimais. Se <n> for omitido, zero será assumido.
SIGN
Retorna –1 se o argumento for negativo, 0 se igual a zero ou 1 se o argumento for maior que zero.
SIN
Retorna o seno de <n>, que deve ser expresso em radianos.
Obs.: Se <n> estiver em graus, basta que seja dividido por 57.29578 para ser convertido para
radianos.
SINH
Retorna o seno hiperbólico do argumento.
SQRT
Retorna a raiz quadrada do argumento, que não pode ser negativo.
__________________________________________________________________________________________
94
__________________________________________________________________________________________
TAN
Retorna a tangente de <n>, que deve ser expresso em radianos.
TANH
Retorna a tangente hiperbólica do argumento.
TRUNC
Retorna o número <m> truncado para <n> casas decimais. Se o <n> for omitido, zero será assumido.
CARACTERES
ASCII
Retorna o código ASCII correspondente à string informada no argumento.
CHR
Retorna a string correspondente à representação numérica informada como argumento. É o contrario
da função ASCII.
CONCAT
Retorna uma string que é o resultado da concatenação de <str1> (na frente) com <str2>.
INITCAP
Retorna a primeira letra de cada palavra do argumento em letra maiúscula e as demais em
minúsculas.
INSTR
Retorna a posição da <n>-ésima ocorrência de <str2> dentro de <str1>, começando na posição
<pos>.
__________________________________________________________________________________________
95
__________________________________________________________________________________________
LENGTH
Retorna o número de caracteres da string <str>. Se o argumento é um item definido como CHAR, o
comprimento incluirá os brancos. Se <str> for null, o resultado da função será NULL.
LOWER
Retorna o argumento com todas as letras minúsculas.
LPAD
Completa à esquerda, com os caracteres <pad> para que o tamanho da string resultado seja <len>.
LTRIM
Retira , da esquerda para direita, os caracteres <set> até que seja encontrado um caracter diferente
de <set>.
REPLACE
Retorna <str1> com cada ocorrência de <str2> substituída por <str3>. Se <str3> não for informado,
todas as ocorrências se <str2> serão removidas. Se nem <str2> nem <str3> forem informadas a
função retornará NULL.
RPAD
Completa, à direita, com os caracteres <pad> para que o tamanho da string resultado seja <len>.
RTRIM
Retira , da direita para esquerda, os caracteres <set> até que seja encontrado um caracter diferente
de <set>.
__________________________________________________________________________________________
96
__________________________________________________________________________________________
SOUNDEX
Retorna um string que represente o som de <str>.
SUBSTR
Retorna uma parte da string <str>, a partir da posição <pos> por <len> caracteres. Se l<len> for
omitido, retorna o restante da string.
TRANSLATE
Retorna <str>, substituindo cada um dos caracteres presentes em <set1> pelo caracter
correspondente em <set2>. Se <set1> tiver mais caracteres que <set2>, e esses caracteres
estiverem presentes em <str>, serão removidos do resultado.
UPPER
Retorna o argumento com todas as letras maiúsculas.
DATAS
ADD_MONTHS
Retorna a data <dte> adicionada de <n> meses. <n. deve ser um inteiro e pode ser negativo.
LAST_DAY
Retorna a data do último dia do mês de <dte>.
MONTHS_BETWEEN
Retorna o número de meses entre <dte1> e <dte2>.
Definição: FUNCTION MONTHS_BETWEEN (<dte1> DATE,<dte2> DATE) RETURN DATE
Ex.: <variável> := MONTHS_BETWEEN (sysdate, v_dt_nasc) /12;
__________________________________________________________________________________________
97
__________________________________________________________________________________________
NEW_TIME
Converte a data e hora que está no meridiano <zon1>, para a data e hora no meridiano <zon2>.
NEXT_DAY
Retorna a data do primeiro dia da semana nomeado por <day> que seja posterior a <dte>.
SYSDATE
Retorna a data e hora correntes.
ROUND
Retorna <dte> arredondado para o formato especificado.
TRUNC
Retorna uma data no formato especificado por <fmt>, representado <dte> truncada na unidade
correspondente.
CC Século
SYYY, YYYY, YEAR, SYEAR, YYY, YY, Y Ano
Q Quarto de ano
MONTH, MON, MM Mês
WW Início da semana do ano
WHERE Início da semana do mês
DDD, DD, J Dia
DAY, DY, D Último Sábado
HH, HH12, HH24 Hora
MI Minuto
__________________________________________________________________________________________
98
__________________________________________________________________________________________
CONVERSÃO
CHARTOROWID
Converte a string <str> do tipo CHAR ou VARCHAR2 para ROWID.
HEXTORAW
Converte uma string hexadecimal do tipo CHAR ou VARCHAR2 para RAW.
RAWTOHEX
Converte um valor binário em uma string hexadecimal do tipo VARCHAR2.
ROWIDTOCHAR
Converte o valor binário de <bin> para uma string hexadecimal de 18 bytes.
TO_CHAR
Converte um valor numérico ou data para o formato especificado.
__________________________________________________________________________________________
99
__________________________________________________________________________________________
FORMATOS DE NLS
Onde:
TO_DATE
Converte uma string ou um número para o formato data.
TO_NUMBER
Converte <str> para o valor numérico correspondente.
MISCELÂNEA
DECLARE
Só é permitido em comandos SQL.
__________________________________________________________________________________________
100
__________________________________________________________________________________________
GREATEST
Retorna a maior <expr> da lista de valores. Todas as expressões após a primeira são convertidas
para o tipo de dado da primeira antes da comparação ser feita.
LEAST
Retorna a menor <expr> da lista de valores. Todas as expressões após a primeira são convertidas
para o tipo de dado da primeira antes da comparação ser feita.
NVL
Se <expr1> for null, retorna <expr2>. Se <expr1> não for null, retorna <expr1>.
UID
Retorna o valor do inteiro associado a cada username pelo Oracle.
USER
Retorna o username corrente.
USERENV
Retorna informações sobre o user e a sessão.
Valores de <str>
VSIZE
Retorna o número de bytes usado para armazenar a representação interna de <expr>.
__________________________________________________________________________________________
101
__________________________________________________________________________________________
PROBLEMA PROPOSTO:
Gravar na tabela RESULTADO a quantidade de funcionários por departamento, convertendo o código
do departamento da seguinte forma:
RESOLUÇÃO
DECLARE
CURSOR w_c1 IS SELECT cd_depto,count(*) total FROM func GROUP BY cd_depto;
W_c1_row w_c1%ROWTYPE
w_cd_depto number(3);
w_str_depto varchar(1);
BEGIN
OPEN w_c1;
LOOP
FETCH w_c1 INTO w_c1_row;
IF w_c1%NOTFOUND
THEN
CLOSE w_c1;
EXIT;
ENDIF;
W_str_depto := SUBSTR (w_c1_row.cd_depto, 1, 1);
IF w_str_depto = ‘A’THEN w_cd_depto := 100;
ELSIF w_str_depto = ‘B’ THEN w_cd_depto :=200;
ELSIF w_str_depto = ‘C’ THEN w_cd_depto :=300;
ELSIF w_str_depto = ‘D’ THEN w_cd_depto :=400;
ELSIF w_str_depto = ‘E’ THEN w_cd_depto :=500;
END IF;
w_cd_depto := w_cd_depto+ TO_NUMBER(SUBSTR(w_c1_row.cd_depto,2,2));
INSERT INTO RESULTADO (ordem, campo) VALUES
(w_cd_depto,w_c1_row.total);
END LOOP;
END;
__________________________________________________________________________________________
102
__________________________________________________________________________________________
8. COMANDOS
LABELS
Identifica um comando ou conjunto de comandos. Utilizado para desvios e para qualificação.
Deve existir um comando após o LABEL.
sintaxe: <<label>>
Ex.:
<<externo>>
FOR i IN 1..10 LOOP
IF externo.i
THEN
...
ENDIF;
<<Interno>>
FOR i IN 1..10 LOOP
IF inetrno i
THEN
...
ENDIF
EXIT externo WHEN... – encerra ambos os loops
END LOOP;
END LOOP externo;
<<fim>> -- este comando é ilegal porque END não é
End; -- um comando executável
EXIT
Encerra um loop.
Ex.:
LOOP
FETCH w_c1 INTO w_c1_row;
IF w_c1%FOUND
THEN
calc_ir....
....
INSERT
ELSE
EXIT;
ENDIF
END LOOP;
__________________________________________________________________________________________
103
__________________________________________________________________________________________
IF THEN ELSE
A seqüência de comandos só será executada se a condição for verdadeira.
sintaxe:
IF <condição>
THEN
<seqüência de comandos>
END IF;
ou
IF <condição>
THEN
<seqüência de comandos>
ELSE
<seqüência de comandos>
END IF;
ou
IF <condição>
THEN
<seqüência de comandos>
ELSIF <condição>
THEN
<seqüência de comandos>
ELSE
<seqüência de comandos
END IF;
<condição>
[NOT] <expressão boleana> [[AND I OR ] <expressão boleana>]
<expressão boleana>]
<literal boleano> I
<variável boleana> I
<chamada de função boleana> I
(<expressão boleana>) I
<expressão PLSQL> <operador relacional> <expressão PLSQL> I
<expressão PLSQL> IS [NOT] NULL I
<expressão PLSQL> [NOT] LIKE <pattern> I
<expressão PLSQL> [NOT] BETWEEN
<expressão PLSQL> AND <expressão PLSQL> I
<expressão PLSQL> [NOT] IN (<expressão PLSQL>[,
<expressão PLSQL>]) I
<expressão PLSQL> { <nome cursor> I SQL}
{%NOTFOUND I %FOUND I%ISOPEN}
__________________________________________________________________________________________
104
__________________________________________________________________________________________
Ex.:
IF val_sal < 300.00
THEN
Val_ir := 0;
ELSIF val_sal BETWEEN 300.01 AND 1000.00+
THEN
val_ir := val_sal * .10;
ELSEIF val_sal BETWEEN 1000.01 and 3000.00
THEN
val_ir := val_sal * .20;
ELSE
val_ir := val_sal * .30;
END IF;
LOOP
A seqüência de comandos é executada num número infinito de vezes ou até que seja encontrado um
comando “EXIT” ou a condição de “WHEN” seja satisfeita.
sintaxe:
ou
LOOP
<sequencia de comandos>
IF ....
THEN
EXIT; -- encerra o loop
END IF;
END LOOP;
ou
LOOP
<sequencia de comandos>
EXIT WHEN -- encerra o loop
END LOOP;
Ex.:
OPEN w_c1;
LOOP
FETCH WHERE_C1 INTO w_c1_row;
EXIT WHEN w_c1%NOTFOUND;
calc_ir(w_c1_row.vl_sal,w_vl_lim);
...
END LOOP;
CLOSE w_c1;
__________________________________________________________________________________________
105
__________________________________________________________________________________________
PROBLEMA PROPOSTO:
Preencher a tabela TABDEP (nome, código, salário, média, totsal, totméd) com os valores abaixo
obtidos na tabela de departamento:
RESOLUÇÃO
DECLARE
w_tot_sal number(10,2);
w_tot_med number(10,2);
CURSOR w_ c1 IS
SELECT nm_depto, depto.cd_depto, SUM(vl_sal)soma, AVG(vl_sal) media
FROM func, depto
WHERE func.cd_depto = depto.cd_depto
GROUP BY nm_depto, depto.cd_depto;
w_c1_row w_c1%ROWTYPE;
BEGIN
SELECT SUM(vl_sal) INTO w_tot_sal FROM func;
SELECT AVG(vl_sal) INTO w_tot_med FROM func;
OPEN w_c1;
LOOP
FETCH w_c1 INTO w_c1_row;
IF w_c1%NOTFOUND
THEN
CLOSE w_c1
EXIT;
END IF;
INSERT INTO tabdep (nome, código, salário, média, totsal, totmed)
VALUES
(w_c1_row.nm_depto, w_c1_row.cd_depto, w_c1_row.soma,
w_c1_row.media, w_tot_sal, w_tot_med);
END LOOP;
END;
__________________________________________________________________________________________
106
__________________________________________________________________________________________
WHILE LOOP
A seqüência de comandos é executada enquanto a condição for verdadeira. Antes de cada iteração
do loop, a condição é avaliada. Se for verdadeira, a seqüência de comandos é executada.
sintaxe:
Ex.:
OPEN w_c1;
FETCH w_c1 INTO w_c1_row;
WHILE w_c1%FOUND LOOP
...
INSERT INTO folha
END LOOP;
CLOSE w_c1;
PROBLEMA PROPOSTO:
Preencher a tabela TABDEP (nome, código, salário, média, totsal, totméd) com os valores abaixo
obtidos na tabela de departamento
Obs.:
Este problema é o mesmo anterior.
RESOLUÇÃO:
DECLARE
w_tot_sal number(10,2);
w_tot_med number(10,2);
CURSOR w_c1 IS
SELECT nm_depto, depto.cd_depto, SUM,(vl_sal)soma,AVG(vl_sal)media
FROM func, depto
WHERE func.cd_depto = depto.cd_depto
GROUP BY nm_depto, depto.cd_depto;
W_c1_row w_c1%ROWTYPE;
BEGIN
SELECT SUM(vl_sal) INTO w_tot_sal FROM func;
SELECT AVG(vl_sal) INTO w_tot_med FROM func;
OPEN w_c1;
FETCH w_c1 INTO w_c1_row;
WHILE w_c1%FOUND LOOP
INSERT INTO tabdep (nome, código, salário, média, totsal, totmed)
VALUES
(w_c1_row.nm_depto, w_c1_row.cd_depto, w_c1_row.soma, w_c1_row.media,
w_tot_sal, w_tot_med);
FETCH w_c1 INTO w_c1_row;
END LOOP;
END;
__________________________________________________________________________________________
107
__________________________________________________________________________________________
FOR LOOP
A seqüência de comandos é executada um número fixo de vezes estabelecido no comando. No início
do comando a quantidade de vezes que o mesmo será executado já é conhecida, uma vez que não
se pode alterar o valor de <contador> durante a iteração.
sintaxe:
[<< <label> >>]
FOR <contador> IN [REVERSE] <inferior>..<superior> LOOP
<seqüência da comandos>
END LOOP;
Ex.:
Fim := 1;
FOR i IN 3..fim LOOP — <seqüência de comados>
<seqüência de comandos> — não será executada
END LOOP;
__________________________________________________________________________________________
108
__________________________________________________________________________________________
GOTO
Desvia incondicionalmente para um “label”, o qual deve ser dentro do scopo e deve preceder um
comando ou um bloco da PL/SQL.
Ex.:
BEGIN
…
GOTO inclui; — desvio para o comando INSERT
…
<<inclui>>
INSERT INTO func…
END;
BEGIN
…
<<altera>>
BEGIN
UPDATE func — o desvio pode ser para traz
…
END;
GOTO altera;
…
<<fim>> — este label é porque END
END; — não é um comando executavél
NULL
Este comando explicitamente indica que não há ação a ser feita. Serve para compor certas situações
em que um comando é exigido, mas nenhuma ação é realmente necessária.
sintaxe: NULL;
Ex.:
BEGIN
…
<<fim>> — o comando “null” resolve
NULL; — o problema anterior
END;
PROBLEMA PROPOSTO:
Preencher a tabela TABDEP (nome, código, salário, média, totsal, totméd) com os valores abaixo
obtidos na tabela de departamento:
__________________________________________________________________________________________
109
__________________________________________________________________________________________
RESOLUÇÃO:
DECLARE
w_tot_sal number(10,2)
w_tot_med number(10,2)
CURSOR w_c1 IS
SELECT nm_depto, depto.cd_depto, SUM(vl_sal) soma, AVG(vl_sal)media
FROM func, depto
WHERE func.cd_depto = depto.cd_depto;
GROUP BY nm_depto, depto.cd_depto;
w_c1_row w_c1% ROWTYPE;
BEGIN
SELECT SUM(vl_sal) INTO w_tot_sal FROM func:
SELECT AVG(vl_sal) INTO w_tot_med FROM func;
OPEN w_c1;
<<ler>>>
FETCH w_c1 INTO w_c1_row;
IF w_c1%FOUND
THEN
INSERT INTO tabdep (nome, código, salário, média, totsal, totméd)
VALUES
(w_c1row.nm_depto, w_c1_row.cd_depto,w_c1_row.soma),
w_c1_row.media, w_tot_sal, w_tot_med);
GOTO ler;
END IF;
END;
Consideramos que a sintaxe dos comandos SQL já é de conhecimento dos leitores e não serão
repetidos nesta apostila.
OPEN CURSOR
Executa o query associado com uma declaração explícito de cursor.
Ex.:
DECLARE
CURSOR w_c2 (matrícula NUMBER) IS
SELECT nm_func, cd_mat
FROM func
WHERE cd_mat <= matrícula;
BEGIN
OPEN w_c2 (350);
....
END;
__________________________________________________________________________________________
110
__________________________________________________________________________________________
CURSOR LOOP
Implicitamente declara uma área para receber a row, abre um cursor, lê cada row e fecha o cursor
quando todas as rows tiverem sido processadas.
Ex.:
DECLARE
CURSOR w_c2 IS SELECT cd_mat, vl_sal, vl_sal * .10 fgts
FROM func;
...
BEGIN
DELETE FROM folha;
COMMIT;
FOR w_c2_row IN w_c2 LOOP
calc_ir(w_c2_row.vl_sal, w_vl_ir);
w_vl_inss := calc_inss(w_c2_row.vl_sal, w_vl_lim);
INSERT INTO folha
(cd_mat, vl_sal, vl_ir, vl_inss, vl_fgts)
VALUES
(w_c2_row.cd_mat, w_c2_row.vl_sal,
w_vl_ir, w_vl_inss, w_c2_row.fgts);
END LOOP;
COMMIT;
END;
PROBLEMA PROPOSTO:
Preencher a tabela TABDEP (nome, código, salário, média, totsal, totméd) com os valores abaixo
obtidos na tabela de departamento:
__________________________________________________________________________________________
111
__________________________________________________________________________________________
RESOLUÇÃO:
DECLARE
w_tot_sal number(10,2)
w_tot_med number(10,2)
CURSOR w_c1 IS
SELECT nm_depto, depto.cd_depto, SUM(vl_sal) soma, AVG(vl_sal)media
FROM func, depto
WHERE func.cd_depto = depto.cd_depto;
GROUP BY nm_depto, depto.cd_depto;
BEGIN
SELECT SUM(vl_sal) INTO w_tot_sal_ FROM func;
SELECT AVG(vl_sal) INTO w_tot_med_ FROM func;
FOR w_c1row IN w_c1 LOOP
INSERT INTO tabdep (nome, código, salário, média, totsal, totméd)
VALUES
(w_c1row.nm_depto, w_c1_row.cd_depto,w_c1_row.soma,
w_c1_row.media, w_tot_sal, w_tot_med);
END LOOP;
END;
Quando um erro ocorre, uma exception é setada, isto é, a seqüência de execução do programa é
interrompida e o controle é transferido para a área de tratamento de execução do programa.
As exceções pré-definidas pelo Oracle são setadas quando a condição de erro ocorre. As exceções
criadas pelo programa deverão ser setadas explicitamente pelo verbo RAISE.
__________________________________________________________________________________________
112
__________________________________________________________________________________________
EXCEÇÕES PRÉ-DEFINIDAS
Nome da Exceção Oracle Error SQLCODE Condição de Erro
CURSOR_ALREADY_OPEN ORA-06511 -6511 É setada se for executado um
OPEN para um cursor já aberto.
DUP_VAL_ON_INDEX ORA-00001 -1 É setada se for tentada uma
inclusão de uma coluna com valor
duplicado em uma tabela que
possui um índice unique nesta
coluna.
INVALID_CURSOR ORA-01001 -1001 É setada se for feita uma
operação ilegal com um cursor.
Por exemplo: CLOSE em um
cursor não aberto.
INVALID_NUMBER ORA-01722 -1722 É setada se algum comando SQL
tentou uma conversão de uma
string para número e esta
conversão falha porque a string
não representa um número.
LOGIN_DENIED ORA-01017 -1017 É setada se for feita uma
tentativa de logon com um
username/password inválido.
NO_DATA_FOUND ORA-01403 +100 É setada se num SELECT INTO
nenhuma row foi retornada ou se
foi feita uma referência a uma row
não inicializada em uma tabela
PL/SQL.
NOT_LOGGED_ON ORA-01012 -1012 É setada se uma programa
PL/SQL tenata fazer acesso ao
database sem efetuar um logon.
PROGRAM_ERROR ORA-06501 -6501 É setada se ocorrer um problema
interno.
STORANGE_ERROR ORA-06500 -6500 É setada se PL/SQL sai da
memória ou se a memória estiver
corrompida.
TIME_ON_RESOURSE ORA-00051 -51 É setada se ocorrer timeout
enquanto o ORACLE estiver
aguardando por um recurso.
TOO_MARY_ROWS ORA-014222 -1422 É setada se um comando
SELECT INTO retormar mais que
uma row.
TRANSACTION_BACKED_O ORA-00061 -61 É setada quando a parte remota
UT de uma transação é
desmanchada. A transação local
deve ser desmanchada também.
VALUE_ERROR ORA-06502 -6502 É setada se uma operação
aritmética, conversão, constraint
error, truncation ocorrer.
ZERO_DIVIDE ORA-01476 -1476 É setada se houver ocorrido uma
divisão por zero.
__________________________________________________________________________________________
113
__________________________________________________________________________________________
Ex.:
DECLARE
…
BEGIN
SELECT …
SELECT …
SELECT …
EXCEPTION
WHEN NO_DATA_FOUND THEN
…
END;
PROBLEMA PROPOSTO:
Fazer um programa para crítica dos dados informados através de parâmetros:
salário deve estar entre R$ 1500 e R$ 2000 mensais. Na base é gravado o salário atual.
departamento deve existir na tabela de departamentos.
grau de instrução deve estar entre 15 e 20.
ramal deve iniciar com 2.
sexo deve ser F ou M.
RESOLUÇÃO:
DECLARE
w_salario number(7,2) := &1;
w-depto char(3) := &2;
w_git number(2) := &3;
w_ramal number(4) := &4;
w_nome char(8) := &5;
w_sexo char(1) := &6;
e_salario exception;
e_salario exception;
e_depto exception;
e_git exception;
e_ramal exception;
e_sexo exception;
w_aux number(3) := );
BEGIN
IF w_salario < 1500 OR w_salario > 2000 THEN
RAISE e_salario;
END IF;
select count(*) into w_auxi FROM depto WHERE cd_depto = w_depto;
IF w_aux = o THEM
RAISE e_depto;
END IF;
IF w_git < 15 OR w_git > 20 THEM
RAISE e_git;
END IF;
IF SUBSTR(TO_CHAR (nr_ramal),1,1) <> ‘2’ THEM
RAISE e_ramal;
END IF;
IF w_sexo <> ‘F' AND w_sexo <> ‘M’ THEM
RAISE e_sexo;
END IF;
SELECT MAX(cd_mat) INTO w_aux FROM func;
INSERT INTO func (cd_mat, vl_sal, cd_depto, nr _ramal, in_sexo, nm _func, nr _git)
VALUES (w_aux + 1, w_sal * 12, w_depto, w_ramal, w_sexo. w_func, w_git);
EXCEPTION
WHEN e_sexo THEM
__________________________________________________________________________________________
114
__________________________________________________________________________________________
RAISE
Ex.:
DECLARE
erro_soma EXCEPTION;
…
BEGIN
IF …
THEN
RAISE erro_soma;
END IF;
EXCEPTION
WHEN erro_soma THEN
…
WHEN OTHERS THEN
…
END;
Obs.: O desvio de execução do programa é transferido para a exceção OTHERS quando o erro
ocorrido não foi tratado em outras exceções mais específicas. É uma opção para diminuição da
lista de exceptions.
PRAGMA EXCEPTION_INIT
Associa um nome de exceção com um número de SQLCODE. Isto permite que se façam testes se
erro mais específicos em vez de usar OTHERS.
__________________________________________________________________________________________
115
__________________________________________________________________________________________
Ex.:
DECLARE
sem_privilegio EXCEPTION;
PRAGMA EXCEPTION_INIT (sem_privilegio, -1031);
— O ORACLE retorna o erro -1031 se, por exemplo, for feita uma tentativa de alterar uma
tabela em que o usuário só tem autorização de SELECT.
BEGIN
…
EXCEPTION
WHEN sem_privilegio THEN
…
END;
RAISE_APPLICATION_ERROR
É uma procedure que permite ao usuário enviar mensagens de um subprograma ou database trigger.
Ex.:
Obs.: <número> deve variar de -20000 a -20999 e a <mensagem> deve possuir até 512 bytes de
comprimento.
PROPAGAÇÃO DA EXCEÇÃO
Quando uma exceção é setada, se PL/SQL não encontrar um tratamento para ela no bloco correto ou
subprograma, a exceção se propaga. Isto é, a exceção se reproduz no bloco externo e assim por
diante até que a PL/SQL retorne um erro para o ambiente (abortando o programa).
Ex.:
BEGIN
…
BEGIN
IF x=1 THEN RAISE A;
ELSIF x=2 THEN RAISE B;
ELSE RAISE C;
END IF;
…
EXCEPTION
WHEN A THEN
…
END;
__________________________________________________________________________________________
116
__________________________________________________________________________________________
…A’
EXCEPTION
WHEN B THEN
…
END;
A exceção A é tratada no bloco mais interno. Após seu tratamento o programa continua no
comando A.
A exceção B se propaga para o bloco mais externo, é tratada e o programa termina
normalmente.
A exceção COMANDO SQL: se propaga para o bloco mais externo, não e tratada e o erro
passa para o ambiente, isto é, o programa é abortado.
SQLERRM
Ex.:
DECLARE
msg CHAR(100)
BEGIN
FOR num IN 1..9999 LOOP
msg := SQLERRM (num * -1);
INSERT INTO tab_erro VALUES (msg);
END LOOP;
END;
11. SUBPROGRAMAS
Subprogramas são blocos PL/SQL com nome, que podem receber parâmetros e ser invocados. A
PL/SQL possui dois tipos de subprogramas chamados procedures e funções. Geralmente usa-se
uma procedure para executar uma ação e uma função para calcular um valor.
Da mesma forma que qualquer outro bloco (anônimo) PL/SQL, os subprogramas possuem uma parte
declarativa, uma parte executável e uma parte opcional para tratamento de exceção.
Os subprogramas podem ser definidos em qualquer ferramenta ORACLE que suporte PL/SQL.
Podem ser declaradas dentro de blocos, procedures, funções e packages. Os subprogramas devem
ser declarados no fim da parte declarativa, após todos os outros objetos do programa.
Ex.:
DECLARE
w_vl_lim NUMBER(15,2) := &1;
…
PROCEDURE calc_ir (val_sal IN NUMBER, val_ir OUT NUMBER) IS
BEGIN
…
END calc_ir;
FUNCTION calc_inss (val_sal IN NUMBER, val_lim IN NUMBER)
RETURN NUMBER IS
val_inss NUMBER(15,2);
BEGIN
…
__________________________________________________________________________________________
117
__________________________________________________________________________________________
BEGIN
…
END;
PROCEDURES
As procedures são subprogramas que executam uma ação específica.
<nome da variável> [IN | OUT |IN OUT] <tipo> [{:= | DEFAULT} <valor>]
Ex:
FUNCTIONS
Uma função é um subprograma que calcula um valor. Funções e procedures são estruturalmente
iguais, exceto que as funções possuem uma cláusula RETURN que especifica o tipo de retorno da
função.
__________________________________________________________________________________________
118
__________________________________________________________________________________________
Ex.:
DECLARAÇÕES FORWARD
A PL/SQL exige que se declare um subprograma antes de chama-lo. No caso de recursividade,
porém isto não é possível. A PL/SQL resolve este problema com uma declaração forward. Esta
declaração pode ser usada para:
Ex:
DECLARE
w_vl_lim NUMBER(15,2) := &1;
…
PROCEDURE calc_ir(val_sal IN NUMBER, val_ir OUT NUMBER); — declaração
— forward
FUNCTION calc_inss (val_sal IN NUMBER, val_lim IN NUMBER)
RETURN NUMBER IS
val_inss NUMBER(15,2);
BEGIN
…
RETURN val_inss;
END calc_inss;
PROCEDURE calc_ir (val_sal IN NUMBER, val_ir OUT NUMBER) IS
BEGIN
…
END calc_ir;
BEGIN
…
END;
__________________________________________________________________________________________
119
__________________________________________________________________________________________
STORED SUBPROGRAMS
No ORACLE é possível armazenar um subprograma PL/SQL na base da dados após a compilação.
Várias vantagens são adquiridas com este procedimento, tais como:
Local Sintaxe:
De outro <nome da procedure> (<parâmetro>…);
subprograma
De um programa EXEC SQL EXECUTE
de aplicação BEGIN <nome da procedure> (<parâmetro)…); END;
(HOST) END-EXEC;
De uma ferramenta EXECUTE <nome da procedure> (<parâmetro>…);
ORACLE (SQL*PLUS)
ou
BEGIN <nome da procedure> (<parâmetro>…); END;
__________________________________________________________________________________________
120
__________________________________________________________________________________________
Logar modificações
garantir críticas complexas
Gerar o valor de colunas
Implementar níveis de segurança mais complexos
Manter tabelas duplicadas
Pode-se associar até 12 DATABASE TRIGGERS a cada tabela, um de cada tipo (BEFORE UPDATE
<row>, BEFORE DELETE <row>, BEFORE INSERT <row>, BEFORE INSERT <comando>, BEFORE
UPDATE <comando>, BEFORE DELETE <comando> e as mesmas sintaxes para AFTER). Um
DATABASE TRIGGER é composto de 3 partes:
evento
constraint (opcional)
ação
Quando o evento ocorre, o trigger é disparado e um bloco PL/SQL “anônimo” executa a ação.
Deve-se observar que os DATABASE TRIGGERS executam com os privilégios do OWNER e não do
usuário corrente.
__________________________________________________________________________________________
121
__________________________________________________________________________________________
Ex.:
__________________________________________________________________________________________
122
__________________________________________________________________________________________
13. PACKAGES
Um package é um objeto que grupa logicamente subprogramas, objetos e tipos PL/SQL. Packages
são compostos de duas partes: A especificação e o corpo do pacote. A especificação é a interface
com as aplicações. Nela são declarados os tipos, variáveis, constantes, exceções, cursores e
subprogramas. No corpo do pacote é concluída a definição dos cursores e subprogramas e feita a
implementação da especificação.
Um package não pode ser chamado, receber parâmetro nem ser aninhado (declarado dentro de outro
package).
A parte de especificação são declarações públicas, visíveis pelas aplicações. O corpo implementa
detalhes e declarações privadas que são invisíveis pelas aplicações. O corpo seria uma caixa preta.
CRIANDO UM PACKAGE
Um pacote pode ser criado internamente no SQL*PLUS ou no SQL*DBA usando-se os comandos
CREATE PACKAGE e CREATE PACKAGE BODY.
__________________________________________________________________________________________
123
__________________________________________________________________________________________
Ex:
CREATE PACKAGE funcionario AS
TYPE func_reg_type IS RECORD )cd_depto_mat NUMBER, vl_sal NUMBER);
CURSOR salario (mat NUMBER) RETURN func_reg_type;
PROCEDURE admissão
(nome CHAR, grau NUMBER, sal NUMBER, depto CHAR);
PROCEDURE demissão (mat NUMBER);
END funcionario;
PROCEDURE admissão
(nome CHAR, grau NUMBER, sal NUMBER, depto CHAR) IS
BEGIN
INSERT INTO func
(nm_func, nr_git, vl_sal, cd_mat, cd_depto)
VALUES
(nome, grau, sal, cd_mat_seq.NEXTVAL, depto);
END admissão;
Deve-se observar que somente a especificação do pacote é visível e acessível pela aplicação.
Detalhes da implementação que se localizam do body são invisíveis e inacessíveis. Desta forma
pode-se alterar o body sem haver necessidade de se recompilar os programas que usarem os
packages
__________________________________________________________________________________________
124
__________________________________________________________________________________________
REFERÊNCIAS A PACKAGES
Para fazer uma referência aos tipos, objetos e subprogramas declaradas dentro da especificação de
packages deve-se usar a seguinte notação:
Pode-se fazer referência a pacotes de dentro de database triggers, stored subprograms e blocos
PL/SQL dentro de programas e blocos PL/SQL anônimos.
A inicialização da parte executável do package é feita uma única vez, na primeira vez que for feita
referência ao package (por sessão).
Estas mensagens poderão ser mostradas com o uso da procedure GET_LINE ou com o uso do
comando SET SERVER OUTPUT ON no SQL*PLUS ou SQL*DBA, caso contrário estas mensagens
serão ignoradas.
EXEMPLO
Suponha que desejássemos depurar um trigger. Neste caso devemos incluir uma ou mais linhas de
mensagens, da seguinte forma:
Devemos usar o SQL*PLUS ou SQL*DBA com a opção SERVER UOTPUT setada para ON, para
executar o trigger e depurar as mensagens incluídas.
PROCEDURES E FUNÇÕES
Veremos, agora cada uma das procedures e funções contidas no package DBMS_OUTPUT:
DISABLE PROCEDURE
Esta procedure desabilita as chamadas para PUT, PUT_LINE, NEW_LINE, GET_LINE e GET_LINES
e limpa o buffer.
Esta rotina não é necessária se estivermos usando a opção SERVER UOTPUT no SQL*PLUS ou
SQL*DBA.
sintaxe: DISABLE;
__________________________________________________________________________________________
125
__________________________________________________________________________________________
ENABLE PROCEDURE
Esta procedure habilita chamadas para PUT, PUT_LINE, NEW_LINE, GET_LINE e GET_LINES. As
chamadas a estas procedures são ignoradas se o package DBMS_OUTPUT não estiver habilitado.
Deve-se especificar a quantidade de informação (em bytes) as ser armazenada no buffer. Se o buffer
for excedido, receberemos a seguinte mensagem de erro:
-20000, ORU-10027: buffer overflow, limit of buffer_limit bytes.
São permitidas múltiplas chamadas à ENABLE. Não é necessária a chamda a esta procedure quando
utilizamos a opção SQL*DBA ou SQL*PLUS. Se existirem múltiplas chamadas a esta procedure, é o
maior valor dentre os especificados. O tamanho máximo é 1.000.000 e o mínimo é 2.000 bytes.
GET_LINE PROCEDURE
Esta procedure recupera uma linha da informação do buffer, excluindo o caracter newline final. O
tamanho máximo da linha é 255 bytes.
Todas as linhas não recuperadas serão descartadas quando usadas as procedures PUT, PUT_LINE
ou NEW_LINE.
Se a procedure concluir com sucesso, o status retornado é zero, caso contrário é 1 (não existem
linhas no buffer).
GET_LINES PROCEDURE
Esta procedure recupera um array de linhas e pode ser usada no lugar de GET_LINE para reduzir o
número de chamadas ao servidor. Devemos especificar o número de linhas que desejamos recuperar
do buffer. Após recuperar o número de linhas especificado, a procedure retorna o número de linhas
realmente recuperado. Se este número for menor que o número de linhas requisitado, significa que
não existem mais linhas no buffer.
Todas as linhas não recuperadas serão descartadas quando usadas as procedures PUT, PU_LINR
ou NEW_LINE.
Cada linha no array pode ter até 255 bytes de comprimento.
NEW_LINE PROCEDURE
Esta procedure coloca uma marca de fim da linha no buffer. Normalmente usamos esta procedure
após uma ou mais chamadas à procedure PUT, para indicar fim de mensagem. Cada chamada a
NEW_LINE gerará uma linha a ser retornada pelo GET_LINE.
sintaxe: NEW_LINE;
__________________________________________________________________________________________
126
__________________________________________________________________________________________
PUT PROCEDURE
Esta procedure especifica a informação que desejamos armazenar no buffer. Devemos usar esta
procedure para adicionar pedaços de informação ao buffer. As procedures GET_LINE e GET_LINES
não retornam uma linha que não tenham sido terminadas com o caracter newline. Se o tamanho
especificado pelo buffer for excedido, será recebido uma mensagem de erro.
Obs.: Se passarmos como parâmetro um number ou date, quando o item for recuperado será
convertido (com TO_CHAR) para string no formato default. Se desejarmos um formato particular,
devemos passar o parâmetro já convertido (VARCHAR2).
PUT_LINE
Esta procedure especifica a informação que desejamos armazenar no buffer. Esta procedure
armazena, automaticamente, um caracter de fim de linha a cada texto enviado. Cada chamada a
PUT_LINE gera uma linha a ser recuperada pela procedure GET_LINE.
EXEMPLO
__________________________________________________________________________________________
127