Beruflich Dokumente
Kultur Dokumente
Programao de
SGBD
pg: 2
D
Programao de SGBD
ndice
ndice................................................................................................................................................................2
I. Conceitos bsicos........................................................................................................................................3
Introduo.....................................................................................................................................................3
II PL/SQL _ Estrutura Bsica.........................................................................................................................4
Estrutura de um bloco PL/SQL (annimo)..................................................................................................4
Tipos de sub-rotinas de banco de dados.......................................................................................................6
Diferena entre blocos annimos e sub-rotinas...........................................................................................7
Variveis, constantes e tipos de dados.........................................................................................................9
Operadores..................................................................................................................................................10
Variveis especiais.....................................................................................................................................10
Estruturas de controle de fluxo de programa.............................................................................................11
III PL/SQL construes principais.................................................................................................................14
Manipulao de erros.................................................................................................................................20
Triggers......................................................................................................................................................21
IV Estudo de caso...........................................................................................................................................22
Converso de tipo de dados........................................................................................................................44
pg: 3
Programao de SGBD
I. Conceitos bsicos
Introduo
Um nmero muito grande de operaes pode ser executado sobre um banco de dados atravs de
comandos SQL. Algumas dessas operaes podem ser bastante complexas, envolvendo um grande nmero
de tabelas e consultas, com aninhamento de comandos inclusive. Esses recursos da SQL no so
suficientes, entretanto, para solucionar muitos problemas comerciais tpicos, uma vez que a SQL no
oferece recursos de programao estruturada, como loopings e desvios, por exemplo. Por esse motivo, os
principais fornecedores de SGBDs criaram suas prprias extenses procedurais SQL (como a PL/SQL
no Oracle ou a Transact SQL no SQL Server), de maneira a prover recursos de programao em seus
gerenciadores. Essas extenses so verdadeiras linguagens de programao embutidas no SGBD, porm
so proprietrias, ou seja, variam de um produto para outro, apesar de implementarem alguns conceitos
bsicos comuns.
Assim, temos a implementao da SQL nos diversos gerenciadores de banco de dados ocorrendo
basicamente em 3 nveis, conforme a figura a seguir:
SQL padro
Extenses no
procedurais
SQL
Extenses
procedurais
SQL
No primeiro nvel, chamado de SQL padro na figura, h uma uniformidade na sintaxe de certos
recursos SQL, atravs de padronizaes internacionais controladas por rgos especiais como ANSI, ISO,
X-Open, etc. Entram nesta categoria uma grande parte dos comandos DML SQL, de maneira que a
sintaxe e o funcionamento de um SELECT por exemplo, tanto no Oracle como no SQL Server ou MSAccess so iguais para a maioria das consultas bsicas.
Para prover capacidades mais amplas em seus produtos, os fornecedores muitas vezes acrescentam
recursos adicionais ao mecanismo bsico, como por exemplo funes de agregao extras (para clculo de
desvio padro ou varincia, por exemplo), manipulao de strings, tipos de dados, tamanho de registro,
clusulas extras em comandos, etc. Esses recursos variam muito de um SGBD para outro, o que significa
que solues que os utilizem podem no funcionar em outros ambientes de banco de dados e so
representados na figura como Extenses no procedurais SQL.
O terceiro nvel, indicado como Extenses procedurais SQL representa a linguagem de
programao procedural suportada pelo SGBD, e constitui o tema desta apostila.
Com os recursos fornecidos pelas extenses procedurais dos gerenciadores de banco de dados
possvel construir rotinas de diversos tipos que funcionam dentro do SGBD, implementando operaes de
lgica mais complexa e capacidades de processamento linha a linha. Neste material utilizaremos como
referncia o Oracle 7.3 Server e sua linguagem de programao, chamada PL/SQL (Procedural
Language / SQL).
pg: 4
Programao de SGBD
Dentro de um arquivo texto na forma de um bloco annimo. Este tipo de bloco no cadastrado no
dicionrio de dados e sua execuo determinada atravs da chamada ao arquivo no qual ele se
encontra.
Declarado na forma de uma sub-rotina de banco de dados.
pg: 5
Programao de SGBD
BEGIN
EXCEPTION
END;
Exemplo 1:
Declare
wcarga_horaria number(5);
Begin
select carga_horaria into wcarga_horaria
from curso
where cod_curso = 5;
if wcarga_horaria is null then
update curso
set carga_horaria = 72;
commit;
end if ;
exception
when no_data_found then
insert into tab_erro values ( valor no encontrado);
end;
Observaes:
As palavras chaves Begin, End e Declare no so seguidas de ponto e vrgula.
As regras de sintaxe PL/SQL so semelhantes s do SQL:
Linhas de comando podem ser subdivididas
No podem ser usadas palavras reservadas.
Identificadores devem comear com uma letra e conter at 30 caracteres.
Campos de caracteres e datas devem ser usados entre aspas simples.
Comentrios devem ser delimitados por /* * /
So permitidos os comandos select, insert, delete, update
pg: 6
Programao de SGBD
Exerccio:
Testar o bloco PL/SQL do exemplo acima.
Inicialmente defina as tabelas Curso e tab_erro.
Depois execute o bloco sem a existncia do curso com cod = 5.
Inclua o curso com cdigo 5 e teste novamente.
Procedimentos
Tambm chamados de procedimentos armazenados (stored procedures), representam pores de
cdigo SQL e no SQL que ficam armazenados de forma compilada no catlogo do SGBD e so ativados
explicitamente por aplicaes, triggers ou outras rotinas. Como nas linguagens tradicionais de
programao, um procedimento realiza um processamento qualquer e no devolve valor algum em seu
final.
Exemplo:
Ativao
Procedimento
EXEC CrDep(D8,COMPRAS)
Funes
A exemplo das procedures, as funes contm pores de cdigo SQL e no SQL; ficam
armazenadas de forma compilada no catlogo do SGBD e so ativadas explicitamente por aplicaes,
triggers ou outras rotinas. A diferena bsica entre o procedimento e a funo que uma funo, ao
realizar um processamento, produz um valor que devolvido (retornado) em seu final.
Exemplo:
Ativao
Funo
pg: 7
Programao de SGBD
D
VALUES (1, CalcDobro(1));
Ou
SELECT NmFunc,
CalcDobro( VrSalario )
FROM Funcionario ;
p2 NUMBER ;
BEGIN
p2 := p1 * 2 ;
RETURN p2 ;
END ;
Gatilhos
Um gatilho (ou trigger) uma poro de cdigo composto por instrues SQL e no-SQL que
ficam armazenados no catlogo do SGBD e que so ativados automaticamente pelo gerenciador de banco
de dados quando um determinado evento ocorre. Em princpio um gatilho poderia ser entendido como
uma procedure ativada implicitamente pelo SGBD.
Exemplo:
Ativao
Gatilho
Neste material utilizaremos o termo Trigger para referenciar os gatilhos de banco de dados.
Exemplo 2:
001
002
003
004
005
006
007
008
009
010
011
012
013
014
-- Codigo p/ Update
BEGIN
vData := SYSDATE ;
UPDATE Funcionario
SET VrSalario = VrSalario * vPerc, DtUltAlt = vData
WHERE CdDepto = vDepto ;
INSERT INTO LogFunc ( DtOp, Usuario, Chave, CdOp )
VALUES ( vData, USER, VRSALARIO, cCdOp ) ;
pg: 8
Programao de SGBD
015
016
COMMIT ;
017
018
-- Tratamento de excecoes
019
EXCEPTION
020
WHEN NO_DATA_FOUND THEN
021
raise_application_error ( 0001, Depto nao cadastrado ) ;
022
WHEN VALUE_ERROR THEN
023
raise_application_error ( 0002, Salario invalido ) ;
024
WHEN OTHERS THEN
025
raise_application_error ( 9999, Erro geral ) ;
026 END ;
Esse exemplo representa um mdulo PL / SQL tpico (uma procedure, no caso), e permite
visualizar 4 regies bsicas, conforme o esquema:
Assinatura da rotina
(opcional)
Linha 001
rea de declaraes
(opcional)
rea de instrues
(obrigatria)
rea de excees
(opcional)
Exerccio 2:
Com base no modelo da vdeo-locadora, calcular o valor da Multa na devoluo da locao, considerando
R$2,00 reais por dia de atraso. Atualizar a tabela de locao (campo valorloc acrescido do valor da multa).
O nmero da locao deve ser requisitado na tela. Usar exception para testar se o nmero da locao no
existe gravando mensagem de erro(tab_erro).
pg: 9
Programao de SGBD
Subtipos
DEC,
DECIMAL,
DOUBLE,
PRECISION, FLOAT, INT, INTEGER,
NUMERIC, REAL, SMALLINT
NATURAL, POSITIVE
CHAR
VARCHAR2
CHARACTER, STRING
VARCHAR
DATE
BOOLEAN
RECORD
TABLE
Descrio
Permite criar variveis ou constantes que
armazenem nmeros fixos ou de ponto
flutuante com preciso de at 38 dgitos.
Indicado para a criao de variveis ou
constantes que armazenem nmeros
inteiros com sinal, de forma a acelerar
algumas operaes com inteiros no
Oracle. A faixa de valores vlidos vai de
-231-1 at 231-1.
Permite texto de tamanho fixo at 32Kb.
Permite texto de tamanho varivel de at
32Kb.
Utilizado para armazenar datas, horas,
minutos e segundos.
Indicado para valores lgicos TRUE e
FALSE.
Utilizado para construir tipos complexos
estruturados, como imagens de registros
de tabelas, por exemplo.
Utilizado para conter conjuntos de dados
com vrias ocorrncias.
possvel tambm utilizar os atributos especiais %TYPE e %ROWTYPE para fazer com que uma
varivel ou constante herde o tipo de dado de um campo ou registro de tabela. Observe os exemplos a
seguir.
Exemplo 1:
DECLARE
NmUser
TxUnica
DtSist
QtFunc
VrSalario
QtCaixas
VARCHAR2( 30 ) ;
CONSTANT INTEGER := 2 ;
DATE := SYSDATE ;
NUMBER( 5, 0 ) ;
Funcionario.VrSalario%TYPE ;
QtFunc%TYPE ;
Exemplo 2:
DECLARE
pg: 10
Programao de SGBD
RegCargo
Exemplo 3:
DECLARE
RegFunc
Funcionario%ROWTYPE ;
Exemplo 4:
DECLARE
TYPE TabNrMatr IS TABLE OF CHAR(4) INDEX BY BINARY_INTEGER
;
vNrMatr
TabNrMatr ;
Operadores
A tabela abaixo apresenta o conjunto de operadores do PL / SQL.
Operador
+
*
/
**
=
>
<
>=
<=
<>
^=
!=
||
:=
-/*
*/
Significado
Adio
Subtrao
Multiplicao
Diviso
Exponenciao
Igual a
Maior que
Menor que
Maior ou igual a
Menor ou igual a
Diferente de
Diferente de
Diferente de
Concatenao de caracteres
Atribuio
Incio de comentrio (at fim da linha)
Incio de comentrio
Final de comentrio
Variveis especiais
Em um ambiente de programao Oracle existem disponveis para o programador algumas
variveis especiais bastante interessantes para determinadas aplicaes.
Varivel
USER
SYSDATE
UID
Tipo de Dado
Caracter
Date
Caracter / Number
Contedo
Nome do usurio corrente
Data e hora atuais do sistema
Nmero de identificao do usurio corrente
10
pg: 11
Programao de SGBD
Quando for necessrio obter o valor de uma dessas variveis a partir de um comando SELECT que
no referencia diretamente nenhuma tabela ou view normal do banco de dados, deve-se indicar a tabela
especial DUAL na clusula FROM do comando, conforme o exemplo a seguir.
SELECT SYSDATE, USER FROM Dual ;
IF .. END IF
utilizado para permitir que o fluxo do programa seja desviado para um determinado ponto da
lgica, conforme o resultado de uma comparao feita. Existem 3 variaes desta estrutura, cobrindo
desde o caso mais simples at possibilidades de desvio mltiplo.
Variao 1: Desvio simples, sem clusula ELSE
IF <expL> THEN
<operao1> ;
...
<operaoN> ;
END IF ;
;
;
;
11
pg: 12
Programao de SGBD
D
END IF ;
Exemplo 1:
LOOP
<operao1> ;
...
<operaoN> ;
EXIT [ WHEN <expL> ] ;
<operaoN + 1> ;
...
END LOOP ;
...
LOOP
...
vCont := vCont + 1 ;
IF vCont > 10 THEN
EXIT ;
END IF ;
...
END LOOP ;
...
Exemplo 2:
...
LOOP
...
vCont := vCont + 1 ;
EXIT WHEN vCont > 10 ;
...
END LOOP ;
...
Exemplo:
...
vCont := 1 ;
WHILE vCont <= 10 LOOP
...
vCont := vCont + 1 ;
...
END LOOP ;
...
12
pg: 13
Programao de SGBD
...
FOR vCont IN 1 .. 10 LOOP
...
...
END LOOP ;
...
Observaes
A varivel utilizada para o controle do looping FOR criada automaticamente no incio da
estrutura, e por isso, no deve ser declarada explcitamente na rea de declaraes da rotina. O seu
incremento (ou decremento, se a clusula REVERSE for utilizada) tambm automtico. Operaes de
atribuio no podem ser feitas para essa varivel.
13
pg: 14
Programao de SGBD
CHAR( 4 ) ;
BEGIN
SELECT Funcionario.NrMatric
INTO vResult
FROM Funcionario
WHERE Funcionario.NrMatric = pNrMatric ;
RETURN vResult ;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 9999 ;
END ;
Observe na linha 007 a presena da clusula INTO, indicando que o valor retornado pelo comando
ser colocado na varivel vResult, declarada na rotina. Caso houvesse mais de um valor a ser colocado em
variveis, a clusula INTO deveria conter uma lista com os nomes de todas as variveis, separadas por
vrgula. Essas variveis deveriam aparecer em uma ordem compatvel com os campos projetados pelo
SELECT.
Dois cuidados bsicos devem ser tomados ao utilizar-se cursores implcitos:
a) as variveis que recebero os dados obtidos pelo SELECT devero ser declaradas com tipo igual
ao do campo correspondente na tabela, o que torna bastante indicado nesses casos utilizar o
atributo %TYPE ao declarar a varivel, para evitar problemas de incompatibilidade;
b) o comando deve retornar no mximo uma nica linha, seno uma exceo
TOO_MANY_ROWS ser gerada.
No h uma declarao formal do cursor, apenas das variveis a serem atualizadas pelo comando.
Cursores explcitos
14
pg: 15
Programao de SGBD
Inicialmente, existe a declarao do cursor nas linhas 004 a 007, onde no aparece a clusula
INTO. O nome dado ao cursor segue as mesmas regras para os nomes de variveis. A sintaxe bsica dessa
declarao a seguinte:
CURSOR <nome do cursor> IS <declarao SELECT> ;
Ao fazermos a declarao, apenas foi definida uma estrutura que ser utilizada posteriormente,
quando o SELECT for executado e a recuperao das linhas for realizada. A primeira instruo realmente
executvel relativa ao cursor a sua abertura, feita na rea de instrues atravs do comando OPEN. no
momento da abertura que o SELECT executado e as linhas recuperadas tornam-se disponveis para uso.
Sintaxe dos comandos:
Open:
Fetch: Para processar as linhas armazenadas no cursor, preciso carregar os valores da linha corrente em
variveis. A linha corrente aquela em que o cursor est posicionado. Cada fetch funciona como um
read pois faz com que o cursor mude a linha corrente para a prxima.
Fetch <nome-do-cursor> into <rea-de-trabalho>;
Close: Limpa a rea de trabalho do cursor liberando a memria.
Close <nome-do-cursor>;
15
pg: 16
D
Programao de SGBD
Exemplo 2 :
Create or replace procedure patraso
is
begin
--Procedure para gravar socios em atraso
Declare
wdatfecha Date := '19-SEP-97';
cursor locacoes is
Select s.cdsocio, l.nrlocacao, dtprevdev,
valorloc, valormulta from locacao l, socio s
where s.cdsocio = l.cdsocio
and datadev is null
and dtprevdev <= wdatfecha;
--- define um registro com os mesmos campos de locacoes
-reg_locacoes locacoes%rowtype;
-- declara algumas variveis
-wdiatraso number(3);
wval_total locacao.valorloc%type;
wval_multa locacao.valormulta%type;
Begin
open locacoes;
fetch locacoes into reg_locacoes;
while locacoes%found loop
wdiatraso := wdatfecha - reg_locacoes.dtprevdev;
wval_multa := 2 * wdiatraso;
wval_total := reg_locacoes.valorloc + wval_multa;
update locacao
set valorloc = wval_total
where locacao.nrlocacao = reg_locacoes.nrlocacao;
insert into tlog
( dat_log,dsc_mensagem) values
(wdatfecha,'Socio'|| to_char(reg_locacoes.cdsocio) ||
' em atraso - locacao' || to_char(reg_locacoes.nrlocacao));
fetch locacoes into reg_locacoes;
end loop;
commit;
close locacoes;
end;
end;
/
No exemplo acima usamos comandos que permitem que uma varivel herde a estrutura de dados de outra
varivel. So eles:
Atributo %TYPE => Usado para indicar que uma varivel declarada herdar o mesmo tipo de outra
varivel previamente declarada. Isto util quando no sabemos o tipo de uma determinada coluna do
banco de dados alm de permitir alterao da coluna do banco de dados em runtime.
16
pg: 17
Programao de SGBD
D
Exemplo:
Declare
wcodsocio socio.codsocio%type
Neste caso a varivel wcodsocio herda o tipo da coluna codsocio da tabela socio.
Atributo %ROWTYPE => Semelhante ao %type, porm declara uma varivel herdando uma estrutura
de dados do banco de dados
Exemplo:
Declare
socio-reg socio%rowtype
Reg-scio herda toda a estrutura da tabela scio.
Alm dos recursos bsicos ligados aos cursores, existem trs outros que merecem ateno: a
possibilidade da passagem de parmetros para os cursores; os chamados
atributos de cursor e cursores explcitos via looping FOR.
Parmetros de cursor
Geralmente o comando SELECT de um cursor possui uma clusula WHERE que especifica uma
seleo de linhas a serem retornadas. Muitas vezes, temos necessidade de variar um dado a ser comparado
nessa clusula, e isso pode ser feito atravs de uma espcie de parmetro passado para o cursor no
momento de sua abertura. Observe o exemplo a seguir:
001 DECLARE
002
vMatr CHAR( 4 ) ;
003
vNome VARCHAR2( 30 ) ;
004
CURSOR LstFunc ( pSexo CHAR ) IS
005
SELECT NrMatric, NmFunc
006
FROM Funcionario
007
WHERE Sexo = pSexo ;
008
009 BEGIN
010
OPEN LstFunc( F ) ;
011
FETCH LstFunc INTO vMatr, vNome ;
012
CLOSE LstFunc ;
013
014
OPEN LstFunc( M ) ;
015
FETCH LstFunc INTO vMatr, vNome ;
016
CLOSE LstFunc ;
017
018 END ;
Ao abrirmos pela primeira vez, na linha 10, o cursor assume F como sendo o contedo da
varivel pSexo, e assim, recupera apenas os funcionrios do sexo feminino. Na segunda vez que aberto,
o parmetro passado M, e apenas os funcionrios de sexo masculino so processados.
Atributos de cursor
Durante a utilizao de um cursor em uma rotina, uma srie de valores podem ser testados, de
maneira a permitir a monitorao do estado corrente do processamento. Esses valores so obtidos atravs
de variveis especiais mantidas pelo sistema, chamadas de Atributos do cursor. Todos eles tm seu nome
comeando com o smbolo % (sinal de porcentagem) e so referenciados colocando-se o nome do cursor
imediatamente antes do %. A seguir um pequeno resumo com esses atributos e suas caractersticas
principais.
Atributo
Tipo de Dado
Descrio
17
pg: 18
Programao de SGBD
D
%ISOPEN
BOOLEAN
%ROWCOUNT
NUMBER
%NOTFOUND
BOOLEAN
%FOUND
BOOLEAN
Exemplo 2:
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
Exemplo 3:
001 DECLARE
002
vMatr
CHAR( 4 ) ;
003
vSalario
Funcionario.VrSalario%TYPE ;
004
vTotSal
Funcionario.VrSalario%TYPE := 0 ;
005
CURSOR TesteCur IS
006
SELECT NrMatric, VrSalario
007
FROM Funcionario
008
ORDER BY VrSalario DESC ;
009
010 BEGIN
011
OPEN TesteCur ;
18
pg: 19
Programao de SGBD
012
LOOP
013
FETCH TesteCur INTO vMatr, vSalario ;
014
EXIT WHEN TesteCur%NOTFOUND OR TesteCur%ROWCOUNT = 3 ;
015
vTotSal := vTotSal + vSalario ;
016
END LOOP ;
...
...
027
CLOSE TesteCur ;
028 END ;
19
pg: 20
Programao de SGBD
Manipulao de erros
Toda linguagem deve proporcionar aos programadores recursos para uma fcil e adequada
interveno em casos de erro de execuo, de maneira a minimizar ou evitar problemas maiores sobre os
dados. Em PL/SQL isso obtido atravs de um mecanismo baseado no conceito de excees, que podem
ser classificadas em internas ou externas. Uma exceo nada mais do que uma notificao de erro,
realizada pelo programa, atravs de um conjunto de cdigos previamente definidos, que podem ser
detectadas na rea de excees de um mdulo. Tendo sido detectada a ocorrncia, fcil para o
programador associar uma seqncia de instrues para o tratamento daquela espcie de erro.
Ao conjunto de excees padro previamente definidas para o PL/SQL damos o nome de excees
internas, que so mostradas no quadro a seguir.
Exceo
CURSOR_ALREADY_OPEN
DUP_VAL_ON_INDEX
INVALID_CURSOR
INVALID_NUMBER
LOGIN_DENIED
NO_DATA_FOUND
NOT_LOGGED_ON
PROGRAM_ERROR
STORAGE_ERROR
TIMEOUT_ON_RESOURCE
TOO_MANY_ROWS
TRANSACTION_BACKED_OUT
VALUE_ERROR
ZERO_DIVIDE
Descrio
Indica uma tentativa de se abrir um cursor j aberto no programa.
Tentativa de se inserir uma chave duplicada em uma coluna definida
como nica.
Referncia a cursor invlido ou tentativa de operao invlida sobre o
cursor.
Indica que um valor no numrico est sendo usado onde era esperado
apenas nmeros.
Solicitao de login negada
No foram encontrados dados para atender a uma requisio feita
atravs de SELECT INTO.
Usurio no est conectado no Oracle no momento (est off-line).
Erro interno do PL/SQL
Erro de memria do PL/SQL
Ocorreu o atingimento do tempo designado para o usurio na sua
conta.
A instruo SELECT ... INTO encontrou mais de uma linha.
Um servidor remoto desfez a transao
Erro de aritmtica, de converso, truncagem ou de restrio.
Tentativa de se dividir um nmero por zero.
A deteco e o tratamento da condio de erro feita conforme mostrado na rotina criada a seguir.
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
-- Codigo p/ Update
BEGIN
vData := SYSDATE ;
UPDATE Funcionario
SET VrSalario = VrSalario * vPerc, DtUltAlt = vData
WHERE CdDepto = vDepto ;
INSERT INTO LogFunc ( DtOp, Usuario, Chave, CdOp )
VALUES ( vData, USER, VRSALARIO, cCdOp ) ;
COMMIT ;
-- Tratamento de excecoes
EXCEPTION
WHEN NO_DATA_FOUND THEN
raise_application_error ( 0001, Depto nao cadastrado ) ;
WHEN VALUE_ERROR THEN
raise_application_error ( 0002, Salario invalido ) ;
20
pg: 21
Programao de SGBD
024
WHEN OTHERS THEN
025
raise_application_error ( 9999, Erro geral ) ;
026 END ;
Triggers
Um trigger, ou gatilho, de banco de dados uma rotina associada a uma tabela e que disparada
automaticamente sempre que um evento especfico ocorre. Rotinas deste tipo possuem uma estrutura
muito particular, que possvel esquematizar da seguinte forma:
TRIGGER <nome do trigger>
<BEFORE | AFTER> <evento de banco de dados>
[FOR EACH ROW]
[DECLARE
... ]
BEGIN
...
END ;
Um trigger criado atravs da instruo CREATE TRIGGER, e fica armazenado no catlogo do
SGBD, que o ativa a cada vez que o evento de banco de dados definido para ele ocorre. Esses eventos so
as operaes que provocam algum tipo de atualizao nos dados de uma tabela, ou seja, instrues
INSERT, UPDATE ou DELETE. Dentro de um trigger possvel declarar e utilizar variveis, constantes,
cursores, desvios e loopings, como em rotinas de outros tipos. Tambm possvel ativar outras rotinas
(procedures e functions) em seu interior.
Para uma melhor compreenso das caractersticas e recursos disponveis com os triggers, observe
os exemplos a seguir, procurando identificar o efeito de cada um deles e as condies em que so
disparados.
Exemplo 1:
Ativao
Trigger
Exemplo 2:
Ativao
Trigger
UPDATE Funcionario
SET VrSalario = VrSalario * 1.1
21
pg: 22
Programao de SGBD
DECLARE
CdOp
CONSTANT CHAR := S ;
BEGIN
INSERT INTO LogFunc (DtOp, Usuario, TpOp )
VALUES ( SYSDATE, USER, CdOp ) ;
END ;
Exemplo 3:
Ativao
Trigger
UPDATE Funcionario
CREATE TRIGGER AltSalFunc
SET VrSalario = VrSalario * 1.1; AFTER UPDATE OF VrSalario ON Funcionario
FOR EACH ROW
WHEN (new.VrSalario > 5000)
DECLARE
CdOp
CONSTANT CHAR := X ;
BEGIN
INSERT INTO LogFunc (DtOp, Usuario, TpOp )
VALUES ( SYSDATE, USER, CdOp ) ;
END ;
Exemplo 4:
Ativao
Trigger
UPDATE Cargo
SET NmCargo = OFICIAL ADMIN.
WHERE CdCargo = C4 ;
IV Estudo de caso
Veremos agora um caso prtico que nos oferecer a oportunidade de utilizar alguns recursos muito
importantes de um gerenciador de banco de dados. Criao e alterao de tabelas, construo e utilizao
de rotinas no SGBD acompanhados de uma discusso sobre algumas questes pertinentes sobre o projeto
de bancos de dados so os tpicos que sero abordados, atravs do acompanhamento da evoluo de um
pequeno modelo de banco de dados para a manuteno de contas-corrente em um banco. O modelo
propositalmente simplificado, de maneira a ressaltar os tpicos centrais de nosso assunto: SQL Data
Definition Language e PL/SQL.
Inicialmente, o modelo a ser implantado seria o seguinte:
22
pg: 23
Programao de SGBD
@ Nm. Conta
Data Abertura
(E) Agncia
Cliente
Mantm
Conta
Corrente
Possui
Movimento
@ Cd. Cliente
(E) Cliente
@ Nm. Mov.
Nome
Endereo
Telefone
CPF
Data Movim.
Pertence
RG
Tipo Movim
Valor Movim.
Descr. Movim.
Agncia
@ Nm. Agnc.
Nome Agncia
Endereo
Observe que o modelo utiliza uma notao de modelagem de dados que combina a representao de
Peter Chen com uma forma particular de representao de cardinalidades. O projeto suporta contas
conjuntas, atravs do relacionamento N:N Mantm. Com isso, teremos 5 tabelas, correspondentes a cada
um dos arranjos de dados sugeridos no modelo:
23
pg: 24
Programao de SGBD
Entidade
Cliente
Mantm
Conta
Agncia
Movimento
Tabela
Cliente
CliConta
Conta
Agencia
Movimento
Utilizamos um arroba (@) para representar a chave primria de cada tabela e uma letra E para
designar cada uma das chaves estrangeiras. Todas as tabelas possuem uma chave primria simples, exceto
CliConta, que representa o relacionamento Mantm: nesse caso a chave primria composta, formada
pela combinao dos dois atributos (Cliente e Conta Corr.) que, individualmente, representam chaves
estrangeiras.
Alm dessas caractersticas, consideraremos ainda as seguintes especificaes adicionais sobre os
valores dos atributos:
Entidade
Cliente
Atributo
Nome
Endereo
Restries
obrigatrio, deve ser nico na tabela.
obrigatrio.
Agncia
Nome Agncia
Telefone
Conta
Data Abertura
Agncia
obrigatrio.
obrigatrio.
Mantm
Cliente
Conta Corr.
obrigatrio.
obrigatrio.
Movimento
Conta Corr.
Data Movim.
Tipo Movim.
Valor Movim.
Descr. Movim.
obrigatrio.
obrigatrio.
obrigatrio, deve ser C ou D.
obrigatrio, deve ser maior que zero.
obrigatrio.
Alm de observar essas restries deveremos, para criar as tabelas, levar em conta os tipos de dados
mais adequados a cada atributo, bem como definir nomes de campos que sejam mnemnicos e guardem
alguma correspondncia com os nomes dos atributos, mas que tambm obedeam s regras de nomes
impostas pelo Oracle.
Observe o script SQL que gera as tabelas correspondentes ao modelo no Oracle 7.3:
----------
*
*
Arquivo:
*
*
Autor:
*
*
Data:
*
* Finalidade:
*
CriaBan.sql
Cesar
20/3/97
Criar as tabelas referentes ao Banco Simplificado
PRIMARY KEY,
24
pg: 25
Programao de SGBD
D
NmAgencia
EndAgencia
TelAgencia
VARCHAR2(30)
VARCHAR2(50),
VARCHAR2(15)
PRIMARY KEY,
NOT NULL,
NOT NULL
REFERENCES Agencia);
REFERENCES Cliente,
REFERENCES Conta,
PRIMARY KEY,
NOT NULL
REFERENCES Conta,
NOT NULL,
NOT NULL
CHECK ( TpMov IN( 'C', 'D' ) ),
NUMBER(12,2) NOT NULL
CHECK ( VrMov > 0 ),
VARCHAR2(20) NOT NULL ) ;
-- *
-- * Fim deste script
-- *
Voc deve ter reparado que existe uma ordem certa para criar as tabelas, uma vez que
especificamos as restries de integridade referencial (chaves estrangeiras) no prprio comando que cria
as tabelas. Dessa forma, primeiro temos que criar as tabelas que so referenciadas pelas demais. Se esse
cuidado no for tomado, um comando CREATE TABLE que declare uma chave estrangeira para uma
tabela ainda no existente ir falhar.
Uma alternativa seria criar as tabelas apenas com as restries bsicas de NULL / NOT NULL.
Aps criadas todas as tabelas, seriam emitidos comandos ALTER TABLE que acrescentariam a cada
tabela as respectivas restries para implementar as outras regras de integridade (CHECK, UNIQUE,
PRIMARY KEY, FOREIGN KEY). Nesse caso, como ao especificar as chaves estrangeiras todas as
tabelas j existem, no h problema algum relacionado com a ordem das declaraes.
Suponhamos que comandos INSERT tenham sido emitidos para povoar com dados cada uma das
tabelas de nosso modelo. Os dados para estudo sero os seguintes:
25
pg: 26
D
CDAG
---0040
0050
0060
Programao de SGBD
NMAGENCIA
---------------------Praca da Republica
Centro
Prefeitura
ENDAGENCIA
TELAGENCIA
------------------------------ ---------Praca da Republica, 200
555-4433
R 15 de Novembro, 800
555-2211
Av. Sao Paulo, 100
555-6612
3 rows selected.
NMCLIENTE
-------------------------------ANA JUNQUEIRA
JOAO DA SILVA
MAIRA FIGUEIREDO
PEDRO SANTOS
SILVIO PADILHA
ROBERTO ARRUDA
SILVANA FERREIRA
CLAUDIA MARCONDES
JULIANO AGUILERA
MARIANA SOARES
ENDCLIENTE
-------------------------------R SALVADOR, 40
AV CAMPINAS, 89
R OLAVO BILAC, 430
R RUI BARBOSA, 230
R INCONFIDENTES, 20
R BAHIA, 140
AV 7 DE SETEMBRO, 2740
R SALVADOR DALI, 430
R PORTUGAL, 121
R CANDIDO PORTINARI, 1340
10 rows selected.
SQL> SELECT * FROM Conta;
NRCONTA
--------1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
DTABERTUR
--------10-AUG-95
01-SEP-95
12-SEP-95
23-OCT-95
25-OCT-95
04-NOV-95
10-NOV-95
12-NOV-95
17-NOV-95
26-NOV-95
08-DEC-95
12-DEC-95
CDAG
---0040
0060
0040
0050
0060
0050
0040
0050
0050
0040
0060
0060
12 rows selected.
NRCONTA
26
pg: 27
D
----- --------00001
1021
00002
1022
00003
1023
00004
1023
00005
1024
00006
1025
00007
1026
00002
1027
00008
1028
00004
1029
00009
1030
00010
1031
00001
1031
00005
1032
Programao de SGBD
14 rows selected.
Ao analisar a composio de cada tabela, esperamos que voc esteja imaginando como foram
escritos os comandos INSERT correspondentes. Voc tambm deve ter notado que o saldo de uma conta
corrente no se encontra disponvel explicitamente em lugar algum, mas pode ser obtido atravs de um
clculo. Essa soluo possvel mas no muito prtica. Suponha que queiramos acrescent-la, de
maneira que a recuperao desse valor no seja muito demorada. O melhor lugar para ela seria na tabela
de movimentos, conforme indicado na nova verso de nosso modelo Entidade / Relacionamento, mostrado
a seguir. O valor correspondente ao saldo dever ser calculado a cada alterao na base de dados e
27
pg: 28
Programao de SGBD
D
colocado nesse novo campo, que mostrar assim o saldo atual da conta aps computado o movimento.
Evidentemente, o contedo do campo saldo no dever ser nulo em hiptese alguma para qualquer
movimento conhecido em qualquer conta.
@ Nm. Conta
Data Abertura
(E) Agncia
Cliente
Mantm
Conta
Corrente
Possui
Movimento
@ Cd. Cliente
(E) Cliente
@ Nm. Mov.
Nome
Endereo
Telefone
CPF
Data Movim.
Pertence
RG
Tipo Mov.
Valor Movim.
Descr. Movim.
Saldo Atual
Agncia
@ Nm. Agnc.
Nome Agncia
Endereo
Telefone
28
pg: 29
Programao de SGBD
Esse comando cria a nova coluna na tabela. O script a seguir cria o procedimento que ficar
armazenado no SGBD e quando ativado, calcular e atualizar o valor do saldo para cada movimento.
---------
*
*
Arquivo: CriProc0.sql
*
Autor: Cesar
*
Data: 2/9/97
* Finalidade: Exemplo de procedimento de banco de dados
*
(no caso, o procedimento AtuSaldoMov p/ atualizar
*
o saldo de uma conta na tabela de movimentos)
*
;
;
;
;
;
-- *
-- * Cursores p/ obter as contas a processar e seus movimentos
-- *
CURSOR CursorContas IS
SELECT Conta.NrConta
FROM Conta
ORDER BY Conta.NrConta ;
CURSOR CursorSaldoMov IS
SELECT Movimento.NrMov, Movimento.TpMov, Movimento.VrMov
FROM Movimento
WHERE Movimento.NrConta = vNrConta
ORDER BY Movimento.NrMov ;
-- * Corpo do procedimento
BEGIN
OPEN CursorContas ;
LOOP
FETCH CursorContas INTO vNrConta ;
EXIT WHEN CursorContas%NOTFOUND ;
vVrSaldo := 0 ;
-- * Atualiza o novo campo na tabela Conta
OPEN CursorSaldoMov ;
LOOP
FETCH CursorSaldoMov INTO vNrMov, vTpMov, vVrMov ;
EXIT WHEN CursorSaldoMov%NOTFOUND ;
IF vTpMov = 'C' THEN
vVrSaldo := vVrSaldo + vVrMov ;
29
pg: 30
Programao de SGBD
ELSE
vVrSaldo := vVrSaldo - vVrMov ;
END IF;
UPDATE Movimento
SET Movimento.VrSaldo = vVrSaldo
WHERE Movimento.NrMov = vNrMov ;
END LOOP ;
CLOSE CursorSaldoMov ;
END LOOP ;
CLOSE CursorContas ;
END AtuSaldoMov ;
-- *
-- * Fim do procedimento
-- *
O script cria no servidor de banco de dados uma rotina do tipo procedure chamada AtuSaldoMov.
Ela utiliza dois cursores, um para obter os nmeros de conta corrente a processar e outro para obter os
dados dos movimentos da conta. O valor do saldo calculado com base no saldo anterior, tipo de
movimento e valor do movimento. O resultado colocado na coluna do saldo atravs de um comando
UPDATE. Dois loopings so necessrios nessa lgica: um para processar todas as contas, outro para
processar todos os movimentos de uma conta. A lgica utilizada relativamente simples, mas a execuo
desse procedimento pode ser demorada, pois ele causa um grande trfego na rede. Felizmente, para
finalidades prticas, essa rotina dever ser executada apenas uma vez mesmo. O comando para que ela
seja executada seria o seguinte no prompt do SQL *Plus:
30
pg: 31
Programao de SGBD
Resta ento criar o trigger de banco de dados para que o valor de saldo seja calculado a cada
alterao ou incluso na tabela de movimentos. Isso feito atravs do script a seguir, que implementa a
lgica apenas para o caso de incluso na tabela, ficando como exerccio alter-lo para que preveja tambm
a possibilidade de alterao.
-------
*
*
Arquivo:
*
Autor:
*
Data:
* Finalidade:
*
CriTrig1.sql
Cesar
30/3/97
Criar um exemplo de gatilho de banco de dados
31
pg: 32
Programao de SGBD
Exerccio proposto
Agora, vamos assumir que estudos concluram ser interessante desnormalizar a base de dados,
colocando o valor do saldo tambm na tabela de conta correntes. Essa alterao tornaria mais simples a
operao de consulta ao saldo de uma conta, minimizando o trfego na rede e a carga no servidor, mas
acrescentando uma maior complexidade nas operaes de atualizao da tabela de movimentos, pois o
novo valor do saldo deve ser atualizado tambm na tabela de contas. Assim, descreva o procedimento, os
comandos e as rotinas a serem criadas para implementar esse novo requisito. Como auxlio, fornecemos o
novo modelo Entidade / Relacionamento.
32
pg: 33
Programao de SGBD
@ Nm. Conta
Data Abertura
(E) Agncia
Saldo Atual
Cliente
Mantm
Conta
Corrente
Possui
Movimento
@ Cd. Cliente
(E) Cliente
@ Nm. Mov.
Nome
Endereo
Telefone
CPF
Data Movim.
Pertence
RG
Tipo Mov.
Valor Movim.
Descr. Movim.
Saldo Atual
Agncia
@ Nm. Agnc.
Nome Agncia
Endereo
Telefone
33
pg: 34
Programao de SGBD
Funes pr-definidas
ABS( <expN> )
Retorna o valor absoluto (nmero sem sinal) de expN.
Exemplo:
SELECT ABS( -1 ) FROM Dual ;
/* Resultado: 1 */
ASCII( <expC> )
Retorna o valor ASCII do primeiro caracter de expC.
Exemplo:
SELECT ASCII(CdDepto) FROM Depto
WHERE CdDepto = D1 ; /* Resultado: 68 */
/* Resultado: 1222*/
CEIL( <expN> )
Retorna o maior inteiro maior que ou igual a expN.
Exemplo:
SELECT CEIL(12.33) FROM DUAL ; /* Resultado: 13*/
CHARTOROWID(<expC> )
Retorna a expC convertido em um valor de ROWID.
O contedo da expC deve estar no formato da pseudo-coluna ROWID.
Exemplo:
34
pg: 35
Programao de SGBD
CHR( <expN> )
Retorna o caracter ASCII referente ao valor expN.
Exemplo:
SELECT CHR(75) FROM DUAL ;
/* Resultado: K*/
35
pg: 36
Programao de SGBD
FLOOR( <expN> )
Retorna o menor inteiro igual a ou menor que expN.
Exemplo:
SELECT FLOOR( 12.8 ) FROM Dual ;
/* Resultado: 12 */
GREATEST( <exp>,...)
Retorna o maior valor de uma lista de valores exp.
Exemplo:
SELECT GREATEST(abcd, 123, defg ) FROM Dual ; /* Resultado: defg */
INITICAP( <expC> )
Retorna a expC com a primeira letra de cada palavra em maiscula e o resto da palavra em
minsculas.
Exemplo:
SELECT INITICAP(NmFunc) FROM Funcionario
WHERE NrMatric = 1004 ; /* Resultado: Lucio Torres */
36
pg: 37
Programao de SGBD
LAST_DAY( <expD> )
Retorna a data do ltimo dia do ms contida na data expD.
Exemplo:
SELECT LAST_DAY( SYSDATE ) FROM Dual ;
/* Resultado: 31-MAR-98 */
LEAST( <exp>,... )
Retorna o menor valor de uma lista de valores exp.
Exemplo:
SELECT LEAST( abc,123,defg ) FROM Dual ;
/* Resultado: 123 */
LENGTH( <expC> )
Retorna o nmero de caracteres em expC
Exemplo:
SELECT LENGTH( NmDepto ) FROM Depto
WHERE CdDepto = D1 ; /* Resultado: 13 */
LOWER( <expC> )
Retorna todas as letras da expC em minsculas.
Exemplo:
SELECT LOWER( NmCargo ) FROM Cargo
WHERE CdCargo = C1;
/* Resultado: cozinheira */
/* Resultado: ***valor */
37
pg: 38
Programao de SGBD
/* Resultado: 1 */
Retorna a data e a hora da zona expC2 quando a data e a hora da zona expC1 estiver na data e hora
Exemplo:
SELECT
TO_CHAR(
NEW_TIME(TO_DATE(20:16,hh24:mi),PST,GMT),
hh24:mi ) FROM Dual ; /* Resultado: 04:16 */
38
pg: 39
Programao de SGBD
D
Exemplo:
NLSSORT( <expC> )
Retorna um valor sequencial de expC referente a linguagem nacional utilizada pelo sistema.
Quando a ordem sequencial baseada em valores numricos dos caracteres. Esta ordem chamada ordem
binria.
Exemplo:
SELECT NLSSORT( A ) FROM Dual ;
/* Resultado: 4100 */
/* Resultado: 64 */
39
pg: 40
Programao de SGBD
ROWIDTOCHAR( <ROWID> )
Converte o valor ROWID para um valor tipo caracter.
Exemplo:
SELECT ROWID FROM Funcionario
WHERE ROWIDTOCHAR(ROWID) LIKE %5AE1%;
40
pg: 41
Programao de SGBD
SIGN( <expN> )
Se expN for negativo retorna -1, se for positivo retorna 1, se for zero retorna 0.
Exemplo:
SELECT SIGN( 5432 ) FROM Dual ; /* Resultado: 1 */
SOUNDEX( <expC> )
Retorna uma representao fontica de cada palavra em expC (usa fontica da lingua inglesa).
Exemplo:
SELECT nome FROM TABELA
WHERE SOUNDEX( nome ) = SOUNDEX( SMYTH);
/* Resultado: SMITH */
SQRT( <expN> )
Retorna a raiz quadrada da expN, se expN for negativa, retorna nulo.
Exemplo:
SELECT SQRT( 144 ) FROM Dual ; /* Resultado: 12 */
/* Resultado: 555.90267
*/
/* Resultado: BCD */
41
pg: 42
Programao de SGBD
TO_NUMBER( <expC> )
Converte um nmero do tipo caracter para o tipo de dado numrico.
Exemplo:
SELECT TO_NUMBER( SUBSTR(ABCD00193,5,5) )
FROM Dual ;
/* Resultado: 193 */
42
pg: 43
Programao de SGBD
D
Exemplo:
TRUNC( <expN> [, n ] )
Retorna expN truncado na n-sima casa decimal; se for omitido ou for zero, trunca para o valor
inteiro, se n for negativo , zera o dgito esquerda do ponto decimal.
Exemplo:
SELECT TRUNC( 785.143 ) FROM Dual ; /* Resultado: 785 */
SELECT TRUNC( 785.14, -2 ) FROM Dual ;
/* Resultado:100 */
UPPER( <expC> )
Retorna a expC com todas as letras em maisculas
Exemplo:
SELECT UPPER( NmDepto )
FROM Depto
WHERE CDDEPTO = D1; /* Resultado: ADMINISTRACAO */
USERENV( <opo> )
Retorna informaes da opo escolhida sobre o usurio e/ou a seo corrente.
Opes :
ENTRYIDIdentificador de entrada
SESSIONID
Identificador de seo
TERMINAL
Identificador do terminal do usurio
LANGUAGE
Linguagem em uso
Exemplo:
SELECT USERENV( TERMINAL )
FROM Dual ;
/* Resultado: WINDOWS95 PC */
43
pg: 44
Programao de SGBD
VSIZE( <exp> )
Retorna o nmero de bytes usados para armazenar internamente exp.
Exemplo:
SELECT NmFunc, VSIZE( NmFunc )
FROM Funcionario
WHERE NrMatric = 1001;
/* Resultado: 12 */
De
Caracter
Nmero
Data
Para
Caracter
Nmero
Data
TO_CHAR
TO_CHAR
TO_NUMBER
ERRO
TO_DATE
TO_DATE
-
Exerccios Prticos
Lista Nmero 1
Tpico: PL/SQL - Procedures
1) Escreva uma Stored Procedure que atualize a tabela Curso, substituindo uma descrio
existente por outra. Utilizar parametros para indicar a descrio antiga e a descrio nova.
Exemplo: Execute MudaDesc( 'Ingls' , 'B. Dados' );
Obs: a tabela curso deve conter os campos codigo_curso e descr_curso.
2) Considere o modelo E-R Paciente-Consulta j utilizado em aulas anteriores.
Escreva uma procedure que aceite o cdigo do Paciente como parmetro e:
- Calcule o Valor Total de suas consultas nos ltimos 3 meses
Se o valor for maior que 500,00
Gravar 'S' no campo Desconto da Tabela de Paciente
Caso contrrio
Gravar 'N' no campo Desconto da Tabela de Paciente.
- Utilizar o comando exception p/a capturar erros.
44
pg: 45
Programao de SGBD
Lista Nmero 2
Tpico: PL/SQL Triggers
1- Sobre o modelo Paciente-Consulta, escreva um trigger que ao incluir uma consulta
verifique:
Se tipo = `C (convnio) gravar em uma tabela de guias a mensagem
"Emitir guia de convnio do paciente " <cod. Do paciente"> "-" <nome-do-paciente>.
A tabela de guias deve conter o campo Mensagem varchar2(70).
2- Escreva um trigger que ao se excluir uma consulta, grave uma linha na tabela Tlog.
A tabela Tlog deve conter :
data do sistema,
usurio que est efetuando a excluso (user),
cdigo da consulta excluda.
3- Sobre o modelo da Video-Locadora, escreva um trigger que ao inserir uma locao
verifique se o scio j possui mais de 10 locaes no ms atual. Se sim, aplicar um
desconto de 20% no valor da locao que esta sendo cadastrada.
4- Crie um trigger que ao ser alterado o campo endereo da tabela de scio, faa a
insero de uma linha na tabela de log com a mensagem "Observar mudana de
endereo" <codigo do paciente>.
45