Escolar Documentos
Profissional Documentos
Cultura Documentos
AMBIENTE ORACLE
2
2.6.3- Funções e procedures envolvidas em ordem alfabéticas_________________________________
2.6.4- Corpo do programa e procedures___________________________________________________
2.6.5- Padrão de nome de variáveis______________________________________________________
2.6.6- Commit explicito ao termino do programa___________________________________________
2.6.7- Retorno de SQL.SQLCODE em ambientes SQL*PLUS_________________________________
2.6.8- Exemplo de fonte padronizado_____________________________________________________
3-FORMS 4.0 - Conceitos e guia de utilização___________________________________
3.1- Características da ferramenta________________________________________________
3.1.1- Divisão do processamento entre ambientes___________________________________________
3.1.2- Oracle.ini______________________________________________________________________
3.1.3- Codificação de eventos___________________________________________________________
3.2- Modularização de forms e o código PL/SQL____________________________________
Observações:________________________________________________________________________
3.3- Localização de procedimentos PL/SQL________________________________________
3.3.1- Procedures definidas a nível de forms_______________________________________________
3.3.2- Definidas a nível de lib externas___________________________________________________
3.3.3- Nível de base___________________________________________________________________
3.5- Uso de Variáveis___________________________________________________________
3.5.1 - Globais_______________________________________________________________________
3.5.2 -Canvas Null____________________________________________________________________
3.5.3- Internas de PL__________________________________________________________________
3.5.4- Parâmetros_____________________________________________________________________
3.6- Obtenção de Data/Hora_____________________________________________________
3.7- Lista de valores (lov)________________________________________________________
3.8- Triggers mais importantes - Observações______________________________________
3.8.1-Key-<TECLA>_________________________________________________________________
3.8.2- Key-others_____________________________________________________________________
3.8.3- Do-key________________________________________________________________________
3.8.4 Post-change____________________________________________________________________
3.8.5- When-new-???-instance__________________________________________________________
3.8.6- When-validate-item_____________________________________________________________
3.8.7- When-validate-record____________________________________________________________
3.8.8- Post-query_____________________________________________________________________
3.8.9- Pre-query______________________________________________________________________
3.8.10- Pre/Post-????? (Transação)______________________________________________________
3.9 - Integração com base de dados_______________________________________________
3.9.1- Fetch, Buffer e Displayed_________________________________________________________
3.9.2- Base Table vs. Processamento manual______________________________________________
3.9.3- Relação Master-Detail___________________________________________________________
3.9.4- Modo ENTER QUERY__________________________________________________________
3.9.5- Blocos base-table baseado em view’s_______________________________________________
3.9.6- Ativando o SQL TRACE_________________________________________________________
3.10- Integração com outros forms________________________________________________
2.11 -Lock’s no Forms__________________________________________________________
3.12- Forms em modo character__________________________________________________
3.13 - Bugs Comuns no ambiente FORMS._________________________________________
3.13.1- Campo com VARCHAR2 muito grandes___________________________________________
3
3.13.2- Library quando aberta em modo read-only__________________________________________
3.13.3- GPF alterando radio groups______________________________________________________
3.13.4- Sinonimos de database link______________________________________________________
3.13.5- RAISE_APLICATION_ERROR em STORED PROCEDURES._________________________
3.13.6- LOVs sem espaco em disco______________________________________________________
3.13.7- ROS-201 Salvando FORMS em disco______________________________________________
3.13.8- Parametros via run_product em maiúsculas_________________________________________
3.13.9- Refresh de objetos no forms designer______________________________________________
4-REPORT 2.0 - Conceitos e guia de utilização__________________________________
4.1- DATA MODEL e Queries___________________________________________________
4.1.1- Defina o mínimo de queries possiveis_______________________________________________
4.1.2- Utilização de parâmetros léxicos___________________________________________________
4.1.3- Utilização de record-group________________________________________________________
4.2- Processamento de eventos dentro do report_____________________________________
4.3- Considerações gerais na criação de um report.__________________________________
4.4- Monitorando performance___________________________________________________
4.4.1- SQL TRACE___________________________________________________________________
4.4.2- PROFILE_____________________________________________________________________
4.5- Report Character Mode_____________________________________________________
4.6- Client ou Server ?__________________________________________________________
4.7- Principais bug’s no ambiente report.__________________________________________
4.7.1- GPF causados por falta de espaço em disco.__________________________________________
4.7.2- Loops infinitos detectados________________________________________________________
4.7.3- Problemas de impressão - Áreas Negras_____________________________________________
4.7.4- Problemas de impressão - Imagens_________________________________________________
5- Prevenção de GPF’s_____________________________________________________
5.1- Como minimizar a utilização de memória/recursos do windows.___________________
5.2 - O que fazer se um GPF acontecer____________________________________________
5.3- Se o erro for de ambiente___________________________________________________
5.4- Se o erro for da aplicação____________________________________________________
6- Homologando um aplicativo Oracle_________________________________________
6.1- Analise da Lógica utilizada__________________________________________________
6.1.1- Processamento convencional vs. Pensar relacionalmente._______________________________
6.1.2- Verificando transações.__________________________________________________________
6.1.3- Lógica de restart._______________________________________________________________
6.1.5- Sempre verificar execução de comandos foi bem sucedida.______________________________
6.1.6- Aplicando os conceitos___________________________________________________________
6.2- Classificando as aplicações__________________________________________________
Tipo A - Normal_____________________________________________________________________
Tipo B - Importantes__________________________________________________________________
Tipo C - Criticas_____________________________________________________________________
6.3- Verificando conceitos aplicados_______________________________________________
6.3.1- Estrutura básica das fichas:_______________________________________________________
6.4- Definindo tempos Aceitáveis_________________________________________________
4
Exemplo de Ficha de Medição de Tempos - Aplicativos Oracle_______________________________
6.5- Ferramenta PECS de acompanhamento de testes._______________________________
6.5.1 - O que é o PECS________________________________________________________________
6.5.2- Benefícios de uso do PECS_______________________________________________________
6.5.3- Componentes e definições do PECS.________________________________________________
6.5.4- Coletando informações sobre eventos do FORMS_____________________________________
6.5.5- Eventos específicos da Aplicação__________________________________________________
5
1- SQL - CONCEITOS E GUIA DE UTILIZAÇÃO
1.1- FAZES DO PROCESSO DE RESOLUÇÃO DE UMA QUERY
Server
Considerações.
A fase mais importante é a do parse, nela são gastos mais recursos para validação do comando e definição do
plano de acesso, quando um comando SQL é emitido pela segunda vez, este processo já está “resolvido”
economizando-se grande parte do processamento, uma das metas ao se desenvolver os aplicativos é a boa
utilização da SQL Área de modo a evitar todo este processamento.
6
1.2- OTIMIZADOR
No Oracle Server o processo do optimizer é o responsável pela definição do plano de acesso aos dados
requisitados pela query. É a “inteligência” do Oracle , o responsável pela boa performance ou não de sua query.
Existem basicamente 2 modos para o optimizer atuar:
1.2.1 - RULE
Este método é o antigo método utilizado pelo Oracle 6 e 7.0 e agora opcional na 7.1 , baseia-se em determinar
os planos de acessos possíveis e baseado em uma escala de regras definir qual o melhor dos planos de acesso
deva ser utilizado.
Este método não leva em consideração a natureza do dado em si. Caso um dos caminhos possíveis ao dado se
enquadre numa regra de menor nível , este será utilizado pelo otimizador. Deste modo se existir um índice para
a tabela ele sempre será utilizado mesmo que resulte num maior tempo de acesso.
1.2.2- COST
Esta opção está funcional nas releases do Oracle 7.1 em diante, na release 7.0 existe um bug e a mesma não
deve ser utilizada. O Otimizador calcula as opções de acesso ao dado e utiliza o seu “conhecimento” do dado
para escolher qual o melhor plano de acesso, baseado na tabela acima porem observando a seletividade do
dado, numero de blocos necessários para se fazer um full table scan vs. numero de blocos lidos numa leitura,
números de linhas na tabela e outras estatísticas geradas pelo comando analyze.
É importante que se rode as estatísticas de modo que as informações coletadas reflitam a realidade do
dado que será utilizado pelo programa em produção, o comando analyze deve ser executado
periodicamente nas tabelas acessadas.
7
1.2.3- Como definir o modo de otimização
b)Utilizando-se o comando ALTER SESSION SET OPTIMIZER_GOAL=<opção> onde opção pode assumir
os valores CHOSE, RULE, ALL_ROWS e FIRST_ROWS, sendo:
· CHOSE - O otimizador verifica se existem estatísticas no dicionário de dados, caso existam utiliza o
método COST, se não utiliza o método RULE.
· ALL_ROWS - É o método “default” do otimizador pôr custo, a meta é que a query toda seja resolvida no
menor espaço de tempo
· FIRST_ROWS - Utiliza o método custo também, porem a meta é ter a resposta inicial no menor intervalo de
tempo em detrimento da resolução da query como um todo.
· RULE - Utiliza o método RULE para resolução do otimizador.
Observações.
1) Dentro da opção COST é possível alterar o comportamento do otimizador utilizando-se dos database hints
vistos a frente deste documento.
2) O comando ALTER SESSION só altera o otimizador para a sessão corrente do usuário, em uma nova
conexão volta o valor default do init.ora.
As etapas seguintes são a ordem que o processo de otimização segue na resolução do processo de PARSE. Esta
ordem é um processamento interno, não podendo ser modificado pelo desenvolvedor.
B) Transformação de comandos
Comandos são transformados em comandos mais simples e eficientes. Subqueries são transformadas em
joins, condições OR são transformadas em union e através de transitividade restringindo consultas antes
de aplicar o join. Ex.:
Select movimento.cod_venda, comissao.tax_comissao from
movimento, comissao
where movimento.cod_venda < 200 and
movimento.cod_venda = comissao.cod_venda;
é transformado em
Select movimento.cod_venda, comissao.tax_comissao from
movimento, comissao
where movimento.cod_venda < 200 and
comissao.cod_venda < 200 and
movimento.cod_venda = comissao.cod_venda;
8
C) Merge de SQL de views com o SQL analisado
Caso alguma das tabelas acessadas pelo comando seja uma view, o comando SQL é unificado com o
comando implícito na view, caso isto não seja possível o otimizador resolve a view e utiliza as linhas de
resultado como se fosse uma tabela.
Baseado nos parâmetros ou em hints é definido qual o método de otimização será utilizado.
Dentro da lista do “from” o otimizador define a ordem em que os joins serão resolvidos, um par de tabela
é resolvido e o resultado é “joined” com a próxima tabela. A ordem em que os pares são resolvidos é
determinada pelo otimizador baseado nas estatísticas das tabelas e no score dos caminhos de acesso
disponíveis. Caso o desenvolvedor possua alguma informação sobre o número de linhas que será
retornado e esta informação não esteja disponível para o otimizador é possível indicar a ordem em que
as tabelas serão “joined” via hint ORDERED.
1. Nested Loops
Otimizador escolhe uma tabela para tabela drive “outer table” e a outra se torna a tabela “inner”, para
cada linha da tabela drive o Oracle seleciona as linhas que satisfaçam na tabela inner.
2. Sort Merge
Oracle executa um sort das duas tabelas pela chave de ligação do “where”, após o sort é executado um
“merge” das 2 tabelas de modo a se obter as linhas resultantes.
3. Cluster Join
É utilizado em equi-joins de tabelas que estejam localizadas num mesmo Cluster. Num cluster as
tabelas são fisicamente armazenadas seguindo a cluster-key de modo a facilitar o join. É basicamente um
Nested Loop onde a tabela inner já está fisicamente intercalada entre as rows da tabela drive.
Na resolução por regra, o otimizador gera N combinações possíveis de join order e métodos de join usando um
algoritmo interno, dentro deste universo de planos de acessos ele decide qual usar tendo como meta a melhor
utilização de nested loops e sorts merge, para isso ele analisa as opções baseada no ranking das operações
necessárias e nos métodos de acesso das tabelas, quando o método usado é o de custo as estatísticas e
composição dos dados nas tabelas também é levado em conta.
9
Observação:
Quando o otimizador encontra um outer join , a tabela com o operador (+) deve se situar depois da tabela
referenciada na igualdade. O otimizador impõe esta regra na hora de definir a ordem do join.
Deste modo grande parte das tabelas tipo código, descrição o uso do índice não é eficiente. O otimizador
por custo leva em consideração o numero de linhas da tabela e o por regra sempre usa índice.
Não existe um número absoluto de linhas retornadas que possa indicar se o uso do índice é vantagem ou
não, normalmente em torno de 15% este numero depende de vários fatores como o tamanho do bloco em
que o database foi criado, o numero do parâmetro DB_FILE_MULTIBLOCK_READ_COUNT, e o tamanho
que um registro típico ocupa no bloco. O melhor procedimento é tendo criado estatísticas no banco deixar a
cargo do otimizador por custo a decisão no geral e em aplicações onde venha a se detectar problemas de
performance efetuar uma analise mais detalhada com o tkprof e explain plan.
Índices são obrigatórios no caso de se querer garantir a unicidade da linha através de constraint UNIQUE ou
PRIMARY KEY (criados automaticamente na criação das constraints).
É necessário ter em mente que ao mesmo tempo que índices aumentam a performance de consultas, degradam a
performance em inserções, atualizações e deleções. Para qualquer destas operações efetuada na tabela será
necessário atualização de cada índice envolvido na linha/coluna. Tomar cuidado na criação de índices em
tabelas muito dinâmicas, deve-se analisar o custo vs. beneficio em relação a consultas vs. atualizações.
Deve se criar índices pelas foreignkeys de uma tabela, alem de auxiliar o processo de join evita-se que um share
lock seja efetuado na tabela pai, isto evita que inserções, alterações e deleções sejam proibidas na tabela pai
enquanto houverem transações pendentes na tabela filho .
1.3.1 Se um select requerer somente colunas do índice composto, o otimizador não necessita ir a
página de dados.
1.3.1 O Índice é usado caso somente parte das colunas indexadas apareçam no where, contanto que
sejam as primeiras colunas do índice.
Ex. Índice cuja as colunas indexadas sejam (col1, col2 e col3)
where col1= 10 (Índice usado)
where col1 = 10 and col2 = 30 (Índice usado)
where col1 = 10 and col2 = 30 and col3=20 (Índice usado)
where col1= 10 and col3 = 40 (Índice é parcialmente usado)
where col2= 20 and col3 = 40 (Índice não é usado)
1.3.1 Nas escolha de qual coluna deve ser utilizado primeiro escolha a coluna mais
freqüentemente utilizada em where
10
1.3.1 Caso as colunas tenham freqüência comum nos where utilize na definição da ordem de
criação das colunas as colunas mais seletiva para a menos seletiva onde uma
coluna com grande seletividade é aquela que retorna poucas linhas para cada
valor distinto. Uma primary key por exemplo tem a maior seletividade possível
já que somente uma linha existe para cada valor que a coluna possa conter.
1.3.1 Qualquer operação ou função aplicada em uma coluna de índice inibe este índice.
Transformar
Select cd_func,nm_func, nm_departamento
from func, dept
where cd_dept_func = cd_dept
para
Select func.cd_func,func.nm_func, dept.nm_departamento
from func, dept
where func.cd_dept_func = dept.cd_dept
11
C) Evite DISTINCT
uso do predicado DISTINCT provoca um sort na tabela resultado de modo a se retirar as linhas
coincidentes, procure utilizar as estruturas de dados com primary key para obter os resultados únicos
desejados .
A ordem em que as tabelas aparecem não é muito significativa para o otimizador, tanto o otimizador por
regra quanto o por custo testam varias combinações antes de decidir por algoritmos internos qual a
melhor ordem de resolução por joins. Somente em ultimo caso leva-se em consideração a ordem em que
as tabelas se apresentam.
Em sua definição da clausula FROM apresente as tabelas na ordem das tabelas com mais linhas para as
com menos linhas. Ex.
Entende-se tabela com mais linhas o subconjunto de linhas recuperadas já aplicados os filtros explícitos
na condição where.
12
Substitua:
Isto permite ao otimizador checar se efetuando o join tab1, tab3 antes dará um custo menor para a query.
O conceito de transitividade que o otimizador executa só funciona entre colunas e expressões/constantes,
não sendo possível de coluna para coluna.
D) Uso do Like
uso do comando like pode não utilizar índices.
13
F) Forçando o não uso de um índice
Pode se forçar que o otimizador não use o índice sobre determinada coluna aplicando se uma expressão
sobre a mesma. Ex.
G) IS NULL
Campos NULL não são armazenados nos índices, de modo que uma condição CAMPO IS NULL não
utilizara o índice para pesquisa forçando um full-table scan.
H) Use parênteses
Isto facilita a compreensão da lógica em expressões boleanas que utilizem AND e OR, evitando erros e
facilitando o processo de parse.
J) ROWID
Rowid é uma pseudo coluna que toda tabela tem cujo valor é o endereço físico da linha dentro da tabela,
seu uso na cláusula where oferece a melhor performance possível (caso o valor seja conhecido na sessão).
Deve se observar que o rowid não deve ser armazenado para ser usado posteriormente, numa
restruturação da tabela via import/export este valor pode ser alterado.
Exemplo:
DECLARE
..
CURSOR c1 IS SELECT cd_mat, dt_adm, ROWID FROM func;
reg c1%ROWTYPE
BEGIN
OPEN c1;
FETCH c1 INTO reg; /* Obtenho o ROWID para futuro acesso */
..
..
UPDATE func SET vl_sal = vl_sal * 1.5 WHERE rowid = reg.rowid; /* Uso o Rowid como acesso */
CLOSE c1;
END;
14
1.4.4- Cláusula group by
· Ao utilizar a cláusula group by toda coluna que aparecer na lista de colunas selecionadas deve constar
também da cláusula group by com exceção das funções de coluna.
· Só aplique na clausula having restrições em cima de colunas calculadas via funções de coluna ( sum,
max, min, avg, etc..), utilize a clausula WHERE para qualquer outro filtro.
Ex. Troque
SELECT cd_depto, count(*)
FROM func
GROUP BY cd_depto
HAVING COUNT(*) < 10 AND
cd_depto <> ‘12’
para
SELECT cd_depto, COUNT(*)
FROM func
WHERE cd_depto <> ‘12’
GROUP by cd_depto
HAVING COUNT(*) < 10
· Índice só é usado quando estiver nas colunas pertencentes a drive table no caso de um join.
· Não são aplicados quando usados em select que envolvam union, union all, minus e intersect.
· O uso do order by é obrigatório para se garantir que o resultado da tabela venha ordenado, mesmo que
exista um índice para a tabela e este esteja sendo utilizado.
15
1.4.7- Alternativas de sintaxe para mesmo resultados
Várias alternativas de comando são possíveis para se obter um mesmo resultado, o otimizador já troca
vários comandos de forma a obter um melhor resultado. Ex.
De Para
a between b and c a >= b and a <=c
a in ( b,c,d) a=b or a=c or a=d
not in exists
subselect join
É interessante que o desenvolvedor procure já utilizar estas alternativas para simplificar o trabalho do
otimizador.
Exemplos:
De: Para:
SELECT cd_func, nm_func SELECT func.cd_func, func.nm_func
FROM func FROM func, dept
WHERE cd_dept IN ( SELECT cd_dept FROM dept WHERE WHERE func.cd_dept = dept.cd_dept AND
nm_depto LIKE ‘%DIRET dept.nm_depto LIKE ‘%DIRET%’)
%’ )
De: Para:
SELECT cd_func, nm_func SELECT cd_func, nm_func
FROM func A FROM func A, FUNC B
WHERE EXISTS ( SELECT * FROM func B WHERE WHERE A.cd_func = B.cd_gerente )
B.cd_gerente = A.cd_func )
Existem 2 ações que podem ser tomadas para analisar o caminho que o otimizador escolheu para a
resolução de uma query, o EXPLAIN PLAN para analisar queries individuais e os utilitário
TKPROF/TRACE.
16
1.5.1- Explain Plan
Explain plan é um comando que mostra o plano de acesso utilizado por um único comando sql. Para
utiliza-lo é necessário a criação de uma tabela PLAN_TABLE na conta do desenvolvedor que fará a
utilização do comando.
EXPLAIN PLAN
SET STATEMENT_ID = <NOME> INTO PLAN_TABLE FOR
<SQL a ser analisado> ;
EXPLAIN PLAN
SET STATEMENT_ID = 'Emp_Sal'
FOR SELECT ename, job, sal, dname
FROM emp, dept
WHERE emp.deptno = dept.deptno
AND NOT EXISTS
(SELECT *
FROM salgrade
WHERE emp.sal BETWEEN losal AND hisal)
Este comando carregará a tabela PLAN_TABLE com informações da resolução do plano de acesso pelo
otimizador. Para melhor visualizar os dados coletados podemos usar o select abaixo de modo a ter uma
visão do processo executado.
17
Esta query obterá o seguinte resultado para o comando acima analisado
Query Plan
------------------------------
SELECT STATEMENT Cost = 5
FILTER
NESTED LOOPS
TABLE ACCESS FULL EMP
TABLE ACCESS FULL DEPT
TABLE ACCESS FULL SALGRADE
Interpretando o resultado observamos via nível de identação o processo utilizado pelo server para
resolver a query. No primeiro nível verificamos que foi aplicado um filtro composto de um nested loop
( join de emp com dept) e um full-table scan para a tabela salgrade (not exists). Verificamos também que
no nested loop do join não foi utilizado índice para o acesso a table dept, provavelmente por ser pequena
e um full table scan ser mais eficiente).
Outro modo de se analisar performance é utilizando o trace que o server disponibiliza. Para ativa-lo deve
se executar o comando ALTER SESSION SET SQL_TRACE = TRUE/FALSE. , este comando liga e
desliga a geração de um arquivo de trace de sua sessão no server. Após o arquivo de trace ter sido gerado
usa se o programa TKPROF para formatar o arquivo de trace de modo a que possa ser analisado.
Alem da saída similar ao EXPLAIN o trace informa estatísticas sobre todos os comandos sql encontrados,
tais como:
18
Exemplo de parte de uma saída de um arquivo gerado pelo TKPROF.
14 MERGE JOIN
4 SORT JOIN
4 TABLE ACCESS (FULL) OF 'DEPT'
14 SORT JOIN
14 TABLE ACCESS (FULL) OF 'EMP'
Onde
Observações:
Para maiores informações sobre o processo consulte o manual Oracle Server Application Developer’s
Guide - Apêndice B
19
1.6- DATABASE HINTS
É possível forçar o otimizador em determinadas ações através dos database hints, são comandos
colocados dentro de comentários que determinam caminhos que o otimizador deverá executar, as vezes é
possível que o desenvolvedor conhecendo melhor o seu dado escolha uma opção melhor que o otimizador
escolheria, por exemplo.
Observações:
Deve se observar que o uso de database hints deve ser acompanhado pelos AD/DBA/Suporte.
A) ALL_ROWS - Tem como meta o melhor resultado para todas as linhas, é o default e é mais indicado
para processamentos batch. Ex.
B) FIRST_ROWS - A query é resolvida de modo a se obter uma primeira resposta o mais rápido
possível, interessante de ser usada para consultas na tela.
Obs: Este hint é ignorado para comandos DELETE e UPDATE e comandos SELECT que contenham
operadores de conjuntos ( UNION, MINUS, INTERSECT, etc..), group by, for update, distinct, funções
de coluna
C) RULE - Forca o otimizador a utilizar otimização por regra para este comando.
D) FULL(tabela) - Indica que o otimizador deve utilizar um full-table scan para a tabela especificada
SELECT /*+ FULL(a) Don't use the index on ACCNO */ accno, bal
20
FROM accounts a
WHERE accno = 7086854
Caso a tabela tenha recebido um identificador, este deve ser usado no lugar do nome da mesma.
H) INDEX(table [index..indexn]) - Força um index scan pelo índice especificado na tabela especificada.
SELECT /*+ INDEX(patients sex_index) Use SEX_INDEX, since there are few male patients */
name, height, weight
FROM patients WHERE sex = 'M'
Caso não seja informado um índice o otimizador avaliara o custo de todos os índices disponíveis, se
informado 1 ou mais a escolha se dará entre os índices informados.
L) ORDERED - Informa que os joins devem ser executados na ordem da clausula from.
Um join de tab1 com tab2 será efetuado e o resultado será utilizado num join com tab3
M) USE_NL(table) - Força que o join seja um nested-loop com a tabela especificado usada como
inner table.
SELECT /*+ USE_NL(customers) Use Nested loops to get first row faster */
accounts.balance, customers.last_name, customers.first_name
FROM accounts, customers
WHERE accounts.custno = customers.custno
N) USE_MERGE(table) - Forca que a tabela especificada seja “joined” via um sort_merge com o
resultado/ tabela anterior utilizada na ordem do join.
21
1.7- O CONCEITO DE TRANSAÇÃO
Transação é um ou mais conjuntos de ações na base de dados ( inserts, deletes, updates) que constituem
uma unidade lógica mínima que garanta a consistência de seus dados dentro de regras do sistema. Este
conjunto de ações só pode ser aplicado no banco de dados como um todo, caso parte das ações tenham
sido aplicadas e haja uma falha numa ação intermediária, todo as ações já efetuadas neste conjunto
parcialmente executado devem ser desfeitas. Isto é todas as ações são confirmadas ou todo o bloco deve
ser desfeito. Ex.
Não é possível que o processo se interrompa no meio, caso somente as etapas 1,2 e 3 fossem efetivadas,
continuaria com a requisição de vaga em RH, se somente as etapas 1 e 2 fossem realizadas este
funcionário não receberia seguro família, etc.. etc..
É de responsabilidade do desenvolvedor delimitar as transações, para isto deve ser usado o comando
COMMIT para confirmar a transação ou o comando ROLLBACK para cancelar a transação e reverter as
ações já executadas desde o inicio da transação.
O Comando commit termina uma transação e inicia outra, se uma queda do sistema ocorrer ou um
comando rollback for efetivado todos os comandos em aberto ( ate o commit anterior ) serão desfeitos.
Entenda o processo envolvido e regras do seu sistema de modo a determinar logicamente o que é o
conjunto de ações mínimas para se manter os dados íntegros.
· Evite transações muito longas (vários conjuntos lógicos dentro de um mesmo commit)
Enquanto seu dados alterados não forem commitados, a imagem anterior dos mesmos fica
armazenada em áreas de ROLLBACK. Estas áreas são finitas e comuns para todo o banco de dados,
pode não haver área de rollback disponível para uma transação muito longa ou gerar falta de área para
outras aplicações e em caso de falha uma transação muito longa demorará bem mais para desfazer as
ações pendentes. Os dados alterados também ficam em LOCK, isto pode gerar contenção caso outro
usuário necessite altera-los, ao término da transação os locks são liberados.
22
·
· Evite transações muito curtas
No outro extremo evite também commitar a cada linha ou em grupos de ação muito pequenos, cada
commit efetuado gera um overhead, um processamento adicional para liberação de locks e áreas de
rollback. Use o bom senso tendo em vista o tamanho das áreas de rollback disponíveis, número de
usuários concorrendo com os dados e numero de linhas afetadas. Consulte seu DBA para um apoio
nestas decisões.
· Dados não commitados não são vistos por outros usuários (sessões)
Lembre-se que qualquer dado alterado pela sua sessão, só se torna visível a outros após o commit.
1.7.2- Locks
Todo dado alterado numa transação e não commitado fica em estado de lock, outros usuários podem acessar a
informação mas não poderão altera-los até que o commit ou rollback sejam efetuados. Em um ambiente on-line
com vários usuários alterando mesmas informações uma transação que prenda uma linha muito tempo poderá
causar contenção, é importante que se mantenha os lock o mínimo necessário.
Sessão 1 Sessão 2
update func set cargo = 27 update depend set ind_saude= ´4´
where cd_mat =13 where cd_mat = 13
update depend set id_vip = update func set vl_sal = vl_sal *
´S´ where cd_mat = 13 1.10 where cd_mat =13
23
2- PL/SQL - CONCEITOS E GUIA DE UTILIZAÇÃO
2.1- O MOTOR DO PL/SQL
PL/SQL é a extensão do Oracle para comandos procedurais, atualmente existem 2 versões de “motores”
disponíveis no ambiente de desenvolvimento Oracle, uma versão 1.1 para tools ( Forms, Report, Graphics) e 2.1
disponível no Oracle Server 7.1. é importante identificar as diferenças de modo a tornar o código de rotinas
portáveis.
As funções básicas dos SQL (Decode, sysdate, substr, add_months, etc..) estão disponíveis no motor PL,
não é necessário o uso do select from dual para poder utilizá-las,, basta utilizá-las diretamente no código.
Substitua
declare
datatmp date;
begin
select sysdate + 5 into datatmp from dual;
end;
por
declare
datatmp date;
begin
datatmp:= sysdate + 5;
end;
24
2.2- USO DE VARIAVEIS
Pl/sql possui tipos básicos e subtipos mais abrangentes que os tipos permitidos nas tabelas, o tipo number
por exemplo possui os seguintes subtipos
Subtipos
DEC
DECIMAL
DOUBLE PRECISION
FLOAT
INTEGER
INT
NUMERIC
REAL
SMALLINT
Estes subtipos na realidade tem a mesma funcionalidade do tipo number, servindo apenas para
compatibilidade e um melhor descrição do tipo de dado que a variável ira suportar.
Aconselha-se a utilizar em variáveis os mesmos tipos dados existentes no database com exceção do tipo
BOOLEAN comum aos dois motores e TABLE (PL 2.0).
A conversão de tipos do PL/SQL pode ser feita explicitamente ou implicitamente, para se converter os
dados explicitamente utilize a seguinte tabela para determinar o modo de conversão:
· PL Tambem efetua uma conversão implícita de dados sempre que for possível, a seguinte tabela
mostra as conversões possíveis de serem feitas automaticamente.
25
As conversões só podem ser feitas se o conteúdo dos campos forem compatíveis com o tipo do dado
destino e o formato padrão de conversão. Ex.
declare
a varchar2(20);
b number;
c date;
begin
a:= 123;
b:=’123’;
b:=’12A’; /* ERRO ! */
c:=’10-JAN-95’;
c:=’10/1/95’; /* ERRO ! Não é o formato padrão de data */
end;
Ex.
DECLARE
vnmo_func func.nm_func%type;
emp_rec emp%ROWTYPE;
CURSOR c1 IS SELECT deptno, dname, loc FROM dept;
dept_rec c1%ROWTYPE;
...
O uso destes atributos garantem uma consistência de seus programas com a base definida, caso haja
alguma alteração em colunas da base, o seu programa compatibilizará as variáveis com a base.
· Estruture bem seus programas, o PL/SQL fornece mecanismos para isso : Procedures e functions.
· Tenha em mente que unidades menores de códigos que executam funções especificas são mais fáceis
de se utilizar, manutender e de se depurar em caso de erro.
· Não faça grandes blocos PL/SQL, utilize ao invés um grande conjunto de pequenos blocos PL/SQL
que contenham funcionalidade bem definidas e que podem ser testados independentemente caso
necessário.
Problemas de memória podem ocorrer causando desde GPFs em ambiente windows, resultados errôneos e
mau comportamento da ferramenta utilizada. Se seu programa for bem estruturado, as procedures terão
sua funcionalidade bem específicas e atomizadas não necessitando muitas linhas de códigos. Tente
manter uma meta de no máximo 100 linhas por procedure, se sua rotina começar estender muitas linhas
de código tente verificar a possibilidade de encapsular parte de seu código em rotinas menores.
· Procedures e functions podem ser definidas dentro de um programa PL/SQL ou de outra procedure
ou function e ajudam a conservar memória no momento que variáveis definidas internamente a
uma procedure só alocam recursos de memória durante a execução das mesmas.
26
· Deve-se no começo de um programa declarar todas as procedures utilizadas no mesmo ( foward
declarations) , isto evita erro de procedures não declaradas a tempo de compilação, permite uma área
do fonte para com a relação de todas as procedures utilizadas e permite que se insira as rotinas em
ordem alfabética o que facilita a manutenção.
DECLARE
/* Declarações de procedures utilizadas no sistema (Foward) */
PROCEDURE calc_taxa (...); -- Calcula taxa servico
PROCEDURE calc_bonus (...); -- Calcula bonus
/
2.3.1- OVERLOAD
Procedures e functions podem ser “overloaded’ dentro de um programa pl/sql, isto permite que uma única
função tenha uma única funcionalidade e lógica implementada diferentemente dependendo dos
parâmetros passados. Ex.
declare
procedure msg (a in varchar2,b in number ) is
begin
dbms_output.put_line(a||' - Cod:'||to_char(b)) ;
end;
begin
msg(12);
msg(sysdate);
msg(' Teste 1 ',12);
msg(' Resultado OK');
end;
27
O usuário tem aparentemente disponível uma única função que pode ser implementada para todos os
tipos de dados que surgirem a fim de se obter o resultado lógico desejado.
As procedures, functions e packages podem ser armazenadas no banco de dados de forma independente.
Este procedimento traz várias vantagens.
Permite que regras de negócios comuns a todos os sistemas da empresa sejam armazenadas de forma
centralizada, facilitando seu controle e administração. Disponibiliza seu uso para todas ferramentas que
acessam o banco de dados: Database Triggers, Oracle Tools, Linguagens 3 geração via pre-
compiladores, outras Storages procedures, Banco de dados remotos e ate mesmo outras linguagens via
ODBC como ACCESS.
Processo de parse não é necessário para as storage procedures, elas já são armazenadas compiladas no
banco de dados, em caso de se efetuar alguma alteração no ambiente dos objetos utilizados pela
procedure ( criação ou drop de índices, alteração de tabelas, etc..) ela será compilada durante a próxima
execução.
Obs: É interessante para se evitar possíveis erros que após mudanças na base se recompile as procedures
de modo a evitar que possíveis erros sejam detectados na próxima execução das mesmas.
Todos os fontes das stored procedures estão salvos no dicionário do banco de dados, assim estão
sempre disponíveis para uma recompilação e alteração.
28
· Evitar tráfego na rede
No caso de se enviar a procedure para o server transformando num stored procedure este tráfico
diminuirá sensivelmente.
As stored procedures são objeto do banco de dados passíveis de serem tornadas de execução publica
ou para users selecionados, As tabelas acessadas pelas procedures necessitam de grant para o owner
da procedure, o criador da mesma. Um user que tenha grant de execução de determinada procedure
não necessita de ter acesso direto as tabelas envolvidas em seu código, esta característica facilita a
administração e controle de segurança
Obs:
1- As informações disponíveis sobre as stored procedures estão disponíveis nas seguintes tabelas do
catálogo :
ALL_ERRORS, USER_ERRORS, DBA_ERRORS
ALL_SOURCE, USER_SOURCE, DBA_SOURCE
USER_OBJECT_SIZE, DBA_OBJECT_SIZE
29
2.3.3- Estrutura de Packages
Packages são conjuntos de procedures, functions , exceptions e variáveis definidas num único bloco. uma
package é dividida entre 2 áreas, uma área de especificação onde são definidas o que será visível ao
usuário e uma área de implementação (body) onde se definem o corpo das procedures definidas na
especificação e outras procedures auxiliares não disponíveis ao usuário e sim as outras procedures da
package.
Permite tambem que se criem variáveis comuns as procedures da package e disponíveis ao usuário
durante o transcorrer da sessão.
A estrutura de package deve ser usada na criação de bibliotecas unindo rotinas que tratam de assuntos
afins.
Uma série de package estão pre-definidas no database para uso do desenvolvedor, entre elas podemos
destacar
· DBMS_OUTPUT
Esta package é importante na depuração de programas PL/SQL no ambiente SQL/PLUS, podendo emitir
mensagens sinalizando o caminho executado pelo seu programa. Ex.
/
SET SERVEROUTPUT ON
/
BEGIN
..
..
IF ( flag = ‘S’) THEN
INSERT INTO lancamentos ( cd_lanc, dt_lanc , vl_lanc) VALUES ( ‘01’, SYSDATE, vlCalc);
dbms_output.put_line(‘LANCAMENTO INSERIDO ‘);
END;
..
..
END;
· DBMS_SESSION
Esta package permite definir alguns controles de sessão como set role e set sql trace, etc..
Ex.: dbms_session.SET_ROLE() e dbms_session.set_sql_trace(true);
· DBMS_DDL
Esta package permite alguns controles sobre stored procedures, entre elas DBMS_DDL.COMPILE_ALL
que compila todas as procedures na base.
· DBMS_LOCK
Permite a criação de locks lógicos, como por exemplo se bloquear um processo quando determinada
impressora estiver em uso, para isso a aplicação cria um lock lógico para a printer de modo que se outra
processo tentar obter o mesmo lock não terra sucesso.
30
· DBMS_ALERT
Exemplo:
App1:
A Aplicação cima é avisada sempre que uma inclusão, alteração ou exclusão for efetuada na tabela EMP.
· DBMS_PIPE
Permite troca de informação entre sessões de forma assíncrona ( não dependem de commit)
Exemplo:
Esta rotina manda uma mensagem de debug para outras aplicações poderem monitorar com o seguinte
segmento de código.
DECLARE
s INTEGER;
chr VARCHAR2(200);
BEGIN
chr := '';
s := DBMS_PIPE.RECEIVE_MESSAGE('plsql_debug'); /* verifico se tem mensagem... */
IF s = 0 THEN /* caso positivo pega a mensagem na variavel chr */
DBMS_PIPE.UNPACK_MESSAGE(chr);
END IF;
31
· DBMS_SQL
Esta package permite que execute comandos sql montados dinamicamente dentro de aplicações.
32
-
2.4- CURSORES
Cursores são estruturas internas utilizadas pelo Oracle para a resolução de comandos SQL, qualquer
comando sql exige um cursor aberto, eles podem ser explícitos ( abertos pelo desenvolvedor ) ou
implícitos ( gerados pelo database para resolver comandos sql ). Segue algumas observações que devem
ser consideradas pelo desenvolvedor:
· Utilize cursor explicito uma vez que é mais eficiente que utilizar cursor implicitamente .
A sintaxe:
declare
vnome func.nm_func%TYPE;
cursor C1 is select nm_func from func where cd_mat = 12;
begin
open c1;
fetch c1 into vnome;
close c1;
end;
é mais eficiente que
declare
vnome func.nm_func%TYPE;
begin
select m_func into vnome from func where cd_mat=12;
end;
No primeiro caso somente um fetch é executado, no caso do comando select into dois fetchs são
executados, um para obter o dado e um segundo para checar a exceção TOO_MANY_ROWS
Numero de cursores abertos simultaneamente pelo Oracle é finito e definido em parâmetro do init.ora, é
importante que se feche os cursores quando não mais forem utilizados.
Não utilize commit durante o processamento de um cursor for update aberto, o mesmo fica invalidado
para alterações, pois ao dar o commit os locks são liberados
Utilize quando necessário cursor com parâmetros de modo a reutiliza-los já parseados mais de uma vez
na sua aplicação
Tente sempre utilizar um join no cursor mais externo, um join normalmente é melhor que “sub selects” dentro
do uso deste cursor.
33
· Não use locks com for update
Caso seja necessário atualizar um linha de um cursor selecione na declaração do cursor a pseudo coluna
ROWID e quando necessário atualizar a linha utilizando este rowid. Ex.
declare
begin
open c1;
fetch c1 into reg;
..
..
update func set vl_sal = vl_sal * 1.5 where rowid = reg.rowid;
close c1;
end;
Procure usar a estrutura de cursor loop, ela apresenta uma sintaxe clara e eficiente na utilização de
cursores.
Exemplo.
DECLARE
salary_total REAL := 0.0;
CURSOR c1 IS SELECT ename, sal, hiredate, deptno FROM emp;
...
BEGIN
FOR emp_rec IN c1 LOOP
...
salary_total := salary_total + emp_rec.sal;
END LOOP;
...
END;
O cursor é aberto, fetched num loop e fechado ao final (%NOTFOUND). A estrutura emp_rec é
automaticamente declarada como %ROWTYPE do cursor.
2.5- RECURSIVIDADE
PL/SQL é uma linguagem com características recursivas, isto é , o PL/SQL permite que uma função
chame ela própria.
· Em muitos casos o uso de recursividade torna o código mais elegante e simples do que uma versão do
mesmo via iteração.
· Deve-se tomar cuidados como a garantia de um termino do processamento de modo a evitar loops.
· Deve-se tomar cuidado com declaração de variáveis que serão alocadas em cada chamada recursiva.
Um numero grande de iterações pode causar erro de pilha de vaiáveis devido a falta de memória.
34
¨ Versão recursiva
· versão iterativa
Apesar do fonte na versão recursiva ser mais simples e elegante, ele não é mais eficiente já que a cada
iteração a chamada da função gera overhead e nova alocação de memória na área de stack quando
executado.
Se o numero de iterações for muito grande deve-se optar pelo método iterativo pelo ganho de
processamento, caso este número não seja significativo a aproximação recursiva pode ser utilizada para
uma melhor legibilidade do programa.
35
2.6- PADRÃO DE CODIFICAÇÃO DE PROGRAMAS PL/SQL
É interessante um padrão de codificação de seus programas PL/SQL, isto ajuda na clareza, manutenção e
entendimentos dos mesmo. Sugerimos os seguintes tópicos
SPOOL &1
De modo a direcionar possíveis saídas de seu programa para um arquivo de log passado como primeiro
parâmetro na linha de comando.
Inclua em todos os programas um cabeçalho com nome do programa, sistema, pequena descrição do
objetivo do mesmo, ações nas bases acessadas e lista de versões com data, autor e mudanças efetuadas.
Declare o cabeçalho (declaração foward) de todas as procedures e functions utilizadas no programa com
pequena descrição das mesmas.
Como todas as rotinas já foram declaradas foward, inclua o fonte das mesmas em ordem alfabéticas
dentro do fonte. Isto facilita a localização das rotinas em caso de manutenção
Utilize as palavras reservadas, procedures e rotinas originais da Oracle em caixa alta (maiúsculas), o resto
do fonte ( variáveis, funções definidas pelo usuários, etc. ) em caixa baixa (minúscula).
Ao terminar uma definição de função ou procedure indique o nome do módulo após o ultimo END do
bloco. (Vide exemplo de fonte)
36
2.6.5- Padrão de nome de variáveis
· XXX - Indica três letras identificadoras da natureza da coluna de acordo com o glossário de
termos
· YYYYYY- Até seis letras que identificam cada qualificador da coluna de acordo com glossário
de termos.
Ao termino do bloco principal de seu programa PL/SQL saia sempre do sqlplus com o comando EXIT
SQL.SQLCODE, isto informa ao sistema operacional o sucesso ou falha do processo, isto permite que
scripts tenham um bom controle do processo.
SPOOL $1
BEGIN
--
-- Programa FNM003 - Calculo de reajuste de funcionarios.
--
--Este programa varre a tabela de funcionarios atualizando o salario de acordo com índice encontrado na tabela de cargos,
-- caso este índice não seja encontrado o funcionario não tera aumento.
--
--
-- Historico do programa
-- Data Autor Mudancas
-- -----------------------------------------------------------------------------------------------------------
-- 01/04/95 Antonio Jose Entrega de programa para produção
--01/08/95 Antonio Jose Mudanca de acesso para update via ROWID
--01/12/95 Claudia Silva Exception NO_DATA_FOUND para tab_cargo incluido (sem taxa)
--
-- Rotinas utilizadas no programa ( Declaração foward ) -----------------------------------------------------------
37
-- Declaração de Cursores e variaveis globais ------------------------------------------------------------------------
CURSOR cur_tab_func IS
SELECT cod_func, val_salario,cod_cargo,cod_depto, ROWID
FROM tab_func;
wrk_val_taxa NUMBER;
wrk_val_sal_novo NUMBER;
wrk_ind_reajuste NUMBER;
BEGIN
SELECT
val_ind_reaj INTO wrk_ind_reajuste
FROM
tab_cargos
WHERE
cod_cargo = par_cod_cargo AND
cod_depto = par_cod_depto;
RETURN wrk_ind_reajuste;
EXCEPTION
WHEN NO_DATA_FOUND THEN
return 1;
WHEN OTHERS THEN
RAISE_APLICATION_ERROR(200002,’Erro acessando tabela de cargos’);
END calcula_taxa;
38
3-FORMS 4.0 - CONCEITOS E GUIA DE UTILIZAÇÃO
3.1- CARACTERÍSTICAS DA FERRAMENTA
Forms 4.0 é a ferramenta da Oracle para o desenvolvimento de aplicações on-line baseada em arquitetura
cliente-servidor e numa programação orientada a eventos. Deve-se lembrar que parte do processamento
se realiza em sua máquina (cliente) e parte se realiza no servidor onde está localizado o banco de dados
(server), o entendimento deste conceito permite um balanceamento de recursos de cpu obtendo assim
uma melhor utilização dos 2 ambientes.
Roda no Cliente
Roda no Servidor
3.1.2- Oracle.ini
Certos controle do forms são parametrizados através de variáveis de ambiente, no ambiente UNIX estas
variáveis são definidas na profile do usuário e no ambiente WINDOWS são variáveis definidas dentro de
um arquivo chamado ORACLE.INI que se encontra normalmente no seu diretório windows. Este arquivo
contem informações para toda a linha de produto Oracle e entre os diversos parâmetros destacar os
seguintes para o ambiente forms:
Objetos UNIX Windows
Localização de fontes (fmb,fmx,etc) ORACLE_PATH FORMS40_PATH
editor FORMS_EDITOR FORMS40_EDITOR
temp files TMPDIR TMP (SET TMP= no dos)
default font FORM40_DEFAULTFONT (4.0.13)
Diretório de icones TK2_ICON TK20_ICON
39
Exemplos:
FORMS40_PATH=H:\ORAWIN\FORMS45\PLSQLLIB; H:\ORAWIN\FORMS45\SOURCES;
A localização dos fontes e executáveis pelo forms obedece a seguinte regra de busca. Se nome completo
for especificado este será usado, se não :
No caso de libraries, o arquivo .PLL deverá estar no diretório corrente caso não se especifique o path
completo no nome no momento de se atachar a biblioteca, após atacha-la pode se mover para qualquer
diretório apontado pela variável FORMS40_PATH.
Uma linguagem orientada a eventos não é linear, não existe um fluxo seqüencial de comandos definidos
por aplicação, e sim uma série de pequenos códigos associados a cada evento que o usuário ou sistema
possa provocar. Não existe deste modo um “fonte” único de sua aplicação e sim uma série de pequenos
fontes que são disparados numa seqüência comandada pelo usuário e não pelo programa.
Não faça sua lógica assumindo determinadas seqüências de procedimentos que o usuário “normalmente”
seguiria, sua aplicação tem que estar apta a responder os eventos do usuário em qualquer ordem em que
ele possa provocar com o uso do teclado, mouse, menus e eventos disparados pelo sistema operacional
(windows).
Deve-se seguir os mesmos conceitos de modularização discutidos no capitulo inicial de PL/SQL, evite
triggers muito grandes e mantenha seus códigos pl/sql organizados em procedures e functions de acordo
com os padrões discutidos anteriormente.
40
Observações:
3.2.1 - Caso mais de uma trigger dispare um mesmo código, empacote este código numa procedure e
informe a chamada da procedure nas 2 triggers que necessitem disparar o código. Exemplo:
PROCEDURE popula_nmdepto
BEGIN
SELECT nm_depto INTO :blk1.nm_depto FROM depto
WHERE cd_depto = :blk1.cd_depto;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END;
Isto permite um melhor controle do código em caso de manutenção poupando tambem memória na
estação cliente.
3.2.2- Não crie em um único forms várias windows e várias funções distintas. Mantenha a meta de 1
window principal para cada form ( 1 form ó 1 window ó 1 aplicação ó 1 Função básica). Isto permite que
em caso de alteração somente o form afetado tenha que ser recompilado, alem de só carregar na memória
o que for necessário no momento.
3.2.3- Se o fonte de uma procedure ou trigger passar de 100 linhas procure desmembra-la em unidade
menores. Existe um limite de 64K por código no forms e caso um fonte se aproxime deste limite causara
um GPF no ambiente de desenvolvimento windows abortando o programa e perdendo o trabalho digitado.
2.2.4- Não utilize nomes de procedures e objetos do forms com o mesmo nome de objetos do banco de
dados. Isto causa erro na geração do forms.
2.2.5- Dentro do código PL/SQL sempre se referencie a objetos do forms prefixando o nome do bloco,
isto acelera o processo de compilação e evite erros em futuras manutenções caso novos campos sejam
adicionados com mesmo nome em blocos diferentes.
41
2.2.6- Torne suas procedures o mais independentes possível de seu forms, evite acessar diretamente
dados externos (variáveis globais, campos de tela, etc.) sempre que possível utilize os parâmetros
IN e OUT para a interface com o meio externo. Isto torna seu código mais estanque e mais fácil de
depurar.
Exemplo:
Evitar Ideal
BEGIN BEGIN
.. ..
valida_uf; valida_uf(:cd_uf, wrk_ind_find);
IF :global.find = 1 then IF wrk_ind_find = 1 THEN
.. ..
END; END;
3.2.7- Ao utilizar a built-in MESSAGE() do forms para nível de depuração de programa emita sempre o
comando SYNCHRONIZE, isto faz com que a mensagem enviada seja imediatamente mostrada na tela,
evitando que um erro linhas mais a frente desabilite o processamento do comando previamente emitido.
Se possível crie uma procedure MENSAGEM já incorporando o SYNCHRONIZE após o MESSAGE.
3.2.8- Ao utilizar cores no design utilize somente as cores das 2 colunas mais a esquerda da pallete de
cores. Estas cores são comuns tanto para boilerplates como para itens e são as cores mais básicas do
windows. Itens nem sempre tem as cores mais a direita possíveis, muitas vezes o resultado apresentado é
diferente do que aconteceria em um boilerplate e não são disponíveis para ambiente 16 cores.
Cada uma das formas tem suas características próprias que indicam as diferentes situações em que devam
ser escolhidas como opção de armazenamento .
42
3.3.1- Procedures definidas a nível de forms
Recomendado quando:
Observações:
Recomendado quando:
Observações:
· Permite uma centralização de bibliotecas facilitando o gerenciamento das rotinas básicas de uma
instalação.
· Alteração de uma lib não necessita que se regere os forms que a utilizam.
· Lembrar de se rodar o generate da lib sempre que se alterar alguma rotina de uma lib.
· Objetos do forms/canvas não são diretamente acessados pelo código das rotinas, é necessário que se
utilize as built-ins copy() e name_in().
· Permite utilização no PL/SQL de built-ins especificas do forms.
· Não mesclar em uma única LIB rotinas especificas para forms com rotinas especificas para report,
crie se necessário 2 libs separadas
· Não faça uma grande lib com todas as rotinas existentes, divida em libs menores com procedimentos
afins pois uma lib anexada a um forms vai toda para a memória.
· Em desenvolvimento deve-se atachar a library de produção de modo a se evitar conflitos e erros
quando a library de desenvolvimento for atualizada.
43
3.3.3- Nível de base
Recomendado quando:
Observações:
3.5.1 - Globais
Minimize o seu uso, já que são variáveis que ocupam bastante memória e não são desalocadas entre um
forms e outro. Muito usadas para passagem de parâmetros entre forms podem ter esta funcionalidade
substituídas por parâmetros. Quando utilizadas como globais dentro de um forms pode se usar as
variáveis de canvas null para se obter a mesma funcionalidade. Se houver necessidade apague as
variáveis ao termino do seu forms de forma a economizar memória.
Observações:
São control-itens definidos em blocos de um forms sem uma canvas associada. Podem ser usados com
mais eficiência no lugar de globais para variáveis que necessitem ter sua visibilidade possível por todo
um forms.
44
Deve se tomar cuidado pois o conteúdo das mesmas é apagado quando se limpa o forms.
45
Observações:
3.5.3- Internas de PL
Variáveis declaradas em triggers ou procedures tem seu escopo definido somente para o bloco PL/SQL
onde foram declaradas e seus sub-blocos. Não são compartilhadas entre triggers e rotinas.
3.5.4- Parâmetros
Devem ser usados sempre que possível como meio de se passar dados entre forms, seu uso é mais
eficiente que o de variáveis globais, porem não é possível usá-los para retornar informações de um form.
Para um forms utilizar parâmetros os mesmos devem ter sido criados a nível de design no forms destino e
uma lista de parâmetros compatível deve ser criada via programação no forms origem.
Exemplo:
DECLARE
pl_id PARAMLIST;
pl_name VARCHAR2(10) := 'tempdata';
BEGIN
pl_id := GET_PARAMETER_LIST(pl_name); -- Crio lista de parâmetros
IF ID_NULL(pl_id) THEN
pl_id := CREATE_PARAMETER_LIST(pl_name);
END IF;
46
Dentro do forms criar lista de parâmetros correspondente dentro da opção FORM-> PARAMETER.
Observação:
Todo forms possui uma lista de parâmetros pré definida que representa seus próprios parâmetros
definidos a nível de design, assim para se repassar seus parâmetros para outra aplicação pode se usar o
seguinte código:
Caso seu forms necessite uma utilização freqüente de DATA e hora evite a utilização de SYSDATE a toda
hora. O uso de sysdate emite uma chamada ao banco de dados, utilize uma única chamada no inicio do
forms e utilize a variável global no local de sysdate dentro de seu código PL/SQL
When-new-form-instance
:global.DATA_atual=TO_CHAR(SYSDATE,’DD-MON-YY’);
:DT_LANC = TO_DATE(:global.DATA_atual);
Caso seja importante o fator tempo dentro da hora acessada, pode se utilizar a seguinte procedimento:
47
2) Crie a seguinte função
A Função MYSYSDATE pode agora ser utilizada no lugar da SYSDATE evitando tráfego de rede e
requisições ao banco de dados a cada chamada. A variável global :global.threshold é utilizada como
tempo de refresh, sempre que a diferença entre chamadas ultrapassar o seu valor em minutos.
Esta alternativa ao SYSDATE só se compensa quando um número grande de chamadas a DATA e hora for
requisitado dentro de um processamento.
Regra:
Nunca utilize em seu sistema a variável de sistema :SYSTEM.CURRENT_DATETIME, ela retorna a hora
de sua máquina (PC), uma hora não confiavel que o usuário pode ter alterado via painel de controle do
windows ou comando DATE do DOS.
3.7- LISTA DE VALORES (LOV)
· Não utilize LOVs para mais de 3000 linhas de retorno.
Para um LOV ser mostrado na tela, todo o conteúdo do select é armazenado em arquivo
temporário na estação para depois ser apresentado ao usuário. Em consultas muito grandes a
criação de um bloco base-table separado para consulta ( no mesmo ou em outro forms) se
torna mais eficiente no momento que se pode parametrizar um buffer maior de memória e
que o resultado já é apresentado ao usuário após o primeiro bloco de linhas ser carregados do
banco de dados, não precisando que toda a tabela resultado seja transferida para que o
usuário tenha um retorno e permitindo tambem a utilização de modo ENTER-QUERY.
· Long List
Outra alternativa para LOV’s em grande massa de dados é a utilização do parâmetro long
list. Quando este parâmetro esta configurado o filtro básico que todo LOV apresenta é
disponibilizado para o usuário antes da execução do mesmo, deste modo a query enviada
para o server passa a conter uma condição de where de modo a diminuir o numero de linhas
da tabela resultado.
Utilize quando o número de linhas retornado for maior que 200 linhas.
48
· Auto Refresh
Desligue esta opção para LOVs em tabelas não muito dinâmicas. Pode-se popular o LOV
uma única vez de modo que na primeira chamada ao LOV a query é executada e em
chamadas subsequentes os dados já existentes na estação cliente são aproveitados não
executando novas chamadas ao banco de dados.
É possível que um único record-group alimente vários LOVs, deste modo pode-se otimizar o
uso de memória na estação criando um record-group com todas as colunas utilizadas para
pesquisa em uma aplicação e vários LOVs com mapeamento de colunas diferente em cima
deste record-group.
Caso um campo tenha um LOV anexado, utilize o para validação quando o número de linhas
retornada for menor que 200 linhas setando atributo do campo ao invés de se re-executar
uma consulta ao banco de dados numa trigger when-validate-item. No momento que o
domínio do campo já esta disponível na estação dentro do record-group do LOV, não é
necessário uma nova query ao banco de dados.
· Ao usar LOVs para validação a coluna mais a esquerda é utilizada como teste.
3.8.1-Key-<TECLA>
As triggers KEY-<TECLA> são disparadas quando uma tecla física (KEY-F1) ou lógica (KEY-
DELREC) é apertada. Numa redefinição de uma tecla que tenha uma funcionalidade pré-definida deve se
incluir a built-in correspondente para se manter a função básica, já que esta funcionalidade se perde com
a definição da trigger.
Exemplo:
Trigger: Key-down
begin
:global.conta:= TO_NUMBER(:global.conta) + 1; -- ADICIONO FUNCIONALIDADE
down; -- FUNCIONALIDADE DEFAULT
end;
3.8.2- Key-others
Deve-se tomar cuidado com o uso da KEY-OTHERS , esta trigger anula todas as funcionalidades default
das teclas do forms. Qualquer tecla KEY-<TECLA> que não tenha uma trigger definida fica anulada e
causa o disparo da KEY-OTHERS.
49
3.8.3- Do-key
Utilize a trigger DO-KEY para disparar ações correspondentes a teclas ao invés de ativar as built-ins
diretamente. Deste modo, pode se manter o código correspondente às ações das teclas centralizado nas
triggers correspondentes.
Exemplo:
Trigger Key-delrec
BEGIN
:global.conta:= TO_NUMBER(:global.conta) + 1; -- ADICIONO FUNCIONALIDADE
DELETE_RECORD; -- FUNCIONALIDADE DEFAULT
END;
Código PL/SQL
BEGIN
IF :in_status = ‘S’ THEN
DO_KEY(‘DELETE_RECORD’); -- AO INVES DE “DELETE_RECORD”
END IF;
END;
Observação:
A trigger chama a própria built-in caso não haja nenhuma trigger definida para a mesma.
3.8.4 Post-change
Não a utilize. Esta trigger existe para compatibilidade com versões anteriores e será descontinuada em
futuras versões do forms. Em seu lugar utilize as triggers WHEN-VALIDATE-ITEM e POST-QUERY.
3.8.5- When-new-???-instance
Este grupo de triggers são a alternativa para se usar as procedures restritas que são proibidas a nível de
triggers PRE- e POST-. Lembre-se que ela é disparada ao término de um processo de navegação quando
o campo destino recebe o cursor (foco), não sendo disparada a nível de programação (passar pelo campo
via go_item) e que em caso de falha da trigger (RAISE FORM_TRIGGER_FAILURE) o foco não volta
para o campo de origem da navegação.
3.8.6- When-validate-item
Utilize para adicionar validação a um item quando a regra de validação envolvida não depender de outros
campos do mesmo bloco.
A trigger só é disparada quando se “passa” pelo item ou uma validação do bloco é efetuada, não
disparando quando o conteúdo do campo é modificado via programação ou carregado por um LOV
quando o cursor estiver em outro campo.
50
3.8.7- When-validate-record
Utilize para adicionar validação a um item quando a regra de validação envolvida depende de outros
campos do mesmo bloco.
A trigger só é disparada quando se “sai” do registro corrente. Para forcar a validação do bloco utilize a
built-in ENTER.
3.8.8- Post-query
Utilize para popular campos de controle dentro de um execute query, é importante lembrar que em caso
de erro na trigger a linha da tabela que disparou a trigger não é mostrada na tela.
Exemplo:
BEGIN
SELECT nm_depto into :blk1.nm_depto FROM depto
WHERE cd_depto = :blk1.cd_depto;
END;
Esta trigger deverá traduzir os nomes de departamento dos funcionários num execute_query, porem caso
um funcionário não tenha um código de departamento válido a execução da trigger causará erro o que
filtra-ra o registro da query sem que o usuário seja informado.
3.8.9- Pre-query
Utilize para adicionar condições de filtro ao bloco onde a query será executada. Esta trigger permite a
simulação do comando ENTER_QUERY, permitindo que se mova valores para os campos base table do
bloco de modo a servirem como filtros adicionais para a query a ser executada.
Qualquer outra trigger que mover valores para os campos do bloco causará a mudança de status do bloco
para INSERT ou CHANGED, o que pediria uma confirmação de alteração dos dados para um eventual
COMMIT antes de uma execução de query.
As triggers post/pre-insert, post/pre-delete e post/pre-update não são disparadas quando se insere, exclui
ou altera registros em seu forms, e sim após um comando commit_form onde todas as alterações são
efetivadas de uma só vez.
Para cada registro de seu forms cujo status esteja como CHANGED será disparada o conjunto de triggers
da ação correspondentes, assim se 4 registros forem alterados será disparada 4 vezes as triggers pre/post-
update.
51
3.9 - INTEGRAÇÃO COM BASE DE DADOS
O Oracle forms permite uma integração com o banco de dados através dos blocos base-table, estes blocos
criam links com tabelas do database facilitando o processo de atualização e consulta a base de dados.
Todo o controle de geração de SQL tanto para recuperar os dados do servidor ou para a geração das
alterações efetuadas pelo usuário ficam a cargo do forms, baseados nas propriedades dos itens do bloco e
nas propriedades “where” e “order by” do próprio bloco.
A medida que o usuário paginar para novos registros que ainda não tiverem sido carregados do server o
forms ira transferi-los do server sempre em numero igual a FETCHED de modo a minimizar o trafego de
rede aproveitando dos recursos de array processing do Oracle e caso o número de linhas da tabela
resultado for maior que o parâmetro especificado em BUFFERED, o Oracle ira armazena-los em
arquivos temporários no file system do cliente.
Deste modo, é preciso tomar cuidado com espaço em disco já que se um bloco base-table executar um
execute_query sem restrições e o usuário emitir um last_record, toda a tabela será transferida para a
estação.
Evite tambem a built-in LAST_RECORD ela forçara todos os fetchs numa única vez o que causara uma
espera maior para o comando ser executado.
· Não utilize a técnica de se trabalhar com bloco não base-table e se carregar as linhas das tabelas
utilizando-se de PL/SQL via SELECT INTO e built-in DOWN num loop de modo a popular os
registros e efetuar depois as alterações na base de dados manualmente via programação.
52
Não há justificativa para tal procedimento, o mesmo não deve ser utilizado já que:
à Os selects não iriam aproveitar a característica de array processing do oracle (propriedade FETCHED)
tornando a busca dos dados extremamente mais lenta.
à Não haveria controle eficiente de locks quando uma linha fosse alterada pelo usuário
à Uma codificação muito mais complexa teria que ser produzida de modo a gerar todos os controles de
alteração já disponibilizados pela ferramenta.
à Toda a tabela teria que ser carregada na estação antes que a tela fosse liberada ao usuário
Deve se escolher uma tabela drive que se tornará a tabela ligada ao bloco. Os campos de outras tabelas
podem ser populados na trigger POST-QUERY sendo que alterações em outras tabelas que não sejam a
tabela drive podem ser codificadas nas triggers de transação PRE- e POST- ( Delete, Insert, Update).
· Nunca popule uma tabela base table de outra forma que não seja via built-in EXECUTE_QUERY.
Uma linha populada via SELECT INTO num bloco base-table ira gerar uma inserção quando um
COMMIT_FORM for executado.
· Não processe manualmente nenhum comando de DML na tabela driver dentro de um bloco base-table
(INSERT, DELETE ou UPDATE). O forms ira efetuar toda as inserções, alterações e deleções
necessárias quando a built-in COMMIT_FORM for acionada.
Em uma relação pode-se minimizar o tráfego na rede e chamadas ao banco de dados configurando de
forma adequado os parâmetros DEFERRED e AUTO-QUERY .
Isto evita que ao paginar no bloco pai de modo a localizar um registro, chamadas sejam feitas ao banco
de dados executando-se queries para popular o bloco detalhe em registros que não são alvos da pesquisa
desejada pelo usuário.
O modo ENTER-QUERY permite que o usuário faça consultas por qualquer campo do forms. Consultas
em bases muito grande podem se tornar demoradas caso o usuário selecione para consulta campos onde
não existam índices nas colunas especificadas.
Bloqueie as consultas em campos não definidos junto ao usuário como passíveis de consultas via
propriedade QUERY ALLOWED.
53
3.9.5- Blocos base-table baseado em view’s
Quando a definição da tabela drive num bloco base table não for muito clara gerando a necessidade de se
popular várias colunas via PL/SQL pode se optar pela criação de uma view no banco de dados e
informar esta view como base-table do bloco. Este procedimento evita os “sub-selects” via PL/SQL,
trocando-os por um join que é totalmente processado no servidor e aproveitando a facilidade de array
processing que o forms proporciona.
Uma view com join se torna read-only, deste modo as transações não podem ser efetivadas
automaticamente pelo form. Deve-se criar as triggers ON-INSERT, ON-DELETE e ON-UPDATE que
anulam o processamento default do forms evitando tentativas de alteração na view read-only.
O procedimento de alteração nas tabelas que compõe a view deve ser codificada em código PL/SQL
dentro destas triggers. Deve se usar a trigger ON-LOCK para, tambem manualmente, bloquear os
registros nas tabelas dependentes da view.
Para isso utilize o parametro STATISTICS=true na linha de comando ao invocar o forms. Este parametro
tem a mesma funcionalidade de se emitir o comando ALTER SESSION SET SQL_TRACE = TRUE
· CALL_FORM
O primeiro form fica na memória, enquanto o segundo form fica ativo e ao termino da execução o
controle volta ao form de origem. É a maneira mais comum de se utilizar o encadeamento de forms já
que normalmente este retorno é desejado
· NEW_FORM
O primeiro form sai do ar liberando a memória utilizada e não há uma volta automática ao form de
origem quando um EXIT_FORM é emitido no form filho. Deve ser utilizada quando não há necessidade
de se retornar ao form de origem automaticamente já que seu gasto de memória é bem menor.
· RUN_PRODUCT
Pode ser tambem utilizada para chamar outro forms, seu uso é indicado quando se deseja abrir uma nova
seção no oracle de modo a se ter transações independentes.
54
Observações
· Variáveis globais não são compartilhadas entre forms chamados por RUN_PRODUCT já que eles
trabalham em sessões independentes.
A) Se as alterações tiverem sido feitas via blocos base-table e já tiverem sido enviadas ao banco
de dados via comando POST as mesmas serão confirmadas.
B) Se as alterações tiverem sido executadas via comandos de DML dentro de PL/SQL não há a
necessidade de POST logo serão executadas tambem.
2.12.1- Não execute comandos de DDL via built-in FORMS_DDL ou sql dinâmico quando existirem
transações pendentes no seu forms. Qualquer comando de ddl emitido implica num commit o que
liberaria os locks no servidor antes das alterações terem sido enviadas ao forms.
2.12.2- Antes de se chamar um novo forms emita um comando POST caso possa haver transações
pendentes no form de origem. Caso um form filho tente executar um commit_form e este tenha
sido chamado de um form com transações não enviadas ao server ( “posted”) um erro ira ocorrer.
2.12.3- Uma alteração em um control item (não base-table) de um bloco base-table não implica num lock
na linha da tabela de origem. Para que estes itens bloqueiem o registro é necessário que se marque a
propriedade do control item chamada LOCK RECORD.
55
3.13 - BUGS COMUNS NO AMBIENTE FORMS.
Estes bugs normalmente são detectados pelo suporte Oracle e catalogados de acordo
com a ferramenta e o ambiente em que foi detectado. A área de suporte recebe da
oracle um CD-ROM chamado “Oracle Suport Notes” em que estes bugs são
catalogados e seu status atual informado.
A utilização de campos varchar2 com mais de 1600 caracteres pode acarretar GPFs dentro de INSERTs e
UPDATEs dentro de PL/SQL. Se você levar GPF numa procedure e ao isolar o erro detectar que um
comando INSERT ou UPDATE é o causador, verifique a existência de campos VARCHAR2 muito
grandes.
Para resolver troque este campo por 2 ou mais campos varchar2 menores e concatene na hora da inserção
ou update.
Exemplo:
:blkaux.obs1:=SUBSTR(:blk1.observação,1,1000); -- Divido o campo em campos menores
:blkaux.obs2:=SUBSTR(:blk1.observação,1001,1000); --
UPDATE TABELA
SET txt_obs = :blkaux.obs1||:blkaux.obs2 -- Substituo a linha que dava GPF
WHERE ID=27
Caso uma library ao ser aberta esteja em modo read-only, verifique se seu working directory está
apontado para um diretório de rede, isto causa a abertura da biblioteca somente para leitura. Indique
como diretório de trabalho seu disco local que o problema será resolvido.
Tome cuidado para sempre escolher qual dos rádios será alterado para não perder o conteúdo de seu
forms por causa do GPF.
56
3.13.4- Sinônimos de database link
Ao utilizar DATABASES LINK dentro de PL de seu forms não utilize sinônimos para eles. O PL/SQL do
forms não reconhece o sinônimo e dará erro informando que a tabela não existe. Utilize explicitamente o
database link quando for necessário acessar tabelas remotas.
Ao utilizar a built_in raise_aplication_error dentro de uma stored procedure não é possível capturar
dentro do forms o código e a mensagem do erro informado pela stored procedure via
DBMS_ERROR_CODE e DBMS_ERROR_TEXT.
Quando o espaço em disco não é suficiente, um lov pode não trazer todas as linhas da tabela original. O
oracle forms mostra somente o que pode ser carregado não informando que a lista esta incompleta.
Este erro é causado por um duplicidade interna de itens ID gerados devido a algum problema na hora de
se salvar o forms. É possível recuperar o forms salvando-o como texto (FMT) e procurando o item com
duplicidade para uma alteração manual.
Ao passar parâmetros para um report via built-in run_product os mesmos são convertidos para
maiúsculas
Se um objeto desaparecer de sua canvas dentro do design tente fechar seu layout editor e abri-lo
novamente pois em certas ocasiões podem ocorrer problemas de refresh de tela.
Caso o problema persista, verifique as propriedades do item e configure as coordenadas e tamanho para
uma posição visível em seu canvas.
57
4-REPORT 2.0 - CONCEITOS E GUIA DE UTILIZAÇÃO
Existem 2 caminhos que podem ser utilizados quando se trabalha no report em relatórios tipo master
detail ou que necessitem mais de um grupo de informações correlacionadas.
1- Uma única query onde as tabelas são “joined” de modo a se ter todos os dados existentes e desta query
se criar mais de 1 grupo.
Onde Q_3 é
2- Varias queries simples com um único grupo ligadas por links no datamodel.
58
Onde:
Q_1 é
SELECT deptno, dname
FROM DEPT
e Q_2 é
Ambas as opções geram o mesmo número de grupos com as mesmas informações necessárias para a
montagem do relatório. Apesar da segunda opção normalmente facilitar o entendimento, é recomendado
que se diminua ao máximo o número de queries do report de modo a melhorar a performance.
· Opte por 1 query com vários grupos na grande maioria dos casos. É mais eficiente e gasta menos
recursos do Oracle no momento em que abre somente um cursor.
· Utilize 2 ou mais queries somente quando a tabela pai retornar muito poucas linhas ( < 5) e o
conteúdo de suas colunas selecionadas ocuparem um grande espaço. Isto aumentaria o custo de se
replicar estas colunas por toda a tabela resultado gerada pelo join.
O Oracle Reports permite que utilize os chamados parâmetros léxicos de modo a se definir as queries a
serem utilizadas a tempo de runtime de acordo com parâmetros especificados pelo usuário. Esta
facilidade permite que se construa queries mais simples e com menos objetos ao invés de se ter que
selecionar todas as colunas possíveis fitrando-as no LAYOUT e tambem evita cláusulas where complexas
de modo a atender os parâmetros selecionados.
59
Exemplos do uso de parâmetros léxicos
Report (Query):
Como vemos no exemplo o mesmo report (query) pode ser utilizado tanto para uma listagem de
funcionários que ganhem menos que 2000 como para listar os aniversariantes do mês.
· Incluir um valor default nos parâmetros léxicos de modo a se criar os grupos no design.
· Não usar colunas substituídas por parâmetros léxicos em links com outras queries.
· Parâmetros léxicos tem que estar preparados antes da fase do parse, ou seja até a trigger
AFTER_FORM inclusive.
· Podem ser usados em qualquer parte do select inclusive nas clausulas from, order by, group by.
· Um parametro léxico pode conter mais de uma coluna. Deve se manter em tempo de execução o
mesmo número de colunas criados a nível de design.
Pode se passar de dentro de um forms um record-group carregado de modo a substituir uma query de um
report. Para isso deve se incluir na lista de parâmetros passado ao report um parametro do tipo
DATA_PARAMETER, cujo nome deva ser o nome da query que ele ira substituir no report.
Exemplo:
pl_id := CREATE_PARAMETER_LIST('tmpdata');
/*
Adiciono um DATA PARAMETER que substituira a query EMP_QUERY pelo record group EMP_RECS
*/
ADD_PARAMETER(pl_id,'EMP_QUERY',DATA_PARAMETER,'EMP_RECS');
/*
** Inicio o relatório
*/
RUN_PRODUCT ( REPORTS, 'empreport' , SYNCHRONOUS, RUNTIME,
FILEYSTEM, pl_id , NULL);
60
É possível que se crie um relatório somente baseado em record groups gerados pelo forms, neste caso se
não existirem comandos SQL dentro do PL/SQL não haverá a necessidade do report se conectar ao banco
de dados. Para evitar o logon ganhando em performance deve se incluir na lista de parâmetros passado ao
report o parâmetro “logon” com o valor “no”.
Exemplo:
ADD_PARAMETER(pl_id,'LOGON',TEXT_PARAMETER,'NO’);
O record group criado deve manter a mesma estrutura da query a ser substituída. Deve se manter o
mesmo número de colunas e tipo de dados.
61
Observações
· Qualquer comando de DDL que altere algumas das queries do report tem que ser executado
antes do passo 4 nas triggers BEFORE-FORM e AFTER-FORM , nestas triggers o
relatório ainda não foi compilado e as queries não foram “parsed”.
· Idem para qualquer construção ou alteração de parâmetros léxicos que serão usados para as
montagens das queries do DATA MODEL.
· Caso o relatório esteja sendo executado em modo readonly não execute comandos que
causem commits como DDLs dentro das triggers BETWEEN-PAGE, pois um commit
acaba com a transação readonly.
· A trigger BETWEEN-PAGE é executada entre cada página FORMATADA pelo report. Não
há garantias da ordem em que as queries são executadas e os dados “fetched”, pois o
processo de execução dos sql não é síncrono com a formatação.
Segue algumas regras que devem ser observadas e tidas como metas na criação de um report.
1.3.1 Evite truncar campos no LAYOUT. Utilize SUBSTR nos select das queries quando
necessário.
1.3.1 Só selecione campos que serão utilizados no LAYOUT ou para cálculos de fórmulas.
Verifique ao término de um report se existem colunas em grupos do data model
que não sejam utilizados pelo LAYOUT. Evite queries com “SELECT * “
1.3.1 Evite a utilização de filtros dentro dos grupos. Utilize a condição de where das queries
para isso sempre que possível.
1.3.1 Um campo de fórmula só enxerga colunas de seu grupo ou de grupos acima. Não utilize
em fórmulas campos de grupos filhos ou de queries não correlacionadas
1.3.1 Informe um apelido para as colunas que existirem em mais de uma query dentro de seu
DATA MODEL. Isto evitará que o report crie nomes para estas colunas nos grupos
e que em futuras alterações desta query este nome se modifique, criando
incompatibilidade com o LAYOUT definido.
62
1.3.1 Caso uma query de seu DATA MODEL só venha a ser utilizada em determinadas
situações, defina a propriedade MAXIMUM ROWS para 0 (ZERO) dentro da
trigger AFTER-FORM de modo a só processar a query desejada.
Exemplo:
IF :p_flag != 1 THEN
SRW.SET_MAXROW ('Q_STOCKS', 0);
ELSE
SRW.SET_MAXROW ('Q_BONDS', 0);
END IF;
1.3.1 Uma única estrutura do DATA MODEL pode alimentar mais de um único LAYOUT, isto
é 2 ou mais repeating frames podem ser alimentadas por um único grupo do
DATA MODEL. Caso seu relatório exiba layouts alternativos, crie uma única
estrutura no DATA MODEL e crie 2 repeating frames com os layouts desejados,
controlando a escolha via triggers de formatação em cima das repeating frames.
1.3.1 Não utilize frames e objetos sólidos da cor branca. Utilize objetos transparentes no lugar.
Apesar da impressão sair em branco, existe o trabalho na formatação de
“preencher” estes espaços o que causa uma queda na performance e maior
consumo de memória.
1.3.1 Retire frames desnecessárias geradas pelo default LAYOUT. A opção default LAYOUT
gera fixed frames envolta da maioria das áreas de objetos (headers, repeating
frames, etc..) e que muitas vezes não são relevantes para a formatação.
Entendendo a estrutura necessária para seu report retire as frames desnecessárias já que
qualquer objeto a mais sobrecarrega o processo de formatação da página.
1.3.1 Evite utilizar a opção total de páginas em seu relatório ( Ex: Pagina 1 de 30 ). Para o
report calcular o número total de páginas ele formata todo o relatório primeiro
salvando todo o conteúdo em disco para depois imprimir. Esta opção degrada o
processo alem de requerer área temporária na estação.
1.3.1 No caso de se utilizar uma imagem no report, utilize a opção “Reduce Image resolution” .
Esta opção diminui a resolução de uma imagem quando a mesma tem sua escala
reduzida para se adequar ao layout do relatório.
1.3.1 Evite o uso da built-in SRW.DO_SQL dentro de PL/SQL. Ela é menos eficiente que o uso
direto dos comandos dentro do PL e requer um PARSE a cada chamada em tempo
de execução. Use somente quando o objeto acessado não existir em tempo de
runtime.
1.3.1 Não utilize tabelas temporárias criadas dentro do report. Caso seja necessário crie a tabela
com parâmetros ótimos de storage uma só vez e no relatório emita um
TRUNCATE TABLE ao inicio do mesmo. Caso o número de linhas desta tabela
forem significativas utilize a package do banco
DBMS_DDL.ANALYZE_OBJECT(‘TABLE’, owner, tablename , ‘ESTIMATED’)
de modo a colher estatísticas para o otimizador por custo.
1.3.1 O Default LAYOUT apaga um LAYOUT já alterado pelo desenvolvedor. Uma vez que
seu LAYOUT tenha sido alterado manualmente qualquer alteração no DATA
MODEL deve ser codificada tambem manualmente dentro do editor de LAYOUT.
1.3.1 A opção de default LAYOUT “Use current layout settings” não funciona, portanto não
deve ser utilizada.
63
4.4- MONITORANDO PERFORMANCE
Para se ativar o SQL TRACE de modo a utilizar o TKPROF insira um campo fórmula a nível de
report cujo valor seja :
4.4.2- PROFILE
O oracle reports pode gerar um arquivo com estatísticas sobre sua exceção no ambiente do cliente. Para
isso deve se ativar a opção PROFILE no menu do report design (RUNTIME SETTINGS) ou como
parâmetro para o run report (PROFILE=nomearq.txt).
Onde:
· Total Elapsed Time é o tempo total gasto entre a execução do R20RUN e o término do relatório
· Oracle Reports Time é o tempo gasto na ferramenta cliente
· Oracle Time é o tempo gasto no servidor, onde
· Total CPU é o tempo gasto com CPU para todo o processo . Disponível quando a opção de estatísticas
de tempo estiver habilitada no servidor.
64
4.5- REPORT CHARACTER MODE
A geração de um report em character mode na versão 2.0 do report deve ser utilizada para uso dentro do
ambiente do servidor (Unix). No ambiente windows não se pode usar o report para geração de relatórios
ou arquivos seqüenciais ASCII (char mode). No ambiente windows não é possível a geração em disco de
um arquivo seqüencial com a saída do mesmo.
Um relatório em character mode pode porem ser desenvolvido e testado no ambiente windows e
transferido o RDF via ftp para o ambiente unix de modo a roda-lo no servidor. Deve se observar os
seguintes pontos:
· Não utilize objetos gráficos como linhas, boxes, imagens, cores e shades.
Grande parte do tempo que um report leva é devido ao processo de formatação de suas páginas no
ambiente gráfico. Um relatório é candidato a ser rodado em character mode quando não há a necessidade
de um acabamento mais requintado em sua apresentação. Relatórios para conferencia de dados, relatórios
legais e listagens muito grandes ( estoques, lançamentos contábeis, etc..) devem de acordo com a
disponibilidade do server serem rodados em character mode.
Outro uso é quando se tem a necessidade de gerar arquivos em meios magnéticos para interfaces com
outros sistemas.
Rodar um relatório no servidor é indicado quando o processamento de um report é muito pesado para ser
realizado em uma estação. O processo de formatação e impressão de relatórios pode ser demorado, o que
prenderia a estação durante o processamento.
No servidor pode-se rodar tanto relatórios character mode como gráficos ( ambiente motif). A decisão de
se transferir o processamento para o servidor deve seguir as seguintes premissas:
65
4.7- PRINCIPAIS BUG’S NO AMBIENTE REPORT.
Alguns dos bugs mais comuns dentro do Oracle report:
Uma grande causa de GPFs no ambiente reports é a falta de área em disco para a geração de arquivos
temporários. Certifique-se que existe uma variável de ambiente TMP=C:\TMP ou para qualquer
diretório que será utilizado para áreas temporária e que exista área suficiente para os arquivos
temporários. Caso um GPF aconteça libere o maximo de espaço em disco na área temporária e rode o
relatório novamente.
Obs.
Se seu relatório detectar loop infinito verifique se não existe alguma frame de tamanho fixo com um
objeto interno expansível (frames, text itens) que possa vazar a área da frame mais externas. Caso isso
aconteça um loop infinito pode ser gerado.
Se em seu report alguma frame sair totalmente negra ou “sólida” , verifique o driver da impressora
testando com outra impressora/driver. Muitas vezes alguma frame não transparente (branca) sai negra
bloqueando conteúdo de campos em drives de impressão mais antigos.
Se uma imagem em seu report não sair no relatório, procure verificar utilizando outros drivers de
impressão. Pode não haver memória suficiente para um impressão.
Para detectar o problema de impressão de imagens, gere o relatório para um arquivo gerando via driver
de impressora postscript e analise o arquivo gerado via um editor ou comando type. Uma impressão
postscrip é um arquivo texto com os comandos postscrips em forma de texto, deste modo um erro de falta
de memória na formatação da pagina é muitas vezes indicado dentro do mesmo, procure pela palavra
ERROR ou IMAGE.
Observação:
Outros erros menos comuns estão catalogados no CD-ROM “Oracle Suport Notes”.
66
5- PREVENÇÃO DE GPF’S
GPFs podem ocorrer se recursos do windows (memória, pilha interna, etc..) chegarem a níveis muito
baixos, por exemplo quando muitas aplicações estiverem abertas simultaneamente.
Feche todas as aplicações windows não necessárias e evite abrir e fechar a mesma aplicação varias vezes.
Algumas aplicações não liberam todos os recursos utilizados pelo windows ao seu término, deste modo
em cada utilização um pouco dos recursos é perdido.
2. Tente isolar o problema, rode a aplicação de outra maquina e se possível com outra chave de acesso.
Caso o erro não aconteça o problema é do seu ambiente, caso o erro se repita provavelmente é
algo em sua aplicação.
3. Se com a mesma chave ocorre o erro e com chaves diferentes não verifique permissão de gravação em
diretórios da rede.
67
5. No DOS Utilize os comandos
SET TEMP=C:\TEMP onde C:\TEMP é um diretório valido.
SET TMP=C:\TEMP
2. Remova se existir o arquivo SHARE.EXE de seu autoexec.bat. O driver deve estar carregado no
windows via arquivo SYSTEM.INI seção [386Enh] como vshare.386.
Exemplo:
SYSTEM.INI
----------
...
[386Enh]
display=*vdd,*vflatd
WinExclusive=0
...
device=vshare.386 <-Substituto do SHARE.EXE
...
Garanta que o arquivo vshare.386 existe no seu diretório windows/system.
BUFFERS=60,0
FILES=60
5. Caso o código isolado não apresente nenhum problema aparente, contate o suporte de modo a
verificar algum bug ou problema mais complexo.
68
6- HOMOLOGANDO UM APLICATIVO ORACLE
É necessário manter uma meta de se obter códigos eficientes do ponto de vista de performance e fontes
claros do ponto de vista de futuras manutenções.
Listamos a seguir alguns pontos que devem ser verificados pelo analista responsável no momento da
analise de um programa SQL, quer seja um batch pl/sql ou códigos de procedures e functions dentro de
forms e reports.
Um grande hábito que vem da época de outros ambientes e banco de dados é de se programar em um
banco relacional como se estivesse programando arquivos seqüenciais indexados.
Exemplo Lógica 1 .
Esta lógica pode ser usada em qualquer ambiente, de um Dbase até um Cobol/CICS passando pelo
PL/SQL, não é portanto uma lógica otimizada para os recursos que um banco relacional proporciona.
Supondo que :
Temos que nos itens 4 e 5 um total de 500.000 cursores serão abertos e fechados pelo oracle, o que trará
problemas de performance alem de impactar fortemente o tráfego da rede.
O ambiente relacional permite que se “crie” através de um join a tabela perfeita para sua aplicação dentro
de seu programa. Esta mudança minimiza o processamento pelo oracle , diminui o tráfego na rede e
simplifica bastante a lógica do programa evitando assim erros de lógica e uma maior facilidade para
manutenção posterior.
69
Exemplo Lógica 2.
A mudança da lógica leva quase todo o processamento para o passo 1 (Abertura do cursor), este
processamento é enviado de uma única vez ao oracle e somente 1 único cursor é aberto. Seu fonte se
torna menor, mais claro e eficiente.
Outra preocupação que os desenvolvedores devem ter é em relação a integridade dos dados em caso de
falha. É importante que os posicionamentos de commits não criem transações falhas e inconsistências na
base de acordo com as regras definidas para o sistema (Vide 1.7 Pag. 21).
Este cuidado deve ser aplicado em programas PL/SQL e em forms com mais de uma tela compondo uma
única transação.
Para testar seus programas aconselhamos: Que durante os teste de um PL/SQL, ou forms, mate-se a
sessão no servidor, ou desligue-se o micro no meio de um processamento. Este procedimento não poderá
acarretar nenhuma inconsistência na base ou problemas com campos de controle, já que é algo normal de
se acontecer no ambiente de produção e em equipamentos de usuário.
O Oracle não possui recursos automáticos de restart. É de competência do programador incluir esta lógica
em seus programas.
Os programas batch necessitam ter uma lógica de restart. No caso de uma falha do processamento, o
sistema tem que recomeçar do momento que parou. Evitando gastos de recursos necessários e volta de
backup para bases parcialmente atualizadas, sem o controle do que já foi processado.
Para testar um programa batch mate a sessão no meio do processamento e reinicie o mesmo a fim de
validar as rotinas de restart.
Outro erro muito comum em aplicações é assumir que um comando irá dar certo, quer seja traduzindo um
campo de uma tabela básica via select, uma atualização via update , obtenção de uma taxa, etc..
Tenha como regra que qualquer comando SQL pode falhar. Consequentemente, os programas tem que
estar preparados para isso.
70
Um processamento batch de 20.000 linhas pode ser interrompido, caso uma única linha encontre um
código cuja tradução, inesperadamente, provoque uma exception NO_DATA_FOUND. Proteja todos os
comandos SQL com tratamento de exceptions, de modo que todo e qualquer erro seja tratado, evitando
uma interrupção não esperada.
Cuidado com a trigger WHEN_OTHERS. Informe no log o código de erro (SQLCODE) e a mensagem
correspondente (SQLERRM).
Baseados nos tópicos apresentados, podemos analisar o exemplo fornecido como padrão de codificação
PL/SQL.
SPOOL &1
BEGIN
--
-- Programa FNM003 - Calculo de reajuste de funcionarios. - Logica 1
--
--Este programa varre a tabela de funcionarios atualizando o salario de acordo com índice encontrado na tabela de cargos,
-- caso este índice não seja encontrado o funcionario não tera aumento.
--
--
-- Historico do programa
-- Data Autor Mudancas
-- -----------------------------------------------------------------------------------------------------------
-- 01/04/95 Antonio Jose Entrega de programa para produção
--01/08/95 Antonio Jose Mudanca de acesso para update via ROWID
--01/12/95 Claudia Silva Exception NO_DATA_FOUND para tab_cargo incluido (sem taxa)
--
-- Rotinas utilizadas no programa ( Declaração foward ) -----------------------------------------------------------
CURSOR cur_tab_func IS
SELECT cod_func, val_salario,cod_cargo,cod_depto, ROWID
FROM tab_func;
wrk_val_taxa NUMBER;
wrk_val_sal_novo NUMBER;
71
--Implementação de procedures e functions ------------------------------------------------------------------------
wrk_ind_reajuste NUMBER;
BEGIN
SELECT
val_ind_reaj INTO wrk_ind_reajuste
FROM
tab_cargos
WHERE
cod_cargo = par_cod_cargo AND
cod_depto = par_cod_depto;
RETURN wrk_ind_reajuste;
EXCEPTION
WHEN NO_DATA_FOUND THEN
return 1;
WHEN OTHERS THEN
RAISE_APLICATION_ERROR(200002,’Erro acessando tabela de cargos’);
END calcula_taxa;
1. Para cada linha de cursor cur_tab_func um select é utilizado para calcular a taxa.
2. Possui uma transação muito longa, sem commits intermediários, o que alem de manter os locks por
mais tempo, pode acarretar problemas de roolback.
3. Não possui lógica de restart.
72
Podemos reestruturá-lo da seguinte forma:
Programa 2
SPOOL &1
BEGIN
--
-- Programa FNM003 - Calculo de reajuste de funcionarios. - Logica 1
--
--Este programa varre a tabela de funcionarios atualizando o salario de acordo com índice encontrado na tabela de cargos,
-- caso este índice não seja encontrado o funcionario não tera aumento.
--
-- Tabelas Acessadas Leitura Update Delete Insert
--TAB_FUNC x x
--TAB_CARGOS x
--TAB_CONTROLE x x
--
-- Historico do programa
-- Data Autor Mudancas
-- -----------------------------------------------------------------------------------------------------------
-- 01/04/95 Antonio Jose Entrega de programa para produção
--01/08/95 Antonio Jose Mudanca de acesso para update via ROWID
--01/12/95 Claudia Silva Exception NO_DATA_FOUND para tab_cargo incluido (sem taxa)
--0105/96 Antonio Carlos Mudanca da logica para join, commit a cada 200 registros e lógica de reestart
--
-- Rotinas utilizadas no programa ( Declaração foward ) -----------------------------------------------------------
73
-----------------------------------------------------------------------------------------------------------------------------------------------------------
PROCEDURE commita_bloco ( par_cod_func IN NUMBER) is
wrk_ind_reajuste NUMBER;
BEGIN
UPDATE tab_controle -- Tabela só tem um registro.
SET cod_func_reestart = par_cod_func; -- Atualizo o último funcionario processado.
Commit; -- Fecho a transação
EXCEPTION
WHEN OTHERS THEN
RAISE_APLICATION_ERROR(200002,’Erro commitando bloco’);
END commita_bloco;
BEGIN
-- Inicializo variavel de restart ---------
wrk_num_linhas:=0;
FOR wrk_reg IN cur_tab_func LOOP
atualiza_sal ( wrk_reg.ROWID, wrk_val_sal_novo);
wrk_num_linhas:= wrk_num_linhas + 1;
IF wrk_num_linhas > 200 THEN
commita_bloco(wrk_reg.cod_func);
wrk_num_linhas:=0;
END IF;
END LOOP;
COMMIT;
END;
/
EXIT SQL.SQLCODE
/
Como podemos observar, a lógica ficou menor. Temos implementado um bloco menor de transação
assim, como um controle de restart em caso de interrupção anormal do sistema.
74
6.2- CLASSIFICANDO OS MÓDULOS DE SUA APLICAÇÃO
É atribuição do analista responsável classificar os módulos de seu sistema nas classificações: baixa,
média e alta criticidade . Estes critérios irão permitir um melhor foco na fase de testes e homologação
das aplicações. Sugerimos abaixo critérios para a classificação dos módulos.
· Verificar se regras de negócio e a funcionalidade definida para a módulo estão de acordo com o
produto apresentado.
· Preenchimento das “Ficha de Controle de Qualidade - Aplicativos Oracle”.
· Utilização de explain sobre as queries mais importantes ( vide item 1.5.1 Pag 17).
· Verificação pelo analista responsável da lógica utilizada no programa.
· Utilização de TRACE/Tkprof dentro do ambiente de homologação acompanhado pelo AD/DBA
( vide item 1.5.2 Pag 18).
75
6.3- VERIFICANDO CONCEITOS APLICADOS
Aplicações definidas como tipo B e C devem ser validadas via ficha de Controle de Qualidade de
Aplicativos Oracle. Estas fichas contem um resumo das regras definidas neste documento e devem ser
preenchidas para cada módulo das aplicações a serem validadas.
1) Cabeçalho da Ficha
Este cabeçalho deve ser preenchido com dados sobre o módulo verificado.
2) Corpo da Ficha
Atende
Atende parcialmente
Não atende
Peso Conceito Pag.
Conceitos Gerais
Crie índices da coluna mais seletiva para a menos seletiva 10
Deve ser preenchido para cada critério especificado, onde cada coluna tem o seguinte significado:
· Peso
Esta coluna informa o peso do conceito para o ambiente <cliente>. Pode assumir os seguintes valores:
· Conceito
Resumo do conceito a ser observado no módulo, para maiores informações vide documento na pagina
indicada pela coluna PAG.
· Não Atende
Marque um X nesta coluna caso o módulo não atenda o item, indo contra o conceito especificado.
76
· Atende Parcialmente
Marque um X nesta coluna caso o módulo atenda parcialmente o item, com poucas ocorrências de
códigos que vão contra o conceito especificado.
· Atende
Marque um X nesta coluna caso o módulo atenda o item. Não existindo código que atue contra o conceito
especificado.
· Pag.
Esta coluna indica a página no documento onde se encontra uma explicação para o conceito indicado.
Observações:
77
EXEMPLO DE FICHAS DE CONTROLE DE QUALIDADE - APLICATIVOS ORACLE
78
Ficha de Controle de Qualidade - Aplicativos Oracle
Ambiente <cliente>
Atende
Atende parcialmente
Não atende
Peso Conceito Pag.
Conceitos Gerais
1 Deve se criar índices pelas foreignkeys de uma tabela. 10
1 Nas escolha de qual coluna deve ser utilizado em um índice escolha primeiro a coluna mais 10
freqüentemente utilizada em clausula where.
2 Uso database hints deve sempre acompanhado pelo AD/DBA , numa view utilize codificados 20
diretamente em seu fonte.
2 Utilize Explain plan para queries complexas 17
2 Utilize TRACE/TKPROF em ambiente de homologação para programas tipo críticos. 18
3 Crie índices da coluna mais seletiva para a menos seletiva 11
SQL
1 Clausula having somente para colunas calculadas via funções de coluna 15
1 Informe todas as ligações entre tabelas 13
1 Não armazenar rowid para uso em sessões posteriores 14
1 Sempre qualifique as colunas quando mais de uma tabela for envolvida 11
1 Usar order by quando for obrigatório resultado ordenado 13
2 Evitar operações dentro de funções de coluna 12
2 Evite DISTINCT 12
2 Evite between 16
2 Evite in (a,b,c) 16
2 Evite not in, utilize exists 16
2 Evite subselects, utilize joins 16
2 Evite where “CAMPO IS NULL” - não utilizara o índice 14
2 Armazene rowid para acesso a tabelas numa mesma sessão. 14
3 Agrupe primeiramente as condições de ligação entre tabelas e depois as condições de filtros 12
individuais em cláusulas WHERE.
3 Na clausula FROM apresente as tabelas na ordem das tabelas com mais linhas para as com 12
menos linhas
3 Criar apelidos (alias) para expressões 11
3 Procure utilizar sempre toda a chave de um índice composto 13
3 Se possível não aplique funções/Expressões em colunas da tabela 13
3 Use parênteses na clausula where 14
3 Uso do comando like pode não utilizar índices 13
Visto Responsável :
79
Avaliação de Critérios de programação - PL/SQL - Pag. 2/2
Atende
Atende parcialmente
Não atende
Peso Conceito Pag.
PL/SQL
1 Defina bem o conjunto mínimo de ações de uma transação 22
1 Evite dead locks atualizando tabelas sempre na mesma ordem 23
1 Feche os cursores quando não mais forem utilizados 33
1 Para comandos explícitos de lock consulta ao AD/DBA 23
1 Não utilizar commit em cursor for update 33
1 Não utilizar database hints em PL/SQL de FORMS e REPORT 20
1 Não utilize select from dual para utilizar funções SQL no PL 24
2 Estruture bem seus programas. Utilize procedures e functions 26
2 Evite abrir cursores dentro de loops de outros cursores 33
2 Evite transações muito curtas 23
2 Evite transações muito longas 22
2 Não faça grandes blocos PL/SQL, utilize códigos menores, menos de 100 linhas 26
2 Não use locks com cursor for update 34
2 Utilize foward declarations para procedures 27
2 Utilize operadores %TYPE e %ROWTYPE 26
2 Utilizar os mesmos tipos dados existentes no database para as variáveis: 25
3 Procure usar a estrutura de cursor loop 34
3 Utilize conversão explicita para variáveis 26
3 Utilize cursor explicito uma vez que é mais eficiente que utilizar cursor implicitamente 33
3 Padronize seu fonte PL/SQL 36
Visto Responsável :
80
Ficha de Controle de Qualidade - Aplicativos Oracle
Ambiente <cliente>
Atende
Atende parcialmente
Não atende
Peso Conceito Pag.
Conceitos Gerais
1 Deve se criar índices pelas foreignkeys de uma tabela. 10
1 Nas escolha de qual coluna deve ser utilizado em um índice escolha primeiro a coluna mais 10
freqüentemente utilizada em clausula where.
2 Uso database hints deve sempre acompanhado pelo AD/DBA , numa view utilize codificados 20
diretamente em seu fonte.
2 Utilize Explain plan para queries complexas 17
2 Utilize TRACE/TKPROF em ambiente de homologação para programas tipo críticos. 18
3 Crie índices da coluna mais seletiva para a menos seletiva 11
SQL
1 Clausula having somente para colunas calculadas via funções de coluna 15
1 Informe todas as ligações entre tabelas 13
1 Não armazenar rowid para uso em sessões posteriores 14
1 Sempre qualifique as colunas quando mais de uma tabela for envolvida 11
1 Usar order by quando for obrigatório resultado ordenado 13
2 Evitar operações dentro de funções de coluna 12
2 Evite DISTINCT 12
2 Evite between 16
2 Evite in (a,b,c) 16
2 Evite not in, utilize exists 16
2 Evite subselects, utilize joins 16
2 Evite where “CAMPO IS NULL” - não utilizara o índice 14
2 Armazene rowid para acesso a tabelas numa mesma sessão. 14
3 Agrupe primeiramente as condições de ligação entre tabelas e depois as condições de filtros 12
individuais em cláusulas WHERE.
3 Na clausula FROM apresente as tabelas na ordem das tabelas com mais linhas para as com 12
menos linhas
3 Criar apelidos (alias) para expressões 11
3 Procure utilizar sempre toda a chave de um índice composto 13
3 Se possível não aplique funções/Expressões em colunas da tabela 13
3 Use parênteses na clausula where 14
3 Uso do comando like pode não utilizar índices 13
Visto Responsável :
81
Avaliação de Critérios de programação - FORMS Pag. 2/3
Atende
Atende parcialmente
Não atende
Peso Conceito Pag.
PL/SQL
1 Defina bem o conjunto mínimo de ações de uma transação 22
1 Evite dead locks atualizando tabelas sempre na mesma ordem 23
1 Feche os cursores quando não mais forem utilizados 33
1 Para comandos explícitos de lock consulta ao AD/DBA 23
1 Não utilizar commit em cursor for update 33
1 Não utilizar database hints em PL/SQL de FORMS e REPORT 20
1 Não utilize select from dual para utilizar funções SQL no PL 24
2 Estruture bem seus programas. Utilize procedures e functions 26
2 Evite abrir cursores dentro de loops de outros cursores 33
2 Evite transações muito curtas 23
2 Evite transações muito longas 22
2 Não faça grandes blocos PL/SQL, utilize códigos menores, menos de 100 linhas 26
2 Não use locks com cursor for update 34
2 Utilize foward declarations para procedures 27
2 Utilize operadores %TYPE e %ROWTYPE 26
2 Utilizar os mesmos tipos dados existentes no database para as variáveis: 25
3 Procure usar a estrutura de cursor loop 34
3 Utilize conversão explicita para variáveis 26
3 Utilize cursor explicito uma vez que é mais eficiente que utilizar cursor implicitamente 33
3 Padronize seu fonte PL/SQL 36
FORMS
1 Bloqueie as consultas em campos não definidos junto ao usuário como passíveis de consultas 52
1 Empacote códigos comuns em procedures 41
1 Não mesclar em uma única LIB rotinas especificas para forms e report 43
1 Não processe manualmente nenhum comando de DML na tabela driver dentro de um bloco 52
base-table (INSERT, DELETE ou UPDATE)
1 Não utilize LOVs para mais de 3000 linhas de retorno. 47
1 Não utilize nomes de procedures e objetos do forms com o mesmo nome de objetos do banco 41
de dados
1 Nunca popule uma tabela base table de outra forma que não seja via built-in 52
EXECUTE_QUERY
1 Utilize a rotina exec_form_menu para chamar um forms de um menu ou outro forms 53
1 Não faça libs muito grandes, divida em libs menores com procedimentos afins 43
Visto Responsável :
82
Avaliação de Critérios de programação - FORMS Pag. 3/3
Atende
Atende parcialmente
Não atende
Peso Conceito Pag.
FORMS (cont)
2 Não utilize a técnica de se trabalhar com bloco não base-table e se carregar as linhas das 51
tabelas utilizando-se de /SQL
2 Antes de se chamar um novo forms emita um comando POST 54
2 Evite a built-in LAST_RECORD. 51
2 Evite triggers muito grandes 40
2 Não utilize trigger Post-change 49
2 Não crie em um único forms várias windows e várias funções distintas 41
2 Referencie a objetos do forms prefixando o nome do bloco 41
2 Utilize a trigger DO-KEY para disparar ações correspondentes a teclas ao invés de ativar as 49
built-ins diretamente
2 Utilize opção long list para LOVs com mais de 200 linhas 47
2 Não crie procedure ou trigger com mais de 100 linhas 41
3 Evite a utilização de SYSDATE a toda hora 46
3 Evite acessar diretamente dados externos em procedures, utilize os parâmetros IN e OUT 42
3 Forms deve estar preparado para tratar eventos possíveis 40
3 Mantenha seus códigos pl/sql organizados em procedures e functions 40
3 Não use auto-refresh em LOVs 48
3 Use LOV para validação quando o número de linhas retornada for menor que 200 linhas 48
3 Prefira variáveis de canvas null a variáveis globais 44
3 Use parâmetros para passar informações entre forms 45
3 Utilize MESSAGE() junto com SYNCHRONIZE, 42
3 Utilize sempre que possível as opções DEFERRED=TRUE e AUTO-QUERY=TRUE em uma 52
relação
3 Utilize somente as cores das 2 colunas mais a esquerda da pallete de cores 42
Visto Responsável :
83
Ficha de Controle de Qualidade - Aplicativos Oracle
Ambiente <cliente>
Atende
Atende parcialmente
Não atende
Peso Conceito Pag.
Conceitos Gerais
1 Deve se criar índices pelas foreignkeys de uma tabela. 10
1 Nas escolha de qual coluna deve ser utilizado em um índice escolha primeiro a coluna mais 10
freqüentemente utilizada em clausula where.
2 Uso database hints deve sempre acompanhado pelo AD/DBA , numa view utilize codificados 20
diretamente em seu fonte.
2 Utilize Explain plan para queries complexas 17
2 Utilize TRACE/TKPROF em ambiente de homologação para programas tipo críticos. 18
3 Crie índices da coluna mais seletiva para a menos seletiva 11
SQL
1 Clausula having somente para colunas calculadas via funções de coluna 15
1 Informe todas as ligações entre tabelas 13
1 Não armazenar rowid para uso em sessões posteriores 14
1 Sempre qualifique as colunas quando mais de uma tabela for envolvida 11
1 Usar order by quando for obrigatório resultado ordenado 13
2 Evitar operações dentro de funções de coluna 12
2 Evite DISTINCT 12
2 Evite between 16
2 Evite in (a,b,c) 16
2 Evite not in, utilize exists 16
2 Evite subselects, utilize joins 16
2 Evite where “CAMPO IS NULL” - não utilizara o índice 14
2 Armazene rowid para acesso a tabelas numa mesma sessão. 14
3 Agrupe primeiramente as condições de ligação entre tabelas e depois as condições de filtros 12
individuais em cláusulas WHERE.
3 Na clausula FROM apresente as tabelas na ordem das tabelas com mais linhas para as com 12
menos linhas
3 Criar apelidos (alias) para expressões 11
3 Procure utilizar sempre toda a chave de um índice composto 13
3 Se possível não aplique funções/Expressões em colunas da tabela 13
3 Use parênteses na clausula where 14
3 Uso do comando like pode não utilizar índices 13
Visto Responsável :
84
Avaliação de Critérios de programação - REPORT Pag. 2/2
Atende
Atende parcialmente
Não atende
Peso Conceito Pag.
PL/SQL
1 Defina bem o conjunto mínimo de ações de uma transação 22
1 Evite dead locks atualizando tabelas sempre na mesma ordem 23
1 Feche os cursores quando não mais forem utilizados 33
1 Para comandos explícitos de lock consulta ao AD/DBA 23
1 Não utilizar commit em cursor for update 33
1 Não utilizar database hints em PL/SQL de FORMS e REPORT 20
1 Não utilize select from dual para utilizar funções SQL no PL 24
2 Estruture bem seus programas. Utilize procedures e functions 26
2 Evite abrir cursores dentro de loops de outros cursores 33
2 Evite transações muito curtas 23
2 Evite transações muito longas 22
2 Não faça grandes blocos PL/SQL, utilize códigos menores, menos de 100 linhas 26
2 Não use locks com cursor for update 34
2 Utilize foward declarations para procedures 27
2 Utilize operadores %TYPE e %ROWTYPE 26
2 Utilizar os mesmos tipos dados existentes no database para as variáveis: 25
3 Procure usar a estrutura de cursor loop 34
3 Utilize conversão explicita para variáveis 26
3 Utilize cursor explicito uma vez que é mais eficiente que utilizar cursor implicitamente 33
3 Padronize seu fonte PL/SQL 36
REPORTS
1 Utilizar na trigger BEFORE-FORM o comando DBMS_SESSION.SET_ROLE(‘ALL’) 60
1 Defina o mínimo de queries possíveis 57
1 Informe apelidos para as colunas que existirem em mais de uma query 60
1 Só selecione campos no data model que serão utilizados no LAYOUT 60
1 Utilizar o máximo de processamento e transformação de colunas dentro das queries 60
2 Evite o uso da built-in SRW.DO_SQL dentro de PL/SQL 61
2 Não utilize frames e objetos sólidos da cor branca 61
3 Evite truncar campos no LAYOUT 60
3 Evite utilizar a opção total de páginas em seu relatório ( Ex: Pagina 1 de 30 ) 61
3 Retire frames desnecessárias geradas pelo default LAYOUT 61
Visto Responsável :
85
6.4- DEFININDO TEMPOS ACEITÁVEIS
Deve-se no fase de homologação preencher a Ficha de Medição de Tempos - Aplicativos Oracle.
Este documento é importante pois permitirá direcionar os trabalhos de otimização de performance sobre
os aplicativos/tarefas que possam impactar o bom andamento do sistema como um todo.
· Efetuar no mínimo 3 medições de tempos em horas e dias diferentes de modo a se obter uma média
mais realista do dia a dia em produção. Uma única medida pode ter seu resultado distorcido
devido a condições atípicas do ambiente Oracle/Risc no momento da medição.
· Nunca efetue uma medição logo após o banco Oracle entrar no ar, espere pelo menos 6 horas após o
startup para efetuar a medição. É necessário um tempo de estabilização para que a área de cache
do banco de dados seja preenchida, evitando-se resultados piores devido ao maior numero de I/O
em disco que seria necessário.
· Para processos compostos de várias tarefas indique um * na coluna G (Grupo) e indique na descrição
do mesmo as seqüência de módulos/tarefas que compõem este grupo.
Ex:
Isto permite identificar que apesar do tempo do PL/SQL ter ultrapassado o esperado, no conjunto o
processo de carga continua aceitável, abaixo de 1 hora (55 minutos).
· Caso o módulo seja do tipo OUT (Outros) especificar na descrição o tipo do processo.
86
Exemplo de Ficha de Medição de Tempos - Aplicativos Oracle
87
Ficha de Medição de Tempos - Aplicativos Oracle
Ambiente <cliente>
Módulo: Folha : de
Descrição:
Responsável: Empresa:
Data: Obs:
Sigl Descrição
a
SHL Shell G Coluna indicador de grupo
REP Report
FRC Forms - Commit
FRQ Forms - Query Marque * quando o módulo for um conjunto de
PLS Batch PL/SQL processos que serão detalhados abaixo.
TRN Transferencia de Arquivos (FTP) Indique no módulo os seqüenciais que compõe
LDR Sql*Loader - Carga de tabelas este módulo. Informe o tempo total.
PRC Pro*C
COB Pro*Cobol
88
OUT Outros - Especificar na descrição.
Um dos mais importantes fatores de um aplicativo é sua performance. Um aplicativo desenvolvido com o
máximo de facilidades possíveis ao usuário, cores, telas de auxílio etc.. pode se tornar inoperante caso a
sua performance não atenda os requisitos mínimos necessários para a função que foi especificado. Uma
aplicação obtêm uma qualidade superior quando alia uma alta performance com facilidades para o
usuário, chegando num ambiente de produção suficientemente testado de modo a se evitar “bugs”.
Performance Event Collection Services (PECS) é uma ferramenta disponível para o forms 4.013 e 4.5,
que permite tuning de performance através de medição de tempos de cada função de seu forms, ao
mesmo tempo analisando o quanto de seu código foi testado.
Como uma ferramenta de auxílio a testes o PECS pode responder as seguintes perguntas:
· Pode-se tambem utilizar o PECS para estudos e planejamento de capacidade das aplicações. Usando
as informações que o PECS recolhe, pode-se através das medidas obtidas efetuar testes e
simulações em análises do tipo ‘E SE ?’.
89
· O PECS armazena as informações recolhidas em formato binário comprimido gerando um arquivo
.DAT no seu disco. Ao término da análise este arquivo pode ser carregado em tabelas do database
para a geração dos relatórios de análise dos resultados obtidos.
· Além dos eventos básicos o desenvolvedor pode criar unidades lógicas, a serem analisadas pelo PECS
utilizando-se de built-ins do PECS dentro de seu código PL/SQL. Estas built-ins, permitem
informar quando o PECS deve começar a armazenar dados e quando a transação que está sendo
medida termina. Deste modo pode-se cercar uma função de seu forms transformando-a em um
evento que passa a ser analisado pelo PECS.
· PECS permite uma análise da cobertura de seus testes informando que áreas de seu forms foram
executadas e mais importante, quais áreas não foram testadas durante a fase de testes.
· Occurrence
· Event
:
Uma transação com uma definição de início e fim específica de uma aplicação ou forms.
· Class
Um grupo de eventos correlacionados. Eventos pertencem a classes. Classes são “donas” de eventos.
Por exemplo: Um form é uma classe que é dona de eventos (triggers, lovs). Um WHEN-BUTTON-
PRESSED é uma ocorrência de um evento trigger.
· Run
É uma passada de teste em sua aplicação do inicio ao fim. Cada arquivo .DAT mapeia um único run
de seu experimento.
· Experiment
90
O sistema PECS é composto de 4 componentes:
· PECS built-ins
São built-ins que podem ser inseridas dentro de código PL/SQL, para definir eventos customizados.
Estas built-ins incluem:
¨ PECS Assistant
Uma aplicação forms para monitorar, carregar arquivos .DAT nas tabelas PECS e visualizar os
resultados obtidos.
¨ PECS Reports
Tabelas em seu banco de dados utilizadas pelo sistema PECS, devem ser criadas dentro do usuário
SYSTEM utilizando para isso o script PECSBILD.SQL.
¨ PECS_RUN
¨ PECS_EXPERIMENT
¨ PECS_CLASS
¨ PECS_CLASS_EVENTS
¨ PECS_DATA
¨ PECS_SUMMARY
.
1- Rode sua aplicação com PECS ON de modo a coletar dados, armazenando-os num arquivo .DAT
Exemplo:
91
2- Utilize o PECS Assistent para carregar os dados contidos no arquivo .DAT para o banco de dados.
3- Analise os resultados via windows do PECS Assistant ou através dos reports Performance e Coverage
Reports.
Este procedimento carregará uma análise completa do teste executado. Caso se deseje coletar
informações apenas de determinados eventos, deve-se usar as built-ins (PECS.DISABLE) para limitar o
foco dos experimentos eliminando LOVs por exemplo.
92
6.5.5- Eventos específicos da Aplicação
Eventos da aplicação são transações lógicas definidas pelas regras de negócio de sua aplicação, vide item
1.7.
Você pode criar classes e eventos para analisar estas transações via report do PECS.
Uma classe definida C_CORRENTE pode conter, por exemplo os eventos, DEPOSITO, RETIRADA e
TRANSFERENCIA.
93