Lomadee, uma nova espécie na web. A maior plataforma de afiliados da América Latina

Potência / Expoentes em SQL e PL/SQL – Oracle

Fala Pessoal,

Hoje vai mais uma dica de SQL e PL/SQL.

Até o dia de hoje, eu nunca tinha necessitado usar expoente no SQL / PL/SQL, nunca tinha pego nenhum problema em desenvolvimento que precisasse ser usado potência, expoente e tal.

Porém, hoje uma amiga desenvolvedora, Leilah, precisou dessa funcionalidade e aí discutimos um pouco sobre o assunto. Descobri portanto, que no Oracle, não precisamos fazer muita conta e nem usar sintaxes esquisitas para usar potência e elevar um número a uma determinada potência, basta usarmos a função POWER, isso mesmo, funciona assim:

Exemplo SQL:

SQL> select power(2,3) from dual;
POWER(2,3)
----------
8

Neste exemplo, temos 2 elevado a 3, que nos dá 8 como resultado…

Exemplo PL/SQL:

SQL> declare
2 v_num number;
3 begin
4 v_num := power(2,3);
5 dbms_output.put_line('O numero 2 elevado a 3 é: '||to_char(v_num));
6 end;
7 /
O numero 2 elevado a 3 é: 8
Procedimento PL/SQL concluÝdo com sucesso.

Pronto pessoal, fica aí a dica de utilização de potência em PL/SQL.

Espero que gostem.

Grande abraço.

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Lomadee, uma nova espécie na web. A maior plataforma de afiliados da América Latina

Dica de SQL – Primeiro sábado do mês seguinte

Fala PessoAll,

Recebi um email do amigo Vitor Ugo sobre uma solicitação que ele havia recebido para criação de um Job.

Até aí moleza, como podemos ver no post: Job no Oracle criar um Job é fácil! Só que este Job tem uma particularidade, ele deve rodar apenas no primeiro sábado de cada mês.

Com isso, fiz a dica para Vitor, dele colocar o job para executar todo dia, e antes de chamar a procedure do job fazer um teste e identificar se era o primeiro sábado, se sim, beleza roda a procedure, senão, não faz nada! Funcionaria, porém não é uma solução das mais bonitas, porque mesmo sem fazer nada, o job executaria todos os dias.

Foi então que o Vitor desenvolveu um select, que recupera o primeiro sábado do mês seguinte, e resolveu todos os problemas.

Segue o select desenvolvido por Vitor:


select LEAST(NEXT_DAY(ADD_MONTHS(trunc(sysdate,'MM')+(8/24),1)-1,7),
next_day(ADD_MONTHS(trunc(sysdate,'MM')+(8/24),1),7)) from dual;

Neste select o “7″ indica que é um sábado, caso desejem outro dia da semana, basta que vocês alterem esse número para o dia desejado!

É isso, fica aí a dica. Espero que gostem

Abraço a todos.

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Lomadee, uma nova espécie na web. A maior plataforma de afiliados da América Latina

Copiar tabela no Oracle – Backup de tabela

Fala PessoAll,

Uma coisa bastante útil e bastante simples que podemos precisar no nosso dia a dia é fazer uma cópia de uma determinada tabela do nosso banco de dados.

Possíveis casos:

1 – Um update nas colunas;
2 – Deleção de alguns registros;

Entre outros que envolvam os dados contidos nesta tabela.

Portanto, em casos como esses, queremos garantir que caso dê alguma “caca” tenhamos de onde recuperar as informações rapidamente, nada mais rápido que um select em uma tabela que encontra-se no mesmo banco, sem precisar voltar backup, sem precisar acionar DBA, sem nada.

Vamos ao exemplo:

Vamos supor que temos em nosso banco de dados uma tabela de módulos do nosso sistema, chamada TB_MODULOS, e precisaremos fazer umas alterações nesta tabela… Para garantir, vamos fazer uma cópia dela.

Primeiro vamos contar quantos registros temos na nossa tabela de origem, pra ter certeza que a cópia levou tudo, não adianta termos uma cópia inconsistente!

SQL> select count(*) from tb_modulos;
COUNT(*)
----------
264960

Beleza, nossa tabela tem 264.960 linhas! Portanto, nossa cópia tem que estar exatamente igual!!

Vamos agora fazer a cópia da tabela:

SQL> create table tb_modulos_22012010 as select * from tb_modulos;
Tabela criada.

Depois da tabela criada, vamos contar a nova tabela, pra garantir que tem a mesma quantidade de registros!!

SQL> select count(*) from tb_modulos_22012010;
COUNT(*)
----------
264960

Pronto, nossa cópia funcionou perfeitamente, todos os 264.960 registros que tinhamos em TB_MODULOS agora estão em TB_MODULOS_22012010, podemos agora proceder com as alterações na tabela de módulos sem maiores problemas no caso de ocorrer um erro! Garantia é o melhor remédio!!! Rsrs.

Portanto, vimos que temos como fazer uma cópia de forma rápida de uma tabela do nosso banco de dados. O comando padrão para isso é: create table "TABELA_NOVA" as select * from "TABELA_ANTIGA", lembrando que desta forma você faz uma cópia da tabela inteira, mas você pode muito bem selecionar apenas algumas colunas, fazer um filtro usando uma cláusula where e etc… a “moral da história” é que: será criada uma tabela nova com o resultado do select que você fizer!!

Mas… depois da alteração pronta e validada, lembrem-se de dropar a tabela de backup.

Espero que gostem e que seja útil!

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Lomadee, uma nova espécie na web. A maior plataforma de afiliados da América Latina

Oracle – SQL TRACE – TKPROF

Fala PessoAll,

Estamos aqui novamente para compartilhar mais uma experiência.

Dessa vez com algo bastante básico para quem quer se especializar em performance de aplicações, que é o meu caso!!

Em alguns momentos na nossa vida de DBA nos deparamos com processos que são um tanto quanto complexos de serem analisados, por exemplo: Uma procedure que demora muito ou uma query que demora demais para retornar ou um procedimento inteiro que tem todas as querys otimizadas mas demora muito entre outras coisas. Para que possamos analisar estes tipos de problemas, temos um grande aliado que é o SQL_TRACE, ele vai gerar uma espécie de “relatório” com todas as query´s envolvidas no processamento, e nos mostrar o que cada query fez, o plano de execução de cada uma, quanto tempo demorou para rodar, quanto de CPU consumiu, quantas vezes foi executada, isso nos dá uma visão exata do que está ocorrendo, podendo ser até um erro de lógica na aplicação, onde por exemplo, devido a um erro uma determinada query é executada milhares de vezes sem necessidade.

Hoje vou mostrar como fazemos para gerar um trace de uma determinada operação no banco e como formatar este trace de forma que possamos ler e entender o passo a passo da execução. Vamos lá!

O primeiro passo é alterar a sessão que o processo vai rodar para que o trace seja gerado, isso pode ser feito com o comando:

ALTER SESSION SET SQL_TRACE=TRUE;

Após este commando, podemos executar a nossa rotina lenta, que um arquivo será gerado com o que esta rotina fez.

Begin
Nossa_Rotina_Lenta(1,4,4);
End;

Após a conclusão do processamento, devemos ir até o local onde foi gerado o arquivo, no meu caso, o arquivo é gerado no caminho: {ORACLE_BASE}\admin\negraod\udump

Se você tentar abrir o arquivo gerado, possivelmente não vai conseguir entender nada! Para que nosso arquivo fique legível, vamos usar um utilitário chamado TKPROF. Esse utilitário tem como objetivo interpretar o trace e deixar ele num formato legível.

O uso do TKPROF é da seguinte forma: tkprof trace.trc arquivo_saida.txt explain=usuário/senha@banco

Depois deste comando executado, no seu arquivo de saída, terá um conteúdo parecido com este:

********************************************************************************
count = Numero de vezes que o procedimento foi executado
cpu = Tempo em segundos executando pelo CPU
elapsed = Tem em segundos para execução do procedimento
disk = Numero de leituras físicas no disco
rows = Numero de linhas processadas pelo comando
********************************************************************************

SELECT COUNT(*)
FROM dual

call count cpu elapsed disk query current rows
——- —– —– ——- ——- ——- ——- ——-
Parse 1 0.02 0.02 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.00 0 1 4 1
——- —– —– ——- ——- ——- ——- ——-
total 4 0.02 0.02 0 1 4 1

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 121

Rows Row Source Operation
——- —————————————————
1 SORT AGGREGATE
1 TABLE ACCESS FULL DUAL

Neste exemplo, conseguimos ler e ver o que aconteceu com a query, além do plano de execução que ela utilizou para executar.

Depois disso é analisar as query´s mais complexas e atacar na mudança delas, em muitos casos é necessário a mudança da lógica da rotina, para que se possa ganhar alguma performance!

É isso pessoal. Espero que ajude vocês!

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Lomadee, uma nova espécie na web. A maior plataforma de afiliados da América Latina

Utilizando Compartilhamento Windows no Linux

Fala PessoAll,

Bom, hoje tivemos mais um desafio bem interessante.

Recebemos um dump de um determinado cliente, o arquivo de dump (X.dmp) veio com 260Gb em um único arquivo. Infelizmente, na máquina Linux onde a base está instalada não tinha nenhum disco com esta quantidade de espaço livre. E agora pra importar esse dump??

Vasculhamos nossos servidores e achamos um servidor com mais de 260Gb livre, dando sopa! Que beleza, problema resolvido!

Idéia 1: Descompactamos os 260Gb neste servidor e a partir dele fazemos o import na máquina destino, tudo certo! NÃO! Este servidor roda Oracle 10G e o servidor de destino roda Oracle 9i, não funciona! Que falta de sorte!

Idéia 2: Descompactamos neste servidor e através da rede, criamos um mapeamento da máquina onde será importado, para esta máquina que tem espaço sobrando e tudo certo! Ok? NÃO de novo. O servidor que tem esse espaço é um Windows 2003 Server, e a máquina onde a base está rodando e o dump teria que ser importada, estava rodando Linux… Red Hat Enterprise.

Mas… porque não? Será que não tem como fazer? Pesquisando na internet achei alguns sites que explicavam como fazer e aí decidi testar. E, para alegrar ainda mais minha sexta-feira, funcionou beleza! Como se fosse uma pasta na máquina Linux.

Segue o passo a passo:


Inicialmente deve-se verificar os compartilhamentos disponíveis na máquina destino
[oracle@oracle9i oracle]$ smbclient -L 192.168.0.13 -U oracle
Password:
Sharename Type Comment
--------- ---- -------
IPC$ IPC IPC remoto
D$ Disk Recurso compartilhado padrão
RV Disk
SQLLDR Disk
ADMIN$ Disk Administração remota
C$ Disk Recurso compartilhado padrão

Em seguida deve-se conectar como SU
[oracle@oracle9i oracle]$ su -
Password:

Depois deve ser criada a pasta que irá exibir os dados do compartilhamento
[root@oracle9i root]# mkdir /mnt/Dump_Carref

Depois deve ser executado o commando que efetivamente vai criar o link
[root@oracle9i root]# mount -t smbfs -o username=oracle,password=oracle01 //192.168.0.13/SQLLDR /mnt/Dump_Carref

Depois disso já podemos listar o conteúdo da pasta, que já será exibido o conteúdo do mapeamento em questão
[root@oracle9i root]# ls /mnt/Dump_Carref
IN

É isso!

Espero que seja útil também pra vocês!

Grande abraço.

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Lomadee, uma nova espécie na web. A maior plataforma de afiliados da América Latina

Notebook com Windows 7 para um DBA

Fala PessoAll,

Creio que muita gente está pensando e vivendo um grande dilema: Migro ou não para o Windows 7.

Comprei uma máquina nova, um Dell Vostro 1320, como todas as máquinas recentes eu tinha direito ao upgrade gratuito do Vista para o Windows 7, e claro eu decidi arriscar instalar o 7 pra ver como sairia no ambiente de trabalho, enfim no dia a dia de um DBA.

Meio receioso… com o CD do XP Professional do lado, para que em caso de problemas, não perdesse tempo, iniciei a instalação.

Primeira coisa: Particionar o HD, claro… C:\ e D:\, arquivos todos no D:\ e S.O no C:\ em caso de problemas… Formata apenas o C:\, instala o S.O novo e tá tudo certo!

Para este passo, evitando quebrar cabeça, pesquisei alguém que já tivesse feito algo e achei um vídeo no Youtube que explicava direitinho como fazer. O vídeo é Como Formatar um Computador e instalar o Windows 7. Claro que eu já tinha uma noção boa, mas usando Windows XP… o vídeo serve só pra conferir se não tem nenhuma particularidade, e não tem!

Pronto… Windows 7 Ultimate instalado! Rodando 100%

Agora vem o desafio, instalar o Oracle!

Pesquisei em alguns sites, e confirmei que existe uma versão do Oracle para Windows Vista e que funciona no Windows 7. Como todo e qualquer download de produtos Oracle, fui até o OTN (http://otn.oracle.com) e dei uma pesquisada nas versões disponíveis do Database, e encontrei a tal versão para Vista, que pode ser encontrada no link: Oracle 10g para Windows Vista e 2k8, depois do download, fiz a instalação! Ele deu um erro dizendo que o S.O não era homologado para aquela versão do Oracle. Solução: Marcar o checkbox dizendo que tá sabendo, mas quer instalar assim mesmo! Pronto. Instalado, Oracle no ar, rodando, sem problema algum! Já dei shutdown/startup pra ver se ia subir numa boa, e até então tudo certo!

Depois disso vem as nossas queridas ferramentas! Tão importantes no nosso dia a dia!

Até então estão instaladas e funcionando normalmente:

- PL/SQL Developer (FrontEnd Oracle)
- Toad (FrontEnd Oracle)
- UltraEdit (Editor poderoso de Texto)
- UltraVNC (Irmão do VNC fee e mais poderodo)
- One Studio (Ferramenta de controle de solicitações)
- Putty (Ferramenta de conexões com ambientes Unix)

Tudo isso funcionando normalmente, como se fosse o bom e velho XP, só que muito mais rápido e muito mais bonito!

As demais atividades que precisamos fazer como DBA, podemos conectar via Terminal Server e fazer sem problemas, como sempre fizemos! No mais, está tudo certo! Rodando, funcionando e aprovado!

Estou agora desfrutando da novidade, como diria Jessier Quirino: “Eu ando é na frente, feito bengala de cego!”

Abraço a todos.

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Lomadee, uma nova espécie na web. A maior plataforma de afiliados da América Latina

Job não executa no Oracle 8i (DBA)

Fala PessoALL,

Bom, ontem me deparei com mais um pequeno probleminha…
Criei um Job em um banco de dados Oracle 8i, o job estava criado certinho, com as datas de Next_Sec setadas, ou seja, tudo perfeito pra rodar. Pra confirmar se a procedure do Job estava ok, executei manualmente o Job, pra ver se seria alimentado o campo Failures, ou se manteria 0 (zero).

Executei manualmente assim:

begin
dbms_job.run(1);
end;

Depois conferi e Failures permanecia 0 (zero), perfeito. Era só esperar a próxima hora de execução (Next_Sec) e ele rodaria perfeitamente! No horário esperado… cadê??? Nada do Job executar!

Aí vamos as pesquisas… recorri ao grupo GPOracle e aí me veio a dica: “Dá uma olhada no parâmetro JOB_QUEUE_PROCESSES“.

Então vamos lá, olhar o parâmetro:


SQL> select name, value from v$parameter where name like '%job_queue%';

NAME VALUE
--------------------- ------------------
job_queue_processes 0

Hum… está como 0 (zero), ou seja, estou dizendo pro banco que nenhum processo de Job vai rodar na minha base.

Beleza, então vamos alterar este parâmetro.

Supondo que você está conectado com um usuário com tal privilégio…


SQL> alter system set job_queue_processes=10;

Sistema alterado.

SQL> select name, value from v$parameter where name like '%job_queue%';

NAME VALUE
--------------------- ------------------
job_queue_processes 10

Pronto! Como este parâmetro é dinâmico, seu banco já está ok! Seus Job’s já vão funcionar normalmente.

Lembrando que para que a alteração se mantenha em um possível shutdown -> startup no seu banco, é necessário que no arquivo initBASE.ora deve ser adicionada a linha job_queue_processes=10 para que na inicialização este parâmetro seja devidamente carregado.

É isso gente, espero que seja útil pra vocês!!

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Lomadee, uma nova espécie na web. A maior plataforma de afiliados da América Latina

Validando Digito Verificador Inscrição Estadual Bahia (BA)

Fala PessoAll,

Bom, como toda e boa pessoa normal, de vez em quando bate a saudade das épocas de desenvolvimento, de quebrar cabeça para fazer alguns códigos “ninja” pra resolver alguns problemas do nosso Dia a Dia (Oracle, rsrs).

Otem me deparei com a demanda de um amigo, precisando fazer uma validação do dígito da Inscrição estadual da Bahia, em PL/SQL. Vamos lá!

Primeiro passo: Pesquisar como se faz a validação do dígito verificador da inscrição estadual da BAHIA!! BAHIA!! Ninguém melhor que a Sefaz/BA pra me dizer isso. Então, fui no site da SEFAZ/BA e achei como fazer a validação, depois foi só cair no PL/SQL de cabeça e colocar pra funcionar. A página que diz como deve ser feita a validação é: http://www.sefaz.ba.gov.br/contribuinte/informacoes_fiscais/doc_fiscal/calculodv.htm.

Segue abaixo a function utilizada para fazer esta validação. Essa function retorna ‘S’ caso esteja OK e ‘N’ caso não seja validado o dígito verificador.


create or replace function valida_dig_inscest_BA(pInscEstadual varchar2) return varchar2 is
v_IE varchar2(10);

idig1 number;
idig2 number;

iRes1 number;
iRes2 number;

cBase1 number;
cBase2 number;
begin
v_IE := rtrim(replace(replace(replace(pInscEstadual, '.', ''), '-', ''), '/', ''));

if length(v_IE) <> 8 then
return('N');
end if;

iRes1 := 0;
iRes2 := 0;

cBase1 := substr(v_IE, 1, 6);
iDig1 := substr(v_IE, 7, 1);
iDig2 := substr(v_IE, 8, 1);

--Se o primeiro dígito for um dos testados, modulo 10, senao, modulo 11
if(substr(cBase1, 1, 1) in (0, 1, 2, 3, 4, 5, 8)) then
--Faz um loop de 7 até 2...
for i in reverse 2 .. 7 loop
--Verifica se o numero encontrado é válido.
if instr('0123456789', SubStr(cBase1, (7-i)+1, 1)) > 0 Then
--Sendo válido, já soma com a multiplicação pelo indice.
ires2 := ires2 + (SubStr(cBase1, (7-i)+1, 1) * i);
else
return('N');
end if;
end loop;

--Recupera o resto do calculo realizado por 10
ires2 := mod(ires2, 10);

--Se for 0, o digito é zero.
if(ires2 = 0) then
ires2 := 0;
--Se não for zero, subtrai o valor de 10
else
ires2 := 10 - ires2;
end if;

--O numero para o calculo do primeiro digito, é os 6 primeiros + o digito 2
cBase2 := cBase1||ires2;

--Faz um loop de 8 até 2...
for i in reverse 2 .. 8 loop
--Verifica se o numero encontrado é válido.
if instr('0123456789', SubStr(cBase2, (8-i)+1, 1)) > 0 Then
--Sendo válido, já soma com a multiplicação pelo indice.
ires1 := ires1 + (SubStr(cBase2, (8-i)+1, 1) * i);
else
return('N');
end if;
end loop;

--Recupera o resto do calculo realizado por 10
ires1 := mod(ires1, 10);

--Se for 0, o digito é zero.
if(ires1 = 0) then
ires1 := 0;
--Se não for zero, subtrai o valor de 10
else
ires1 := 10 - ires1;
end if;

--Se resultado 1 e 2 iguais a digitos 1 e 2, é válido
if(ires1 = idig1 and ires2 = idig2) then
return('S');
else
return('N');
end if;
--Se começa com 6, 7 ou 9
else
--Faz um loop de 7 até 2...
for i in reverse 2 .. 7 loop
--Verifica se o numero encontrado é válido.
if instr('0123456789', SubStr(cBase1, (7-i)+1, 1)) > 0 Then
--Sendo válido, já soma com a multiplicação pelo indice.
ires2 := ires2 + (SubStr(cBase1, (7-i)+1, 1) * i);
else
return('N');
end if;
end loop;

--Recupera o resto do calculo realizado por 11
ires2 := mod(ires2, 11);

--Se for 0, o digito é zero.
if(ires2 = 0) then
ires2 := 0;
--Se não for zero, subtrai o valor de 11
else
ires2 := 11 - ires2;
end if;

--O numero para o calculo do primeiro digito, é os 6 primeiros + o digito 2
cBase2 := cBase1||ires2;

--Faz um loop de 8 até 2...
for i in reverse 2 .. 8 loop
--Verifica se o numero encontrado é válido.
if instr('0123456789', SubStr(cBase2, (8-i)+1, 1)) > 0 Then
--Sendo válido, já soma com a multiplicação pelo indice.
ires1 := ires1 + (SubStr(cBase2, (8-i)+1, 1) * i);
else
return('N');
end if;
end loop;

--Recupera o resto do calculo realizado por 10
ires1 := mod(ires1, 11);

--Se for 0, o digito é zero.
if(ires1 = 0) then
ires1 := 0;
--Se não for zero, subtrai o valor de 10
else
ires1 := 11 - ires1;
end if;

if(ires1 = idig1 and ires2 = idig2) then
return('S');
else
return('N');
end if;
end if;
end;

É isso aí gente, espero que seja útil.

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Lomadee, uma nova espécie na web. A maior plataforma de afiliados da América Latina

JOB no ORACLE – Definindo a periodicidade. (INTERVAL)

Fala PessoALL,

Bom, atendendo à dica do amigo Alessandro Varela (http://blogdovarela.com.br) hoje falarei sobre: Como definir corretamente a periodicidade da execução dos seus Job’s! Complica não? É nada!! Vamos lá!

Espero que todos tenham lido o post que fiz falando sobre Job’s, caso não tenha lido, ainda dá tempo, basta ler o post Jobs no Oracle.

Bom, quando fazemos a criação de um Job, é porque temos a necessidade que uma determinada tarefa seja executada de tempos em tempos, e para isso geralmente precisamos definir um intervalo para que o Job seja executado novamente. Por exemplo: Quero que meu Job rode a cada hora, quero que meu Job rode todo dia de 23:00, quero que meu job rode a cada 5 minutos, e assim por diante. Só que no momento de fazer esta parametrização é quando começa a confusão, pois, as pessoas esquecem de que o Job vai rodar sozinho e ele é quem tem que definir a próxma execução! Para simplificar isso, vamos lá!

Todo mundo lembra no post anterior que eu falei que para criar um Job usamos a package DBMS_JOB e a procedure DBMS_JOB.SUBMIT(...), certo? Pois é, nesta procedure, um dos parâmetros que é passado é um tal de INTERVAL, ou seja, o intervalo entre cada execução do seu Job. É aqui que mora o X (xis) da questão! É neste parametro que vamos informar de quanto em quando tempo nosso Job vai rodar.

O que tem que ser considerado aqui, é que o Job será executado automaticamente (essa é a razão do seu existir) e é justamente por isso que rola a confusão, quando este parâmetro for usado já não estaremos mais na data “agora”, estaremos na data de execução do Job, sei lá, 23:00! E aí o banco vai usar este parâmetro INTERVAL para setar o campo NEXT_DATE, que é a próxima data em que o Job será executado, ou seja você tem que levar em consideração que o banco sempre vai usar sysdate para calcular este valor.

Como é de rotina, vamos para os exemplos que tudo vai ficar mais claro.
Exemplos mais comuns:

Job para rodar de hora em hora:
Interval -> ’sysdate + 1/24′
Ou seja, se este Job rodar dia 25/10/2009 às 14:00, quando for somada 1 hora, teremos 15:00 como NEXT_DATE.

Job para rodar a cada 5 minutos.
Interval -> ’sysdate + 5/1440′
Ou seja, se este Job rodar dia 25/10/2009 às 14:00, quando for somado 5 minutos (1/1440), teremos 14:05 como NEXT_DATE.

Job para rodar uma vez por mês:
Interval -> ‘add_months(sysdate, 1)’
Ou seja, se executar dia 25/10/2009, aplicando este valor acima, teriamos 25/11/2009 como NEXT_DATE.

Esse foi um dos casos mais estranhos, pedido através do blog pra mim…
Job para rodar em um dia específico a cada ano e numa determinada hora:
‘add_months(to_date(to_char(sysdate, ”DD/MM/YYYY”)||” 05:00”, ”DD/MM/YYYY HH24:MI”), 12)’
Ou seja, se o job rodar dia 25/10/2009 as 15:00, e aplicarmos esta fórmula aí, teremos 25/10/2010 05:00 como NEXT_DATE.

Uma dica legal para você fazer esta fórmula que será o NEXT_DATE do seu Job é dar select em sysdate usando a dual. Que eu creio ser o que o banco faz na hora de rodar o Job.

Por exemplo:
Se executarmos o comando:
select sysdate, sysdate + 1/24 from dual
Vamos obter como retorno:

sysdate sysdate + 1/24
20/10/2009 15:55:35 20/10/2009 16:55:35

Isso aí nos dá a hora atual e a hora atual somado 1 hora. Assim você monta seu NEXT_DATE facilmente!

É isso pessoal, espero que tenha ficado claro e que daqui pra frente seja mais fácil montar seus Jobs para as mais diversas necesidades.

Qualquer coisa, estamos por aqui!

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Lomadee, uma nova espécie na web. A maior plataforma de afiliados da América Latina

Privilegios (Grant) no Oracle

Fala PessoAll,

Demorei, mas estamos de volta.

Dessa vez, vou dar uma dica bem simples sobre privilégios (grants) no banco Oracle.

Quem muitas vezes não foi realizar um select em uma tabela qualquer no banco de dados e obteve um ora-00942: table or view does not exist? Pois é, este erro nem sempre é o que diz que é! Que coisa não? Muitas vezes a tabela existe só que pertence a um outro schema do banco de dados, e aí o usuário que voce está conectado não consegue enxergar este objeto. Isso pode acontecer com tabelas, views, functions, procedures, etc o que acontece é que o schema proprietário do objeto tem que conceder a devida permissão para o usuário que você está conectado.

Vamos a um cenário, para que possamos entender esse rolo todo.

Suponhamos que em nossa base a gente tenha o usuário DONOSISTEMA que criou uma tabela chamada TABELA_BASE e você se conecta no banco com o usuário USERSISTEMA, então como faríamos para que você conseguisse acessar esta tabela?

Assim:

Primeiro vamos conectar com DONOSISTEMA e criar a tabela:

SQL> conn donosistema/oracle;
Conectado.
SQL> create table tabela_base(campo1 number, campo2 varchar2(100));

Tabela criada.

Beleza, agora vamos conectar com o usuário USERSISTEMA e tentar dar um select count(*) nesta tabela:

SQL> conn usersistema/oracle;
Conectado.
SQL> select count(*) from donosistema.tabela_base;
select * from donosistema.tabela_base
*
ERRO na linha 1:
ORA-00942: a tabela ou view nÒo existe

Parece que não deu muito certo não? Pois é, não tem privilégio.
Agora vamos conectar novamente como DONOSISTEMA e conceder o privilégio:

SQL> conn donosistema/oracle;
Conectado.
SQL> grant select on tabela_base to usersistema;

ConcessÒo bem-sucedida.

Perfeito… agora vamos conectar novamente com o usuário USERSISTEMA e tentar novamente fazer o select count(*) nessa tabela:

SQL> conn usersistema/oracle;
Conectado.

SQL> select count(*) from donosistema.tabela_base;

COUNT(*)
----------
0

Agora parece que ficou beleza não? Nosso usuário conseguiu realizar acessar a tabela sem problemas.

Só que… eu sou um cara chato! Não quero ter que colocar nome do dono do objeto na frente (DONOSISTEMA.)… na verdade não quero nem que meu usuário que vai acessar a aplicação saiba quem é o dono dos objetos, pra ele não cair em tentação! Rsrs. Para isso, precisamos criar um objeto chamado SYNONYM que nada mais é que um sinônimo (óbvio não) para o objeto original. Por exemplo, no nosso caso, temos que criar um synonym com o nome TABELA_BASE que aponte para o objeto DONOSISTEMA.TABELA_BASE certo?

Então vamos lá.

Pra não dizerem que estou mentindo (rsrs) inicialmente vou conectar como USERSISTEMA para que possamos ver que se tirar o nome do dono do objeto da frente da tabela o select não vai funcionar, vamos ver:


SQL> conn usersistema/oracle;
Conectado.

SQL> select count(*) from tabela_base;
select count(*) from tabela_base
*
ERRO na linha 1:
ORA-00942: a tabela ou view nÒo existe

Hum… realmente não funciona.

Agora vamos conectar como DONOSISTEMA e criar o synonym para esta tabela ok? vamos lá:


SQL> conn donosistema/oracle;
Conectado.
SQL> create public synonym tabela_base for donosistema.tabela_base;

Sin¶nimo criado.

Beleza. Agora vamos conectar novamente como USERSISTEMA e ver se ele consegue acessar sem o nome do dono na frente? Vamos:


SQL> conn usersistema/oracle;
Conectado.
SQL> select count(*) from tabela_base;

COUNT(*)
----------
0

Perfeito não? Que beleza!! É assim que fazemos para que tenhamos um usuário dono dos objetos do nosso banco de dados e vários outros usuários que apenas utilizam estes objetos. Desta forma organizamos nossos objetos e garantimos que fica transparente aos usuários seu acesso.

E como eu sei se tenho permissão ou não para um determinado objeto?
Simples, consultando o dicionário dados. Tentem rodar o select abaixo:


select grantor, grantee, table_name, privilege
from all_tab_privs
where grantee = 'USUARIO_RECEBEDOR_PRIVILEGIO'
and grantor = 'USUARIO_DONO_OBJETO'
and table_name = 'NOME_DO_OBJETO'

Aí vocês podem usar ou não todos os filtros que coloquei.
Aí podemos filtrar por:
GRANTOR: que é o usuário que concedeu a permissão. No nosso caso DONOSISTEMA.

GRANTEE: que é o usuário que recebeu a permissão. No nosso caso USERSISTEMA.

TABLE_NAME: que é o nome da tabela envolvida no nosso processo. No nosso caso TABLE_BASE.

É isso gente.
Espero que tenham gostado e que daqui pra frente fique tudo mais claro sobre permissões, sinônimos e etc.

Atc.
Gerson Júnior
(gerson.vasconcelos@gmail.com)