1º Emprego: DBA ORACLE!!! \o/

fevereiro 18th, 2010 por antonioDBA

Graça e Paz meus amigos do GPO!!!

Resolvi criar este post apenas para compartilhar minha alegria com vocês: Consegui o meu 1º emprego como DBA Oracle!!! \o/

Eu gostaria de agradecer muito por todos que me ajudaram no início, e que ajudam no crescimento do GPO também. Não foi pouca as vezes que consegui nos blogs do site tirar minhas dúvidas a respeito de oracle. Não vou dizer que foi fácil conseguir esse emprego, mas valeu a pena todo o esforço. Agora que vai começar a “brincadeira” pra mim…anteriormente foi só no lab…agora vou colocar em prática os estudos GRAÇAS A DEUS!!!

De cara já peguei um ambiente sensacional: Um Oracle RAC com 4 nós + Storage, além de mais 2 Bancos Oracle com diversas bases ativas.

Assim que der virei com novos posts, dando dicas mais do cotidiano do que os meus posts anteriores!

Grande abraço a todos!!!

Obrigado Senhor Jesus por essa vitória!!! \o/

Views de Desempenho Dinâmicas

novembro 18th, 2009 por antonioDBA

Olá a todos pessoal! Tudo em ordem com vcs?

Hoje falaremos um pouco sobre as views de desempenho dinâmicas, você ja ouviu falar sobre elas? Não conhece suas funcionalidades? Então leia esse post e boa leitura!

As views de desempenho dinâmicas possuem esse nome porque elas são atualizadas continuamente enquanto um banco de dados está aberto e em uso.
O seu conteúdo relaciona-se principalmente ao desempenho. Elas fornecem dados sobre as estruturas de disco internas e de memória, e podem ser acessadas pelo administrador de banco de dados.
As views de desempenho dinâmicas são identificadas pelo prefixo V_$, mas a Oracle fornece sinônimos públicos com o prefixo V$.
É importante ressaltar que após a instância ser iniciada no estágio NOMOUNT, as views V$ que podem ser lidas na memória estarão acessíveis, logo, as views que lêem dados do arquivo de controle precisam que o banco de dados esteja montado.

Segue abaixo a lista das views de desempenho dinâmicas acessíveis no estágio NOMOUNT:

V$PARAMETER: Contém informações sobre os parâmetros de inicialização.
V$SGA: Contém informações resumidas na SGA.
V$OPTION: Lista as opções que são instaladas com o servidor Oracle.
V$PROCESS: Contém informações sobre os processos que estão ativos no momento.
V$SESSION: Lista informações da sessão atual.
V$VERSION: Lista o número de versão e os componentes.
V$INSTANCE: Exibe o estado da instância atual.

E por fim, segue abaixo a lista das views de desempenho dinâmicas acessíveis no estágio MOUNT:

V$THREAD: Contém informações de thread, por exemplo, sobre os grupos de redo logs.
V$CONTROLFILE: Lista os nomes dos arquivos de controle. Mesmo disponível, essa view não retorna linhas no estágio NOMOUNT.
V$DATABASE: Contém informações do banco de dados.
V$DATAFILE: Contém informações do arquivo de dados a partir do arquivo de controle.
V$DATAFILE_HEADER: Exibe informações do cabeçalho do arquivo de dados a partir do arquivo de controle.
V$LOGFILE: Contém informações sobre os arquivos de redo log on-line.

Muito obrigado e bons estudos!

“Nem olhos viram nem ouvidos ouviram o que Deus tem preparado para aqueles que o amam”

Chuck Norris o DBA

outubro 28th, 2009 por antonioDBA

Boa tarde meus caros, tudo jóia?

Só pra descontrair um pouco, segue abaixo um texto que achei na web “super importante” sobre o maior DBA de todos os tempos: Chuck Norris!!!

- CHUCK NORRIS não faz DELETEs. Ele olha para os registros e eles correm de medo.
- CHUCK NORRIS não cria PKs. Os registros simplesmente não atrevem-se a duplicar.
- CHUCK NORRIS não faz DELETEs. Ele olha para os registros e eles correm de medo.
- CHUCK NORRIS não cria PKs. Os registros simplesmente não atrevem-se a duplicar.
- CHUCK NORRIS não usa LOG. Ele lembra de todos registros que alterou.
- CHUCK NORRIS não usa LOG. Ele não vai falhar.
- CHUCK NORRIS não cria INDEXes. Ele sabe que os registros retornarão o mais rápido que puderem.
- MSSQL SERVER É muito mais rápido que ORACLE. Basta que o DBA seja CHUCK NORRIS.
- Uma vez adaptaram o ROUNDHOUSE KICK para o ORACLE. Assim nasceu o TRUNCATE TABLE.
- CHUCK NORRIS não dá DROP TABLE. Ele dá ROUNDHOUSE KICK TABLE.
- Uma vez CHUCK NORRIS deu um ROUNDHOUSE KICK em um banco poderoso. Hoje ele é conhecido por ACCESS.
- CHUCK NORRIS sabe todos os erros do ORACLE de cor. Porque ele criou eles.
- SELECT SUM (FORÇA) FROM CHUCK_NORRIS; Internal error. Don ‘ t call the support.
- SELECT CHUCK_NORRIS; Drop database sucessful.
- SELECT ROUNDHOUSE_KICK FROM CHUC… Lost connection.
- DELETE FROM CHUCK_NORRIS. Not Found. (Ele está atras de você, a ponto de dar um ROUNDHOUSE KICK!!!)
- CHUCK NORRIS tem IGNORE CONTRAINTS automático. Ninguém restringe nada a CHUCK NORRIS. Ninguém.
- CHUCK NORRIS não faz cursos de ORACLE. A ORACLE é que faz cursos com ele.
- CHUCK NORRIS instala o ORACLE sem ler o manual. (Quem você pensa que é para ter tentado isso?)
- CHUCK NORRIS instala o ORACLE em um 486. Rodando KURUMIM. Em 2 minutos.
- CHUCK NORRIS instala o MSSQL Server em um Pentium 100MHZ. Rodando Solaris. A partis dos fontes.
- CHUCK NORRIS instala o DB2 em um 486. Rodando WINDOWS VISTA. Sem HD.
- CHUCK NORRIS não tem Certificação. São as empresas que tentam tirar Certificação em CHUCK NORRIS. Em vão.
- Se disser ao DBA CHUCK NORRIS que ” o problema está no banco “, é melhor que esteja se referindo ao Itaú.
- CHUCK NORRIS SABE qual o problema de performance do banco. Ele só está dando uma chance do banco se arrepender. 5… 4… 3…
- CHUCK NORRIS não cria STORED PROCEDURES. Todas suas Queries já se armazenam no banco, tentanto se esconder. Mas é inútil.
- TRIGGERS tem este nome porque CHUCK NORRIS sempre ameaçava atirar no banco quando ele não fazia algo automático.
- CHUCK NORRIS não faz Modelo de Dados. Ele encara o banco até que ele faça o modelo sozinho.
- CHUCK NORRIS instala o ORACLE sem a interface gráfica. E sem a interface texto. (Pergunte a ele você!)
- Megabyte, Gigabyte, Terabyte, Petabyte, Exabyte, Chuckbite.
- ORACLE tem as versões Personal, Standard, Enterprise e ChuckNorris Edition. Mas nenhum computador é rápido o suficiente para rodá-lo.

Fonte: http://wendel.scardua.net/2006/08/02/chuck-norris-facts-versao-dba/

Gerenciamento de UNDO

outubro 20th, 2009 por antonioDBA

Bom dia meus caros, tudo bem com vocês?

Hoje irei explanar sobre um assunto muito importante em administração de Bando de Dados Oracle: Gerenciamento de UNDO. Vamos lá?

#Gerenciando Segmentos de Undo#

*Visão Geral
- Sempre que um dado é alterado, o Oracle armazena num segmento de undo (ou rollback) a imagem antiga deste dado.
- Os segmentos de Undo são utilizados para rollback de transações, consultas consistentes e operações de flashback.
- As alterações em dados de usuários (DML) utilizam-se dos segmentos de undo normais.
- As alterações em estruturas (DDL) utlizam o segmento de rollback existente na tablespace SYSTEM.
- Se o gerenciamento automático de Undo (UNDO_MANAGEMENT=AUTO) estiver sendo usado, o Oracle cria e gerencia os segmentos de undo automaticamente.
- Se o gerenciamento for manual, os segmentos precisam ser criados e gerenciados pelo DBA (comandos CREATE ROLLBACK SEGMENT).
- Um segmento de Undo pode ser compartilhado por várias transações ao mesmo tempo.
- Uma transação estará sempre restrita a um único segmento de undo.
- O cabeçalho de um segmento de Undo contém informações sobre as transações ativas naquele segmento.

#Utilidades dos Segmentos de Undo#

*Rollback de Transação
- Quando uma sessão executa um ROLLBACK, o Oracle regrava todas as imagens de dados alterados pela transação e salvas no segmento de undo de volta para seus locais originais.
- Se uma sessão termina de maneira anormal, o Oracle faz o ROLLBACK automaticamente.
- Se a instância falhar enquanto transações estão em curso, os dados dos segmentos de Undo também serão usadas na recuperação da instância, para efetuar o ROLLBACK destas transações.

*Flashback
- A partir do Oracle 9i foram introduzidos recursos para consultas de dados como eram no passado (por exemplo, para ver os dados de uma tabela como eram há uma hora atrás). Este tipo de consulta é chamado de Flashback Query.

*Consistência de Leitura
- Se uma sessão consulta um dado que está sendo alterado por uma transação ativa (não submetida a COMMIT), o Oracle utiliza os dados do segmento de undo para mostrar o valor anterior à alteração.
Uma consulta sempre verá todos os dados de seu resultado consistentemente ao momento inicial da leitura.
- Se isto não for possível (por falta de espaço suficiente de Undo por exemplo), a consulta recebe uma mensagem de erro.

#Parâmetros de Inicialização relacionados com Undo#

*UNDO_MANAGEMENT
- Determina se o gerenciamento de undo será automático ou manual.

AUTO:
utiliza tablespace de undo, com segmentos de undo gerenciados pelo Oracle.
MANUAL: utiliza segmentos de rollback criados pelo DBA numa tablespace comum.

*UNDO_TABLESPACE
- Nome da tablespace de undo ativa no banco de dados.

*UNDO_RETENTION
- Tempo de retenção de dados nos segmentos de Undo após o término da transação. Auxilia em leituras consistentes e consultas flashback.

*UNDO_SUPPRESS_ERROS
- Se este parâmetro for FALSE e o gerenciamento de undo for automático, os comandos de gerenciamento de segmentos de rollback manual receberão erros.
Para evitar estes erros, define-se este parâmetro como TRUE. (Obsoleto no Oracle 10g).

#Retenção dos dados de Undo#

*Definição
- Os dados de Undo devem obrigatoriamente ser mantidos até o final da transação. Ao final de uma transação, seus dados em Undo podem ser liberados. Se estes dados estiverem sendo usados por leitura consistentes ou flashback, e forem apagados por outra transação que precisou de espaço, a consulta recebe erro.
- Para minimizar esta possibilidade, foi introduzido o parâmetro UNDO_RETENTION na versão 9i.
- Com o UNDO_RETENTION, é possível determinar o tempo (em segundos) após o final da transação que o Oracle tentará manter os dados em Undo.

*Valores
- No Oracle 9i, se UNDO_RETENTION=0, o recurso está desligado.
- No Oracle 10g, o Oracle gerencia automaticamente o UNDO_RETENTION, tentando manter os dados o máximo de tempo possível em Undo.
- Se a tablespace de Undo for autoextensível, UNDO_RETENTION indica a retenção mínima.
- Se a tablespace de Undo for de tamanho fixo, UNDO_RETENTION só será considerado pelo Oracle se houver retenção garantida.

*Garantia de Retenção
- No Oracle 9i, o UNDO_RETENTION só será respeitado se houver espaço suficiente na tablespace de Undo.
- Uma transação procura espaço em Undo livre ou com dados já expirados.
- Se não encontrar, pode “roubar” o espaço mesmo que o tempo de retenção não tenha terminado.
- No Oracle 10g, é possível determinar a garantia de retenção:
Retenção Sem Garantia: padrão, funcionamento igual ao Oracle 9i.
Retenção Garantida: se a transação não encontrar espaço com dados já expirados, ela recebe erro.
- A garantia de retenção é definida pelos seguintes comandos:

CREATE TABLESPACE nome [RETENTION GUARANTEE|NOGUARANTEE];

ALTER TABLESPACE nome [RETENTION GUARANTEE|NOGUARANTEE];

ALTER TABLESPACE UNDOTBS1 RETENTION GUARANTEE;

#Informações Sobre Segmentos de Undo/Rollback#
- Para obter informações sobre todos os segmentos de rollback no banco de dados, consulte a view DBA_ROLLBACK_SEGS.

#Problemas mais Comuns com Undo#

*Espaço Insuficiente Para Transações
- A transação recebe erro por não haver espaço suficiente no segmento de undo.
*Causas Possíveis
- Se o gerenciamento for automático, a tablespace de Undo pode não ser grande o suficiente, ou ainda podem existir sessões consumindo muito espaço de undo anormalmente. Verifique as transações
consumindo muito undo e considere aumentar a tablespace.
- Se o gerenciamento for manual, além das causa acima ainda é possível que os segmentos de rollback criados sejam pequenos demais ou não estejam sendo limpos de maneira adequada. Verifique as configurações de segmentos de rollback (quantidades e tamanhos), e considere utilizar o gerenciamento automático.

*Erro de Consistência na Leitura
- Uma consulta recebe erro “snapshot too old” (ORA-01555) porque estava consultando dados em segmentos de undo (leitura consistente), e estes dados foram apagados por uma transação que precisou de espaço.
*Causas Possíveis
- Segmentos de undo/rollback muito pequenos. Aumente os segmentos.
- Consultas muito longas. Ajuste as consultas.
- Verifique a possibilidade de ajustar o UNDO_RETENTION e RETENTION GUARANTEE.

Obrigado pela leitura e Bons estudos!

Ajustes de Memória: Shared Pool

outubro 1st, 2009 por antonioDBA

Boa tarde meus amigos! Tudo bem com vocês?
Infelizmente, devido a falta de tempo, estava sem atualizar o blog.
Hojei irei abordar um tema muito importante na área de Tunning de Banco de Dados Oracle: Ajustes de memória na Shared Pool.
Vamos lá?

#Ajustes de Memória na Shared Pool#

*Shared Pool. Pra que ela serve?
- É uma área para compartilhamento.

- O que ela tem: Comandos e planos de execução dos últimos comandos executados. É bom, pois O oracle pula boa parte do parse, pois a shared pool armazena os planos de parses realizados anteriormente.

*Library cache: É onde é armazenado o texto propriamente dito, o código compilado e o plano do seu comando. É usado pra SQL e PL/SQL. Ex.: procedure, select.

*Cache do dicionário de dados: é armazenado todas as informações necessárias pra validar o seu comando. Ele Consulta no dicionário do disco que fica na tabela system. Funciona totalmente em função do library cache.

Obs.: Um mecânismo do oracle muito utilizado pelas áreas de memória é o LRU: O oracle joga a informação que faz mais tempo que não é utilizada.

*UGA: É um pedaço da PGA. É uma subdivisão do PGA. Se você utiliza um servidor compartilhado, ela vai ficar dentro da SGA. Pois é na SGA que ficam as áreas compartilhadas.

- Sempre que um novo objeto (objeto que ainda não esta na memória) for necessário, você vai precisar de espaço para alocá-lo. É o 1º passo do plano de parse. Você tem q alocar um espaço em memória na shared pool.

- Objetos recriados são eliminados do cache: O oracle precisa revalidar o código que está em memória.

- Objetos fixos são compostos de pedaços contíguos (chunks) de memória: Nem sempre uma package vai estar inteiro na memória ( Normalmente fica fragmentada: Um pedaço aqui outro lá).

-Armazena metadados complexos dos cursores: Armazenas informações para planos de execução: Objetivo: evitar reparse, e compartilhamento.

*Como o oracle controla os dados que vão entrar na shared pool?
-Ele controla por regiões, por pedaços em que ele pode alocar comandos. (pedaços contíguos (chunks) de memória).

- Existe um mecânismo de proteção de áreas de memória. O oracle tem um mecânismo parecido com o lock em tabelas. Ele se chama LATCH.

*LATH: É um mecanismo que protege as áreas de memórias, semelhante como o lock protege tabelas/objetos em disco oracle.

*A Diferença entre latch e lock.
- O lock pode ser muito demorável. Enquanto o latch é extremamente rápido, ele funciona normalmente em milésimos de segundo.

- O latch é instantâneo, mexeu na área de memória (a procedure colocou o código) e está liberado. Não precisa do commit como no lock.

- No lock, quando você executa um DML com sucesso e eu tento fazer na mesma linha que a sua, o oracle enfileira, e eu fico preso. E sucessivamente.

- Latch é um mecanismo genérico que protege as áreas de memória.

*Eu posso ter problemas de performance se eu superdimensionar minha área de memória?
Sim. Pois ele ficar super oculpado analisando a área superdimensionada.

*Como eu faço pra saber se a minha shared pool está funcionado bem?
- Através do script Statspack, que a oracle disponibiliza. Após sua execução será gerado um relatório detalhado sobre o funcionamento da shared pool.

- Hard parse: é o nome dado quando o parse foi realizado por completo (o oracle procurou em memória e nao achou, e teve q fazer todas as fases do parse). Trabalho pesado.

- Soft parse – É quando a shared pool encontra o comando em memória, mas mesmo assim é necessário uma parte do parse, pois ele precisa ver se você tem privilégios (ele pulou o plano de execução). Logo, Ele faz uma parte pequena do parse.

*Existe algum caso em que o oracle não precise fazer nenhum tipo de analise/parse?
Existe. Sim. Se você na mesma sessão, executou o mesmo comando.

*Como eu consulto informações sobre o funcionamento da Library cache? Que fica na shared pool. Através da view de desempenho:

V$LIBRARYCACHE; uma view q mostra o funcionamento da L.C.

INVALIDATIONS; Mostra as procedures que estão em memória, essa procedure faz menção a uma tabela x,uma select ou update.

- O que acontece se eu coletar nossas estatísticas para a tabela?
Aquele plano de execução pode nao ser válido ou a melhor opção. Isso indica que o objeto pl/sql pode ser invalidado.

*Isso se chama invalidação em memória: Quando o oracle marca como não sendo mais atual. Logo, ele precisa fazer um novo parse para verificar se este ainda é o melhor plano para esse comando.
- Isso é bom ou ruim pra performance?
Ruim. Pois o oracle vai ter que fazer o trabalho de validação e parse. Se agente pensa num ambiente pesado, muita gente utilizando o banco, muitas sessões ativas. O banco nas primeiras versões chegava até a cair por causa de bug no library cache. Dica do professor: Não altere código durante horário de pico.
Qual a recomendação do oracle pra invalidations?
Próximo de zero. O ideal é zero. Se você faz isso em horários foras de pico provavelmente gerará poucos invalidations.

Dica: A imensa maioria dos comandos iniciais desse percentual é ruim ao subir o banco. O ideal é esperar o banco subir, normalizar seu funcionamento/uso diário e aguarda umas 3 horas para gerar esse script;
- Em linhas gerais a oracle recomenda que esse número seja acima de 90%. Caso seja menor, pode ser um problema de shared pool.

*O que esta query acima quer dizer? Se você aumentar a memória qual o ganho estimado?
- Se você aumentar a shared pool a performance vai continuar igual.

- O oracle tem uma serie de indicadores pra você tomar uma decisão. De acordo com a amostragem e análise deles todos é q você deverá tomar uma decisão, e nunca tomar uma decisão por um valor de um indicador isolado. (Isso é uma palavra final? Não. É apenas um indicador).

* O trabalho de ajuste tem 2 perfis:

- Perfil pró-ativo: monitorar, analisar os indicadores antes q a casa caia. Olhe os indicadores pra ver se as coisas estão indo bem ou mal.
Periodicamente e com um foco especial: em momentos críticos do meu sistema, fechamento de mês, na atualização do oracle, quando entrou novos funcionários,etc. Em outras palavras: Quando mudar alguma coisa. O interessante é verificar periodicamente.

- Trabalho reativo: Já estão reclamando que está ruim. Você vai analisar a memória, analisar disco e esses indicadores.

*Um outro tipo de Problema na shared pool é a Fragmentação de memória: pois existem objetos de tamanho e utilização muito diferentes, e pelo jeito que o oracle utiliza a shared pool. Pois um único comando pode ter eliminado vários outros comandos na memória, pois teve que retirar os outros comandos prontos pra serem executados para alocar um comando maior na memória. Isso gera perda performance.

*São causados por quem?
- Por objetos grandes.

*Como oracle procura minimizar esse problema?
- Ele faz o seguinte: eu pego um pedaço da shared pool e vou reservar esse pedaço pra comandos muito grandes. Os objetos grandes vão disputar em uma área específica para objetos grandes. E o resto da área não reservada será disputada por objetos menores. Agora vai entrar um comando grande e irá sair um outro grande. Com esse procedimento eu evito fragmentação e perda de performance. Uma das maneiras de evitar a fragmentação é usar a área reservada. O parâmetro da área que determina o tamanho da shared pool.
Obs. Por default o oracle configura 10% da shared Pool pra comandos muito grandes.

*O que eu como DBA posso fazer para minimizar a fragmentação?
- Evitar que os comandos grandes saiam da memoria. Existe uma maneira no oracle de você pregar um objeto em memóra (esse comando nao sai mais). Esse comando passar a ser isento do mecanismo LRU.
Obs.: Baixou o banco zera. Logo, você tem q fixar novamente.

* Quais os comandos ideais pra fixar?Como determina isso?
- Os comandos idéias são os objetos q são muito usados. Em outras palavras, com muita utilização e que são grandes.

Ex.: Você carrega uma query (select), ele ocupa um bloco, com seu cabeçalho, plano de execução e tudo mais, depois você carrega uma procedure que ocupa um outro grande espaço em memória, depois uma package, outra query, e outra query. E assim vai carregando minha memória:

*Quanto estiver quase toda ocupada, o que o oracle vai fazer?
- Vai retirar o comando Menos recentemente usado.

*Como falo para o Oracle que eu quero fixar um objeto na shared pool?
- Usa a package: EXECUTE DBMS_SHARED_POOL.KEEP(‘OWNER.OBJETO’);

- Para retirar: EXECUTE DBMS_SHARED_POOL.UNKEEP(‘OWNER.OBJETO’);

*Qual a visão que mostra os comandos na shared pool?

v$sql_area; mostrar as querys

v$db_object_cache; ela diz os objetos do banco de dados que estão em cache.

select owner,name from v$db_object_cache where kept=’yes’ and owner=’scott’.

Obs.: Eu quero limpar minha shared pool. Você utiliza o comando: ALTER SYSTEM FLUSH SHARED_POOL; Mesmo que você deseje limpar tudo você não vai conseguir tirar os comandos q estão fixos.

Obs.: Uma dica de manutenção do DBA:
Antes de baixar o banco, verifique os objetos mais utilizados. E depois quando for rodar: Você roda o rdbms pool nesses arquivos.
- Esse procedimento evita a perda de performance: Pois os principais comandos já vão estar em memória.

*Para descobrir quais os objetos mais utilizados:

desc v$db_objects_cache

executions; indica a quantidade que essa query/comando teve.

Sharabale_man; tamanho do comando em memória, em bytes. Mostra quanto de espaço o comando oculpa em memória.

*Fixar uma query (Ex.:um select), pode ser interessante?
- Sim. Se for um comando sql grande e que é efetuado muitas vezes.
Como que faço?
Através do comando:
desc dbms_shared_pool

*Limpeza da Shared Pool.

- Se você define que precisa alterar o tamanho da shared pool, qual o parâmetro que determina o tamanho da shared pool?

- Através do Parâmetro: shared_pol_size. Este é um parâmetro dinâmico (logo você pode aumentar ou diminuir seu tamanho com o banco em funcionamento).

*Como faço para visualizar o valor do parâmetro?
- Através do comando: show parameter shared_pool_size

Ex.: alter system set shared_pool_size=300M

* Os Parâmetros para controlar a memória:
- Ex.: sga_max_size = indica o Limite da SGA. Em outras palavras, determina o limite de tamanho da SGA. (A soma das áreas da minha SGA)

- A sga_max_size é um parâmetro estático, ou seja, não é possível fazer alteração com o banco funcionando.

Obrigado e bons estudos!

Processamento de Consultas no Oracle

agosto 26th, 2009 por antonioDBA

Boa Tarde meus caros! Como anda essa força?

Dando continuidade no tema de Arquitetura Oracle, irei abordar hoje sobre o funcionamento e etapas do processamento das consultas oracle. Vamos lá!

* Processamento de Consultas
As consultas são diferentes de outros tipos de instruções SQL, porque, se forem bem sucedidas, retornarão dados como resultados. Enquanto outras instruções apenas informam se houve êxito ou falha, uma consulta pode retornar uma linha ou milhares de linhas. Há três estágios principais do processamento de uma consulta:

- Analisar (Analyze/Parse)
- Executar (Execute)
- Extrair (Fetch)

+ Analisando uma Instrução SQL +
Durante o estágio de parse, a instrução SQL é transmitida do processo de usuário para o processo de servidor, e uma representação analisada da instrução SQL é carregada em uma área SQL compartilhada.

* Durante o parse (Analyze/Parse), o processo de servidor:
- Procura uma cópia existente da instrução SQL no pool compartilhado.
- Valida a instrução SQL verificando sua sintaxe.
- Efetua pesquisas no dicionário de dados para validar definições de tabela e coluna.
- Adquire bloqueios de análise em objetos, de forma que as definições não se alteram durante a análise da instrução.
- Verifica os privilégios do usuário para acessar os objetos de esquema mencionados.
- Determina o plano de execução ideal para a instrução.
- Carrega a instrução e o plano de execução em uma área SQL compartilhada.

* Executando a Instrução (Execute)
Neste ponto, o servidor Oracle possui todas as informações e recursos necessários para que a instrução seja executada.
Para as instruções SELECT, o processo de servidor prepara-se para recuperar os dados.

* Extraindo as Linhas de uma Consulta (Fetch)
No estágio de extração, as linhas são selecionadas, ordenadas (se necessário) e retornadas pelo servidor ao usuário.
Dependendo do número de linhas retornadas em cada extração, uma ou mais extrações podem ser necessárias para transferir os resultados de uma consulta para o usuário.

Amigos, é importante ressaltar, como esses conceitos “básicos” fazem toda a diferença para o DBA lá na frente, o Oracle é uma ferramenta muito poderosa e robusta, mas em determinadas situações você precisará compreender bem os conceitos para resolver alguns problemas, e não ter apenas um “ctrl+c” dos comandos em sua mente.

Bons estudos! Deus os abençoe!

Arquitetura Oracle e seus componentes

agosto 19th, 2009 por antonioDBA

Boa Tarde meus amigos. Fazia um tempinho que não postava no blog, devido a falta de tempo e as minhas leituras diárias no “pequeno” livro do Bob Bryla (Manual do DBA - Oracle 11g) de 700 e poucas páginas. rsrs

Hoje irei explicar de uma forma geral a arquitetura oracle e seus componentes. Algo que todos os DBA’s, obrigatoriamente, devem saber de cabo a rabo. Vamos lá, e boa leitura:

*O RDBMS Oracle é um sistema de gerenciamento de banco de dados relacional.

*O servidor Oracle consiste de:
- Instância Oracle (Oracle Instance)
- Arquivos do Banco de Dados (Database Files)

*Arquivos do Banco de Dados Oracle
- Um banco de dados Oracle (Database files) são um conjunto de dados tratados como uma unidade.
- Um banco de dados possui uma estrutura lógica e física.
- A estrutura física do banco de dados é um conjunto de arquivos do sistema operacional. Em um banco de dados Oracle eles são compostos de três tipos de arquivos:

+ Arquivos de Dados (Data Files)
+ Arquivos de Logs (Redo Logs)
+ Arquivos de Controle (Control Files)

*Arquivos de Dados (Data Files)
- Os arquivos de dados contém os dados do banco, e eles são armazenados em tabelas definidas pelo usuário. Além disto, nos arquivos de dados também são armazenados o dicionário de dados, as imagens anteriores de dados alterados, índices e outros tipos de estruturas. Um banco de dados Oracle deve conter no mínimo um arquivo de dados.

*Características dos Arquivos de Dados

- Os arquivos de dados podem estar associados a apenas um banco de dados Oracle.
- Um ou mais arquivos de dados formam uma unidade lógica chamada tablespace.

*Redo Logs
- Os redo logs armazenam as mudanças efetuadas no banco de dados para possibilitar a recuperação dos dados em caso de falhas. Um banco de dados Oracle deve possuir no mínimo dois arquivos de redo log.

*Arquivos de Controle (Control Files)
- Os arquivos de controle contém as informações necessárias para manter e verificar a integridade do banco de dados. Por exemplo, o arquivo de controle é utilizado para identificar os arquivos de dados e os arquivos de redo log. Um banco de dados Oracle deve possuir no mínimo um arquivo de controle.

*Outros Arquivos Importantes
- O servidor Oracle também faz uso de outros arquivos que não fazem parte do banco de dados:

+ Arquivo de Parâmetros (Parameter File)

-define as características da instância Oracle. Por exemplo, ele contém parâmetros que
definem o tamanho das estruturas de memória da SGA
+ Arquivo de Senhas (Password File)
-faz a validação de quais usuários tem permissão de fazer start up e shutdown na instância
Oracle
+ Arquivos de Redo Log Arquivados (Archived Redo Log Files)
-são cópias off-line dos arquivos de redo log, que podem ser necessários em um processo de
recuperação de falhas de mídia

* Instância Oracle (Oracle Instance)
- Uma Instância Oracle consiste na estrutura de memória chamada de SGA (System Global Area) e nos processos em segundo plano (background processes) utilizados para gerenciar o banco de dados
Uma Instância Oracle somente pode abrir e utilizar um banco de dados de cada vez

* Área Global do Sistema (System Global Area)
- Área de memória utilizada para armazenar as informações do banco de dados que são compartilhadas pelos processos
- Contém dados e informações de controle e é alocada na memória do computador onde o servidor Oracle esta operando
- Dinâmica e definida pelo parâmetro SGA_MAX_SIZE
- Definida em porções (granule)
- Consiste de diversas estruturas de memória

* Área Global do Sistema (Continuação)
+ Shared Pool
-utilizada para armazenar os comandos SQL executados recentemente, e as informações do
dicionário de dados. Estes comandos SQL podem ser solicitados por processos do usuário ou
no caso de stored procedures, lidos do dicionário de dados.
+ Database Buffer Cache
-utilizada para armazenar os dados recentemente utilizados. Os dados são lidos e gravados
nos arquivos de dados
+ Redo Log Buffer
-utilizado para armazenar as alterações feitas no banco de dados pelos processos
e servidores pelos processos em segundo plano

* Área Global do Sistema (System Global Area)
+ Java Pool
-utilizado para armazenar código Java
+ Large Pool
-utilizado para armazenar grandes estruturas de memória que não estão relacionadas
diretamente ao processamento de instruções SQL, como por exemplo blocos de dados
copiados durante operações de backup e recovery
+ Streams Pool
-utilizado para manter estruturas de dados e controle do recurso Oracle Streams

* Processos em Segundo Plano
- Os processos em segundo plano (background processes) de uma instância executam funções comuns que são necessárias para atender as solicitações de serviço de usuários simultâneos, sem comprometer a integridade e o desempenho do sistema.
- Eles consolidam funções que, de outra forma, seriam tratadas por diversos programas Oracle executados para cada usuário.
- Ele executam tarefas de I/O e monitoram outros processos Oracle para oferecer maior paralelismo, o que aumenta o desempenho e a confiabilidade.
- Dependendo da configuração, uma instância Oracle pode incluir vários processos de segundo plano, no entanto cada instância inclui cinco processos de segundo plano fundamentais. São Eles:

+ O Database Writer (DBW0)
é responsável por gravar dados alterados do buffer cache do banco de dados nos arquivos de dados.
+ O Log Writer (LGWR) grava as alterações registradas no buffer de redo log nos arquivos de redo log.
+ O Monitor de Sistema (SMON, System Monitor) verifica a consistência no banco de dados e, se necessário, inicia a recuperação do banco de dados quando ele é aberto.
+ O Monitor de Processo (PMON, Process Monitor) disponibiliza recursos se um dos processos Oracle falhar.
+ O Checkpoint Process (CKPT) é responsável pela atualização das informações de status do banco de dados nos arquivos de controle e nos arquivos de dados, sempre que as alterações efetuadas no cache de buffer ficam registradas no banco de dados de forma permanente.

* Processos de segundo plano opcionais:
ARCn LMDn QMNn
CJQ0 LMON RECO
Dnnn LMS Snnn
LCKn Pnnn

* O Database Writer (DBW0) grava os buffers sujos do Buffer Cache do banco de dados nos arquivos de dados. Ele garante que um número suficiente de buffers livres esteja disponível no Buffer Cache de buffer. O desempenho do banco de dados é melhorado, porque os processos de servidor efetuam alterações somente no cache de buffer.

*O LGWR executa gravações seqüenciais do buffer de redo log no arquivo de redo log nas situações a seguir:
- Quando uma transação efetua commit.
- Quando 1/3 do buffer de redo log está cheio.
- Quando há mais de um megabyte de alterações registradas no buffer de redo log.
- Antes de o DBW0 gravar blocos modificados do cache de buffer do banco de dados nos arquivos de dados.
- Como o redo é necessário para a recuperação, o LGWR confirma o COMMIT somente após o redo estar gravado em disco.

* Se a instância Oracle falhar, qualquer informação na SGA que não foi gravada em disco se perderá. Por exemplo, a falha do sistema operacional causa uma falha na instância. Depois da perda da instância, o processo de segundo plano SMON executará automaticamente a recuperação da instância quando o banco de dados for reaberto.

* O processo de segundo plano PMON efetua uma limpeza após falha dos processos da seguinte maneira:
- Submete a rollback a transação atual do usuário
- Libera todos bloqueios de tabela ou linha que existem no momento
- Libera outros recursos que estejam reservados pelo usuário

* Durante um checkpoint:
- Vários buffers de banco de dados sujos incluídos no log que está sendo submetido a um checkpoint são gravados nos arquivos de dados pelo DBWn.
- O processo de segundo plano de checkpoint CKPT atualiza os cabeçalhos de todos os arquivos de dados e arquivos de controle para que reflitam a conclusão com êxito.

Espero que todos tenham compreendido, em uma visão geral, o básico da arquitetura Oracle e seus componentes.

Grande abraço, bons estudos e até o próximo post galera!

Funções - Functions no Oracle

julho 20th, 2009 por antonioDBA

Ao contrário das procedures as Funções (ou Functions) são blocos PL/SQL que devem obrigatoriamente retornar ao menos um valor. Uma função manipula o conteúdo de uma coluna em uma declaração SQL. Ao se usar uma função em uma declaração SQL, o valor da coluna sobre o qual a função é executada é alterado quando apresentado.

Sintaxe Básica:
CREATE [OR REPLACE] FUNCTION nome_da_função
[( parameter1 [ mode1] datatype1,
parameter2 [ mode2] datatype2,
. . .)]
RETURN tipo_de_dado
IS|AS
Bloco PL/SQL;
Ao contrário das procedures as funções tem que retornar ao menos um valor.
CREATE OR REPLACE FUNCTION pega_sal
(p_id IN emp.empno%TYPE)
RETURN NUMBER
IS
v_sal emp.sal%TYPE :=0;
BEGIN
SELECT sal
INTO v_sal
FROM scott.emp
WHERE empno = p_id;
RETURN v_sal;
END pega_sal;
/
Executando
VARIABLE g_sal NUMBER

EXECUTE :g_sal := pega_sal(7839)

PRINT g_sal
Função para calcular CPMF
CREATE OR REPLACE FUNCTION cpmf(p_value IN NUMBER)
RETURN NUMBER IS
BEGIN
RETURN (p_value * 0.038);
END cpmf;
/
SELECT empno, ename, sal, cpmf(sal)
FROM scott.emp
WHERE deptno = 10;

Funções de valores simples:

ABS(n)= Devolve o valor absoluto de (n).
CEIL(n)=Obtém o valor inteiro imediatamente superior ou igual a “n”.
FLOOT(n) = Devolve o valor inteiro imediatamente inferior ou igual a “n”.
MOD (m, n)= Devolve o resto resultante de dividir “m” entre “n”.
NVL (valor, expressão)= Substitui um valor nulo por outro valor.
POWER (m, exponente)= Calcula a potência de um número.
ROUND (numero [, m])= Arredonda números com o número de dígitos de precisão indicados.
SIGN (valor)= Indica o signo do “valor”.
SQRT(n)= Devolve a raiz quadrada de “n”.
TRUNC (numero, [m])= Trunca números para que tenham uma certa quantidade de dígitos de precisão.
VAIRANCE (valor)= Devolve a média de um conjunto de valores.

Funções de grupos de valores:

AVG(n)= Calcula o valor médio de “n” ignorando os valores nulos.
COUNT (* | Expressão)= Conta o número de vezes que a expressão avalia algum dado com valor não nulo. A opção “*” conta todas as filas selecionadas.
MAX (expressão)= Calcula o máximo.
MIN (expressão)= Calcula o mínimo.
SUM (expressão)= Obtém a soma dos valores da expressão.
GREATEST (valor1, valor2…)= Obtém o maior valor da lista.
LEAST (valor1, valor2…)= Obtém o menor valor da lista.

Funções que devolvem valores de caracteres:

CHR(n) = Devolve o caractere cujo valor em binário é equivalente a “n”.
CONCAT (cad1, cad2)= Devolve “cad1″ concatenada com “cad2″.
LOWER (cad)= Devolve a cadeia “cad” em minúsculas.
UPPER (cad)= Devolve a cadeia “cad” em maiúsculas.
INITCAP (cad)= Converte a cadeia “cad” a tipo título.
LPAD (cad1, n[,cad2])= Adiciona caracteres à esquerda da cadeia até que tenha uma certa longitude.
RPAD (cad1, n[,cad2])= Adiciona caracteres à direita até que tenha uma certa longitude.
LTRIM (cad [,set])= Suprime um conjunto de caracteres à esquerda da cadeia.
RTRIM (cad [,set])= Suprime um conjunto de caracteres à direita da cadeia.
REPLACE (cad, cadeia_busca [, cadeia_substitucao])= Substitui um caractere ou caracteres de uma cadeia com 0 ou mais caracteres.
SUBSTR (cad, m [,n])= Obtém parte de uma cadeia.
TRANSLATE (cad1, cad2, cad3)= Converte caracteres de uma cadeia em caracteres diferentes, segundo um plano de substituição marcado pelo usuário.

Funções que devolvem valores numéricos:

ASCII(cad)= Devolve o valor ASCII da primeira letra da cadeia “cad”.
INSTR (cad1, cad2 [, comeco [,m]])= Permite uma busca de um conjunto de caracteres em uma cadeia, mas não suprime nenhum caractere depois.
LENGTH (cad)= Devolve o número de caracteres de cad.

Funções para o manejo de datas:

SYSDATE= Devolve a data do sistema.
ADD_MONTHS (data, n)= Devolve a data “data” incrementada em “n” meses.
LASTDAY (data)= Devolve a data do último dia do mês que contém “data”.
MONTHS_BETWEEN (data1, data2)= Devolve a diferença em meses entre as datas “data1″ e “data2″.
NEXT_DAY (data, cad)= Devolve a data do primeiro dia da semana indicado por “cad” depois da data indicada por “data”.

Funções de conversão:

TO_CHAR= Transforma um tipo DATE ou NUMBER em uma cadeia de caracteres.
TO_DATE= Transforma um tipo NUMBER ou CHAR em DATE.
TO_NUMBER= Transforma uma cadeia de caracteres em NUMBER.

Oracle - Trigger

julho 13th, 2009 por antonioDBA

Boa tarde pessoal,

Como foi o final de semana? Deu para descansar um pouco? Espero que sim! Vamos retomar nossos estudos?
Você ja ouviu falar em “gatilho do Banco de dados” ou mais conhecido como triggers?
Então vamos lá:

Triggers são procedimentos que podem ser gravados em Java, PL/SQL ou C. São executados (ou disparados) implicitamente quando uma tabela é modificada, um objeto é criado ou ocorrem algumas ações de usuário ou de sistema de banco de dados.

As triggers são similares as stored procedures diferindo, apenas, na maneira como são chamadas. A trigger é executada implicitamente quando ocorre algum evento de trigger enquanto a stored procedure deve ser executado explicitamente.

Uma trigger é composta por quatro partes:

- Momento
- Evento
- Tipo
- Corpo

O momento define quando uma trigger irá ser acionada. Pode ser:

- BEFORE (tabela)
- AFTER (tabela)
- INSTEAD OF (view)

BEFORE indica que os comandos PL/SQL do corpo da trigger serão executados ANTES dos dados da tabela serem alterados. Normalmente usamos BEFORE nos casos em que precisamos incializar variáveis globais, validar regras de negócios, alterar o valor de flags ou para salvar o valor de uma coluna antes de alterarmos o valor delas. Exemplo:

CREATE OR REPLACE TRIGGER novo_func
BEFORE
.
.
.
END;
/

AFTER indica que os comando PL/SQL do corpo da trigger será executado APÓS os dados da tabela serem alterados. Normalmente usamos AFTER para completar os dados de outras tabelas e para completar a atividade de outra trigger de momento BEFORE. Exemplo:

CREATE OR REPLACE TRIGGER novo_func
AFTER
.
.
.
END;
/

INSTEAD OF indica que a trigger irá ser executada no lugar da instrução que disparou a trigger. Literalmente, a instrução é substituída pela trigger. Essa técnica permite que façamos, por exemplo, alterações em uma tabela através de uma view. É usado nos casos em que a view não pode alterar uma tabela por não referenciar uma coluna com a constraint not null. Nesse caso a trigger pode atualizar a coluna que a view não tem acesso.

Dois detalhes muito importantes sobre INSTEAD OF:

- Só funcionam com views e
- É sempre de linha. Será considerado assim, mesmo que “FOR EACH ROW” for omitido.

Exemplo:

CREATE OR REPLACE TRIGGER novo_func
INSTEAD OF INSERT ON vemp
FOR EACH ROW
WHEN …
.
.
.
END;
/

O evento define qual é a instrução DML que aciona a trigger. Informa qual instrução SQL irá disparar a trigger. Pode ser:

- INSERT
- UPDATE
- DELETE

Quando o evento for um UPDATE podemos informar quais colunas que, ao serem alteradas, irão disparar a trigger. O mesmo NÃO ocorre com INSERT e DELETE porque essas instruções sempre afetam a linha por inteiro. Exemplo:

CREATE OR REPLACE TRIGGER novo_func
AFTER INSERT ON emp
.
.
.
END;
/

O evento pode conter uma, duas ou todas as três operações DML em uma única linha de comando. Exemplo:

CREATE OR REPLACE TRIGGER novo_func
BEFORE INSERT OR UPDATE OR DELETE ON emp
.
.
.
END;
/

O tipo define quantas vezes uma trigger será executada. A trigger pode ser executada uma vez para a instrução que a disparou ou ser disparada para cada linha afetada pela instrução que disparou a trigger. Pode ser:

- Instrução (STATEMENT)
- Linha (ROW)

Quando a trigger for do tipo instrução ela será disparada uma vez para cada evento de trigger, mesmo que nenhuma linha tenha sido afetada. São úteis para aquelas trigger que eventualmente não alteram dados ou para situações onde o que queremos é uma resposta da trigger, por exemplo, em uma restrição complexa de negócio. Por DEFAULT toda trigger é deste tipo. Exemplo:

CREATE OR REPLACE TRIGGER novo_func
BEFORE INSERT OR UPDATE OR DELETE ON emp
FOR EACH STATEMENT
.
.
.
END;
/

Quando a trigger for do tipo linha, a trigger será executada toda vez que a tabela for afetada pelo evento da trigger. Se nenhuma linha for afetada a trigger não será executada. São muito úteis quando a ação da trigger depende dos dados afetados pelo evento da trigger. Exemplo:

CREATE OR REPLACE TRIGGER novo_func
BEFORE INSERT OR UPDATE OR DELETE ON emp
FOR EACH ROW
.
.
.
END;
/

O corpo define a ação que uma trigger irá executar quando acionada. O corpo de uma trigger é composto por um bloco PL/SQL, a chamada de uma PROCEDURE ou por um procedimento JAVA. Por definição, o tamanho de uma trigger não pode ultrapassar 32K.

Como, normalmente, precisamos trabalhar com os valores antes e depois da alteração dos dados, a trigger permite que façamos referencia aos valores antes da alteração (OLD) e após a alteração (NEW).

O nome de uma trigger deve ser único dentro de um mesmo esquema, e sua sintaxe básica é:

CREATE [OR REPLACE] TRIGGER [schema.] nome_da_trigger
[BEFORE|AFTER]
[DELETE|OR INSERT|OR UPDATE[OF coluna]]
ON [schema.] nome_da_tabela_ou_da_view
[REFERENCING [OLD [AS] OLD] [NEW [AS] NEW]
[FOR EACH ROW]
[WHEN [condição]]
BLOCO PL/SQL

Onde:

Nome_da_trigger é o nome da trigger;

Nome_da_tabela_ou_da_view indica a tabela ou view associada com a trigger;

Corpo_da_trigger é a ação que a trigger irá executar. Inicia por DECLARE ou BEGIN e termina por END. Também pode conter a chamada de um procedimento.

O uso do nome da coluna na cláusula UPDATE pode aumentar a performance porque a trigger só será disparada quando aquela coluna especificada na cláusula for alterada.

Agora que sabemos como criar uma trigger veremos um exemplo completo:

Primeiro vamos criar uma tabela para gravar um registro de todos os usuários que se conectaram ao banco:

CREATE TABLE vigia
(marca VARCHAR2(100));

CREATE OR REPLACE TRIGGER marca_logon
AFTER LOGON ON DATABASE
BEGIN
INSERT INTO sys.vigia
VALUES (USER || ‘ entrou no sistema em ‘ ||
TO_CHAR(sysdate, ‘DD-MM-YYYY HH24:MI:SS’));
COMMIT;
END;
/

Pronto, temos nossa primeira trigger. Ela registra o nome do usuário e a que horas ele entrou. Esse exemplo foi retirado diretamente da documentação Oracle. No nosso exemplo fazemos referencia a um evento do sistema ao invés de referenciarmos uma tabela. Outros eventos do sistema são:

- AFTER SERVERERROR
- AFTER LOGON
- BEFORE LOGOFF
- AFTER STARTUP
- BEFORE SHUTDOWN

Você pode criar triggers usando os eventos acima para DATABASE e SCHEMA. As duas exceções são SHUTDOWN e STARTUP que só se aplicam a DATABASE. Exemplo:

CREATE OR REPLACE TRIGGER marca_logoff
BEFORE LOGOFF ON SCHEMA
BEGIN
INSERT INTO sys.vigia
VALUES (USER || ‘ saiu do sistema em ‘ ||
TO_CHAR(sysdate, ‘DD-MM-YYYY HH24:MI:SS’));
COMMIT;
END;
/

Eventualmente podemos ter algum tipo de erro em nossa trigger. Para verificar quais são os erros de compilação que temos na trigger basta usar o comando SHOW ERRORS TRIGGER nome_da_trigger. Caso você queira ver os erros de compilação da última trigger que você compilou pode escrever apenas SHOW ERRORS ou SHO ERR. Ao executarmos esse comando ele mostrará a linha onde está o erro. Atenção: caso a linha onde está o erro se estenda por mais de uma linha, este comando indicará o início da linha. Vamos criar uma trigger com erro para servir como exemplo:

CREATE OR REPLACE TRIGGER marca_logon
AFTER LOGON ON DATABASE
BEGIN
INSERT INTO sys.vigia
VALUES (USER || ‘ entrou no sistema em ‘ ||
TO_CHAR(sysdate, ‘DD-MM-YYYY HH24:MI:SS));
COMMIT;
END;
/

Gatilho criado com erro de compilação

Qual é o erro desse gatilho? É um erro bem banal, no caso deixamos de fechar a apóstrofe (ou aspas simples ou quote) no final da instrução TO_CHAR. Ao executarmos o SHOW ERROR ele irá mostrar que houve um erro na linha 4. Isso porque ele aponta onde a linha que contem o erro começou a ser escrita e não a linha onde efetivamente ocorreu o erro está.

Caso precise de mais informações sobre sua trigger, a view USER_TRIGGERS pode fornecer informações muito úteis. Exemplo:

SELECT trigger_name
FROM user_triggers;

Com o nome da trigger que você deseja analisar execute o comando:

SELECT trigger_type, table_name, triggering_event
FROM user_triggers
WHERE trigger_name = ‘nome_da_trigger’;

Ou, se precisar obter o código usado para gerar a trigger:

SELECT trigger_name, trigger_type, triggering_event,
table_name, referencing_names,
status, trigger_body
FROM user_triggers
WHERE trigger_name = ‘nome_da_trigger’;

Caso descubra que não precisa mais da trigger existe duas formas de tratar a situação. Eliminar a trigger ou desabilitá-la.

Eliminando a trigger:

DROP TRIGGER nome_da_trigger;

Caso prefira apenas desabilitar a trigger use o comando:

ALTER TRIGGER nome_da_trigger DISABLE;

Quando a trigger é criada pela primeira vez ela é habilitada automaticamente. Para habilitar a trigger novamente basta usar o comando:

ALTER TRIGGER nome_da_trigger ENABLE;

Mas vamos continuar criando nossas triggers. O próximo caso vai nos ajudar a impedir que alguém cadastre um funcionário fora do horário de expediente:

CREATE TABLE nova_emp
AS SELECT * FROM SCOTT.EMP;

CREATE OR REPLACE TRIGGER hora_exp
BEFORE INSERT ON nova_emp
BEGIN
IF (TO_CHAR(sysdate,’DY’) IN (’SAB’,'DOM’)) OR
(TO_CHAR(sysdate,’HH24:MI’)
NOT BETWEEN ‘08:30′ AND ‘17:30′)
THEN RAISE_APPLICATION_ERROR (-20500,’Você só pode
atualizar os empregados no horário de
expediente’);
END IF;
END;
/

Essa trigger pode ser refinada para testar os predicados condicionais. Por exemplo:

CREATE OR REPLACE TRIGGER hora_exp
BEFORE INSERT OR UPDATE OR DELETE ON nova_emp
BEGIN
IF (TO_CHAR(sysdate,’DY’) IN (’SAB’,'DOM’)) OR
(TO_CHAR(sysdate,’HH24:MI’)
NOT BETWEEN ‘08:30′ AND ‘17:30′)
THEN
IF DELETING THEN
RAISE_APPLICATION_ERROR (-20500,’Você só pode
excluir empregados no horário de expediente’);
ELSIF INSERTING THEN
RAISE_APPLICATION_ERROR (-20502,’Você só pode
incluir empregados no horário de expediente’);
ELSIF UPDATING (’SAL’) THEN
RAISE_APPLICATION_ERROR (-20504,’Você só pode
alterar salarios no horário de expediente’);
ELSE
RAISE_APPLICATION_ERROR (-20506,’Você só pode
Fazer alterações no horário de expediente’);
END IF;
END IF;
END;
/

Vamos ver como usar valores OLD e NEW:

Primeiro vamos criar uma tabela para conter os dados do nosso histórico.

CREATE TABLE DDUR
(USUARIO VARCHAR2(15),
HORARIO DATE,
EMPNO NUMBER(4),
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7,2),
COMM NUMBER(7,2),
DEPTNO NUMBER(2))
/

Agora vamos criar nossa trigger. Ela deve registrar tudo o que fizermos em nossa tabela.

CREATE OR REPLACE TRIGGER hist_emp
AFTER INSERT OR UPDATE OR DELETE ON nova_emp
FOR EACH ROW
BEGIN
INSERT INTO ddur VALUES(
user, sysdate, :OLD.empno, :OLD.ename, :OLD.job,
:OLD.mgr, :OLD.hiredate, :OLD.sal, :OLD.comm, :OLD.deptno);
END;
/

A referência :OLD indica que estamos usando os valores antes da alteração. Caso quiséssemos usar o valor atualizado a referencia seria :NEW. Ambas podem ser usadas na mesma trigger. Por exemplo, nossa trigger poderia ter sido escrita assim:

CREATE OR REPLACE TRIGGER hist_emp
AFTER INSERT OR UPDATE OR DELETE ON nova_emp
FOR EACH ROW
BEGIN
INSERT INTO ddur VALUES(
user, sysdate, :NEW.empno, :NEW.ename, :OLD.JOB,
:NEW.MGR, :OLD.HIREDATE, :OLD.sal, :OLD.comm, :OLD.deptno);
END;
/

Você pode usar :OLD e :NEW em comparações dentro da sua trigger, montando estruturas PL/SQL cada vez mais complexas. Por exemplo:

CREATE OR REPLACE TRIGGER aumento
BEFORE UPDATE OF sal ON emp
FOR EACH ROW
BEGIN
IF (:NEW.sal - :OLD.sal) < :OLD.sal * 0.025
THEN
RAISE_APPLICATION_ERROR (-20512, ‘Favor corrigir indice’);
END IF;
END;

No caso acima, se o aumento de salário for inferior a 2,5% o sistema avisa que houve um erro na alteração salarial. Em um outro exemplo, mas agora com WHEN

CREATE OR REPLACE TRIGGER ver_sal
BEFORE INSERT OR UPDATE OF sal, job
ON empl
FOR EACH ROW
WHEN (NEW.job_id ‘PRESIDENT’)
DECLARE
v_minsal emp.sal%TYPE;
v_maxsal emp.sal%TYPE;
BEGIN
SELECT MIN(sal), MAX(sal)
INTO v_minsal, v_maxsal
FROM emp
WHERE job = :NEW.job;
IF :NEW.sal v_maxsal THEN
RAISE_APPLICATION_ERROR(-20515,’Salario inválido’);
END IF;
END;
/

UPDATE emp
SET sal = 3400
WHERE ename = ‘BLAKE’;

Neste caso estamos garantido que ninguém que for contratado com o cargo diferente de PRESIDENT irá receber um salário menor que o menor salário de seu cargo ou um salário maior que o maior salário de seu cargo.

Uma trigger pode ser bem mais simples do que os exemplos acima. Por exemplo, se quisermos implementar uma restrição onde o salário do funcionário nunca possa ser reduzido, basta aplicarmos a trigger:

CREATE OR REPLACE TRIGGER veri_sal
BEFORE UPDATE OF sal ON emp
FOR EACH ROW
WHEN (NEW.sal < OLD.sal)
BEGIN
RAISE_APPLICATION_ERROR (-20508,
‘O salário não pode ser reduzido’);
END;
/

Para que um usuário crie suas próprias triggers ele precisa ter o privilégio de sistema CREATE TRIGGER e ser o proprietário da tabela onde irá criar a trigger. Caso não seja proprietário ele deve ter o privilégio de sistema ALTER ou ALTER ANY TABLE. Caso precise criar triggers para eventos do banco de dados deve ter o privilégio de ADMINISTER DATABASE TRIGGER. Caso a trigger faça chamada de alguma procedure, quem estiver criando a trigger deve ter o privilégio de EXECUTE na procedure.

Como podemos notar as trigger podem ser usadas de forma bem flexível. Com elas podemos gerar mecanismos de segurança mais flexíveis, auditar dados de tabelas e implementar regras de negócios com mais facilidade.

Fonte: http://www.linhadecodigo.com.br/ArtigoImpressao.aspx?id=322
Autor: Milton Goya

Abraços galera!

Procedimentos (stored procedure)

julho 8th, 2009 por antonioDBA

Boa tarde pessoal,

Resolvi dedicar este post a um assunto muito importante dentro de PL/SQL e importantíssimo para quem deseja trabalhar com Oracle: Procedure. Ainda sente dúvida em Procedure? Então leia este post:

Procedimentos (stored procedure)

Uma procedure nada mais é que um bloco PL/SQL nomeado que pode aceitar argumentos (também chamado de parâmetros) e pode ser chamada por um programa, uma sessão SQL ou uma trigger.
Durante a instalação do banco de dados Oracle um script é executado automaticamente e cria toda a estrutura necessária para que as procedures sejam executadas. Eventualmente esse procedimento automático pode falhar devido a alguma falha física no disco rígido, nesse caso o usuário SYS pode recriar a estrutura através do script SQL DBMSSTDX.SQL.
Para criar uma procedure o usuário precisa ter o privilégio de sistema CREATE PROCEDURE, para criar a procedure em outros schemas o usuário deve ter o privilégio de CREATE ANY PROCEDURE. Este é um ponto muito interessante sobre as procedures, os privilégios para criação de procedures têm que concedidos explicitamente, ou seja, não pode ser adquirido através de roles.
Para executar uma procedure externa é necessário ter o privilégio de EXECUTE. Caso queira alterar a procedure de outro schema deve ter o privilégio de sistema ALTER ANY PROCEDURE.

A sintaxe básica de uma procedure é:
CREATE [OR REPLACE] PROCEDURE [schema.]nome_da_procedure
[(parâmetro1 [modo1] tipodedado1,
parâmetro2 [modo2] tipodedado2,
…)]
IS|AS
Bloco PL/SQL

Onde:
REPLACE - indica que caso a procedure exista ela será eliminada e substituída pela nova versão criada pelo comando;
BLOCO PL/SQL - inicia com uma cláusula BEGIN e termina com END ou END nome_da_procedure;
NOME_DA_PROCEDURE - indica o nome da procedure;
PARÂMETRO - indica o nome da variável PL/SQL que é passada na chamada da procedure ou o nome da variável que retornará os valores da procedure ou ambos. O que irá conter em parâmetro depende de MODO;
MODO - Indica que o parâmetro é de entrada (IN), saída (OUT) ou ambos (IN OUT). É importante notar que IN é o modo default, ou seja, se não dissermos nada o modo do nosso parâmetro será, automaticamente, IN;
TIPODEDADO - indica o tipo de dado do parâmetro. Pode ser qualquer tipo de dado do SQL ou do PL/SQL. Pode usar referencias como %TYPE, %ROWTYPE ou qualquer tipo de dado escalar ou composto. Atenção: não é possível fazer qualquer restrição ao tamanho do tipo de dado neste ponto.
IS|AS - a sintaxe do comando aceita tanto IS como AS. Por convenção usamos IS na criação de procedures e AS quando estivermos criando pacotes.
BLOCO PL/SQL - indica as ações que serão executadas por aquela procedure.

Vamos ver um exemplo de procedure para ajudar nosso entendimento:
CREATE OR REPLACE PROCEDURE aumenta_sal
(p_empno IN emp.empno%TYPE)
IS
BEGIN
UPDATE scott.emp
SET sal = sal * 1.10
WHERE empno = p_empno;
END aumenta_sal;
/

Neste exemplo estamos criando uma procedure para aumentar o salário de um funcionário em 10%. A primeira linha define o NOME DA PROCEDURE, que vai ser AUMENTA_SAL.
A linha dois define o parâmetro P_EMPNO no modo IN. Ou seja, vai ser um dado informado na chamada da procedure. Em seguida determinamos que ele será do mesmo tipo e tamanho que a coluna EMPNO da tabela EMP. Isso é feito através da referencia EMP.EMPNO%TYPE.

Podemos verificar o estado de nossa procedure através de uma simples consulta:
SELECT object_name, status
FROM user_objects
WHERE object_name LIKE ‘%AUMENTA%’;
Agora podemos verificar o funcionamento de nossa procedure:
SELECT empno, sal
FROM scott.emp;

EMPNO SAL
———- ———-
7839 5000
7698 2850
7782 2450

CALL AUMENTA_SAL(7839);
Ou
EXECUTE AUMENTA_SAL(7839);

SELECT empno, sal
FROM scott.emp;

EMPNO SAL
———- ———-
7839 5500
7698 2850
7782 2450

Podemos notar que o salário do funcionário 7839 aumentou em 10%. É interessante notar que neste momento é possível executar a instrução ROLLBACK;
É possível desfazer as alterações porque os dados passados através dos modos OUT e IN OUT são registrados no arquivo de redo log e no segmento de rollback. Isso é perfeito quando trabalhamos com parâmetros pouco extensos, mas pode causar impacto no sistema quando trabalhamos com parâmetros extensos como, por exemplo, um registro ou um VARRAY. Para resolver esse problema podemos usar a opção de NOCOPY. Nossa procedure ficaria assim com a opção NOCOPY:

CREATE OR REPLACE PROCEDURE aumenta_sal
(p_empno IN OUT NOCOPY emp.empno%TYPE)
IS
BEGIN
UPDATE scott.emp
SET sal = sal * 1.10
WHERE empno = p_empno;
END aumenta_sal;
/

Com nossa alteração o valor passado em nosso parâmetro não é gravado no arquivo de redo log e nem no segmento de rollback. Isso implica que, neste caso, NÃO É POSSÍVEL FAZER ROLLBACK. A documentação Oracle afirma que há ganho de performance de 30% a 200% nos casos em que tabelas PL/SQL eram passadas como parâmetro na procedure.
Notem que a procedure pôde ser chamada através do comando CALL quanto pelo comando EXECUTE. Isso ocorre porque uma procedure pode ser chamada a partir de qualquer uma das ferramentas de desenvolvimento Oracle como, por exemplo, o SQL*Plus. Uma das vantagens das procedures é que elas podem ser chamadas a partir de uma aplicação, de outra procedure, de uma trigger e até mesmo a partir de uma simples query.
Exemplo:

BEGIN
AUMENTA_SAL(7839);
END;
/

Durante a criação de nossa procedure pode ocorrer algum erro. Nesse caso será mostrada uma mensagem semelhante a esta:
Aviso: Procedimento criado com erros de compilação.

Ou

MGR-00072: Warning: Procedure AUMENTA_SAL created with compilation errors
Nesse caso o erro pode ser determinado através do SHOW ERROR pode ser usado para listar a linha/coluna onde o erro ocorreu. O comando SHOW ERROR sem parâmetros adicionais mostra os erros da última compilação. Podemos qualificar o comando usando o nome de nosso pacote, procedure, função, trigger ou corpo de pacote.
Por exemplo:

SHOW ERROR aumenta_sal
Ou
SHOW ERROR PROCEDURE aumenta_sal

Vamos criar uma procedure com erro para ver como o comando funciona:
CREATE OR REPLACE PROCEDURE mand_embora
(emp_num NUMBER) IS
BEGIN
DELETE FROM emp
WHER empno = emp_num;
END
/

Notem que falta a letra E em WHERE e falta um ponto-e-vírgula no final de END. Ao executarmos o SHOW ERROR teremos:
SQL> SHOW ERROR
Erros para PROCEDURE MAND_EMBORA:

LINE/COL ERROR
——– —————————————————-
5/14 PLS-00103:Encontrado o símbolo “EMPNO” quando um dos
seguintes símbolos era esperado:
; return returning where
O símbolo “where” foi substituído por “EMPNO” para
continuar.

7/0 PLS-00103: Encontrado o símbolo “end-of-file” quando
um dos seguintes símbolos era esperado:
;
delete exists prior
O símbolo “;” foi substituído por “end-of-file” para
continuar.
Notem que foram listadas as linhas e a colunas onde ocorreram os erros. O ponto-e-vírgula foi mostrado na linha 7 porque só no momento em que foi encerrado o bloco PL/SQL que o compilador “notou” a falta do último ponto-e-vírgula.
O SHOW ERROR é muito útil, mas, eventualmente, temos necessidade de obter mais dados sobre os erros. Neste caso é possível consultar as views de dicionário de dados:

• USER_ERRORS
• ALL_ERRORS
• DBA_ERRORS

Caso haja necessidade é possível obter o código fonte da procedure através das views de dicionário de dados ALL_SOURCE, USER_SOURCE e DBA_SOURCE.
Exemplo:

SELECT text
FROM user_source
WHERE name = ‘MAND_EMBORA’
ORDER BY line;

Eventualmente podemos precisar ver todas procedures e todas as funçoes do nosso usuário. Nesse caso podemos usar:
COL FOR object_name A35

SELECT object_name, object_type
FROM user_objects
WHERE object_type in (’PROCEDURE’,
‘FUNCTION’)ORDER BY object_name;

Caso precisemos apenas dos argumentos de nossa procedure o comando DESC permite identifica-los rapidamente.
Exemplo:
DESC mand_embora

Vejamos o uso de uma chamada de procedure com o uso do modo OUT. Vamos criar uma procedure que consulte a tabela de empregados através do número do empregado e retorne o salário e o cargo do mesmo.
CREATE OR REPLACE PROCEDURE query_emp
(p_empid IN emp.empno%TYPE,
p_sal OUT emp.sal%TYPE,
p_job OUT emp.job%TYPE)
IS
BEGIN
SELECT sal, job
INTO p_sal, p_job
FROM scott.emp
WHERE empno = p_empid;
END query_emp;
/

Agora vamos usar nossa procedure. Note que ela deve ser chamada com um parâmetro de entrada e com dois parâmetros de saída. Vamos declarar duas variáveis globais para receber os valores da procedure: G_SAL e G_JOB:
VARIABLE g_sal NUMBER
VARIABLE g_job VARCHAR2(15)
EXECUTE query_emp (7900, :g_sal, :g_job)
PRINT g_sal
PRINT g_job

Caso não usemos todos os parâmetros definidos para nossa procedure quando formos chamá-la teremos um erro:
SQL> call query_emp(7900);
call query_emp(7900)
*
ERRO na linha 1:
ORA-06553: PLS-306: número incorreto de tipos de argumentos na chamada para ‘QUERY_EMP’
Também ocorrerá um erro caso o empregado pesquisado não exista. Exemplo:
SQL> EXECUTE query_emp (120, :g_sal, :g_job)
BEGIN query_emp (120, :g_sal, :g_job); END;

*
ERRO na linha 1:
ORA-01403: dados não encontrados
ORA-06512: em “SYS.QUERY_EMP”, line 7
ORA-06512: em line 1
Esse tipo de erro pode ser tratado pelo próprio programador. Vamos criar uma procedure que elimine todos os funcionários com o cargo que for informado pelo usuário e apresente um erro caso o cargo não exista:
CREATE OR REPLACE PROCEDURE del_job
(p_jobid IN emp.job%TYPE)
IS
BEGIN
DELETE FROM scott.emp
WHERE job = p_jobid;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20203,’Cargo não existe.’);
END IF;
END DEL_JOB;
/

Ao executarmos nossa procedure com um cargo que não exista obteremos a mensagem de erro que definimos:
SQL> execute del_job(’Presidente’)
BEGIN del_job(’Presidente’); END;

*
ERRO na linha 1:
ORA-20203: Cargo não existe.
ORA-06512: em “SYS.DEL_JOB”, line 8
ORA-06512: em line 1
Veja, logo após “linha 1:” o código de erro “Cargo não existe”.
Vamos ver como uma procedure pode agir como um subprograma. Primeiro vamos criar uma procedure para calcular o valor de Delta.
CREATE OR REPLACE PROCEDURE delta
(p_a IN number,
p_b IN number,
p_c IN number,
p_delta OUT number)
IS
BEGIN
p_delta := (p_b * p_b) - (4 * p_a * p_c);
END delta;
/
Agora vamos criar uma procedure que calcule o valor das raízes de delta:
CREATE OR REPLACE PROCEDURE eq2g
(p_a IN number,
p_b IN number,
p_c IN number,
p_x1 OUT number,
p_x2 OUT number)
IS
p_delta NUMBER;
BEGIN
delta(p_a, p_b, p_c, p_delta);
IF p_delta < 0 then
p_x1 := -1;
p_x2 := -1;
ELSE
p_x1 := -1 * p_b + sqrt(p_delta)/(2 * p_a);
p_x2 := -1 * p_b - sqrt(p_delta)/(2 * p_a);
end if;
end eq2g;
/

Notem que P_DELTA foi declarado depois de IS, mas sem um DECLARE. Isto foi feito porque em uma procedure não aceita DECLARE e sua seção de declaração fica entre IS e BEGIN. Nossa procedure está chamando a procedure DELTA para calcular o delta de nossa equação. Agora vamos executar nossa procedure.
VARIABLE g_x1 NUMBER
VARIABLE g_x2 NUMBER
EXECUTE eq2g (1, 4, 2, :g_x1, :g_x2)
PRINT g_x1
PRINT g_x2
Em nossa procedure quando o delta for negativo, os valores das raízes X1 e X2 retornam com -1. É claro que existem soluções melhores do que esta, trabalhar com raízes imaginárias ou dar uma mensagem de erro quando isso acontecer.

Fonte: http://www.linhadecodigo.com.br/ArtigoImpressao.aspx?id=335
Autor: Milton Goya

Grande abraço e sucesso!