<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dia a dia Oracle &#187; pl/sql</title>
	<atom:link href="http://www.diaadiaoracle.com.br/category/plsql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.diaadiaoracle.com.br</link>
	<description></description>
	<lastBuildDate>Mon, 01 Aug 2011 22:36:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Oracle Tuning &#8211; Exportando Estatísticas de Tabelas</title>
		<link>http://www.diaadiaoracle.com.br/2011/08/01/oracle-tuning-exportando-estatisticas-de-tabelas/</link>
		<comments>http://www.diaadiaoracle.com.br/2011/08/01/oracle-tuning-exportando-estatisticas-de-tabelas/#comments</comments>
		<pubDate>Mon, 01 Aug 2011 22:36:23 +0000</pubDate>
		<dc:creator>oracle</dc:creator>
				<category><![CDATA[banco de dados]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[dicas]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[procedures]]></category>
		<category><![CDATA[query]]></category>

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=98</guid>
		<description><![CDATA[Fala PessoAll, Depois de muito tempo sem postar, estou eu aqui de novo para falar de mais um recurso usado no nosso Diaadia. Desta vez o problema foi o seguinte: Temos uma base de produção 9i que está em plena fase de migração para 11g, claro que para que esta migração aconteça, temos que ter [...]]]></description>
			<content:encoded><![CDATA[<p>Fala PessoAll,</p>
<p>Depois de muito tempo sem postar, estou eu aqui de novo para falar de mais um recurso usado no nosso Diaadia.</p>
<p>Desta vez o problema foi o seguinte:</p>
<p>Temos uma base de produção 9i que está em plena fase de migração para 11g, claro que para que esta migração aconteça, temos que ter a homologação de vários sistemas em 11g, que atualmente rodam na nossa base de produção 9i. Em uma das homologações deste sistema, o analista nos acionou informando que um processo que rodava na base 9i em 10 minutos, já estava a mais de 1 hora rodando na base 11g, sem sucesso.</p>
<p>Vamos as análises&#8230;</p>
<p>Passo 1: Identificar que comando estava causando nosso problema, para isso solicitei ao analista rodar a rotina dele habilitando um trace, para tentarmos identificar. Foi solicitado adicionar os seguintes comandos na execução:</p>
<p><code>begin<br />
   --Habilita geracao do trace.<br />
   execute immediate('alter session set tracefile_identifier=''TRACE_PROC_LENTA''');<br />
   sys.dbms_support.start_trace(true, true);<br />
   -- Call the procedure<br />
   PROCEDURE_DO_ANALISTA_LENTA;<br />
   --Finaliza geracao do trace.<br />
   sys.DBMS_SUPPORT.STOP_TRACE;<br />
end;<br />
/</code></p>
<p>Após concluído o processo, temos que procurar na nossa pasta UDUMP o trace que foi gerado com o identificador &#8220;_TRACE_PROC_LENTA&#8221;.</p>
<p>Analisando o trace&#8230;<br />
<code><br />
call     count       cpu    elapsed       disk      query    current        rows<br />
------- ------  -------- ---------- ---------- ---------- ----------  ----------<br />
Parse      791      0.02       1.25          0          3          0           0<br />
Execute  72124      9.77     127.63        365       3759      75246        7469<br />
Fetch    81349    109.26    2466.37     229643   14999926          0       75146<br />
------- ------  -------- ---------- ---------- ---------- ----------  ----------<br />
total   154264    119.05    2595.27     230008   15003688      75246       82615<br />
</code></p>
<p>Identificamos que o processo rodou em 2595.27 segundos, total!</p>
<p>E temos um comando único, que rodou em 2289.73 segundos. Ficou claro que este é o culpado não??</p>
<p><code><br />
select COL1, COL2, COL3 from MINHA_TABELA</p>
<p>call     count       cpu    elapsed       disk      query    current        rows<br />
------- ------  -------- ---------- ---------- ---------- ----------  ----------<br />
Parse        1      0.00       0.00          0          0          0           0<br />
Execute   5430      1.11       3.54          0          0          0           0<br />
Fetch     5430    106.61    2286.19     222786   14703253          0        3431<br />
------- ------  -------- ---------- ---------- ---------- ----------  ----------<br />
total    10861    107.72    2289.73     222786   14703253          0        3431</p>
<p>Misses in library cache during parse: 0<br />
Optimizer mode: ALL_ROWS<br />
Parsing user id: 214  (OWNER)   (recursive depth: 1)</p>
<p>Rows     Row Source Operation<br />
-------  ---------------------------------------------------<br />
      1  TABLE ACCESS BY INDEX ROWID MINHA_TABELA (cr=7 pr=0 pw=0 time=68 us cost=5 size=33 card=1)<br />
     13   INDEX RANGE SCAN MINHA_TABELA_IDX2 (cr=4 pr=0 pw=0 time=40 us cost=4 size=0 card=1)(object id 32870)<br />
</code></p>
<p>Como podemos ver, este select está sendo executado utilizando um índice, o MINHA_TABELA_IDX2. Ótimo, agora vamos comparar este plano de execução, com o plano de execução que temos em produção. Eis o plano de produção: </p>
<p><code><br />
Rows     Row Source Operation<br />
-------  ---------------------------------------------------<br />
      1  TABLE ACCESS BY INDEX ROWID MINHA_TABELA (cr=7 pr=0 pw=0 time=68 us cost=5 size=33 card=1)<br />
     13   INDEX RANGE SCAN MINHA_TABELA_PK (cr=4 pr=0 pw=0 time=40 us cost=4 size=0 card=1)<br />
</code></p>
<p>Opa&#8230;. qual a diferença? Nesta base a minha query acessa os dados pela PK, e não pelo índice! Matamos a parada!!! </p>
<p>Como resolver?</p>
<p>A base onde a homologação estava sendo feita era uma base 11g criada com uma cópia antiga de produção, que não vinha sendo coletada estatística, que estava sendo constantemente alterada pelos testes e que não estava 100%. Para coletar estatísticas novamente desta tabela, seria mais complicado e demorado, pois a tabela tem 667.000.000 de linhas, claro, o teste tem que ser agora!!!!</p>
<p>Lembramos então que tinhamos uma cópia fresquinha da base de produção, que tinha sido recém migrada para 11g, ou seja, estava em 11g, mas tinha as estatísticas certinhas de produção, onde a query estava rápida.</p>
<p>A solução encontrada foi: <b>Exportar as estatísticas desta tabela</b>.</p>
<p>Então, vamos lá&#8230;</p>
<p>Passo 1: Criar uma tabela de estatísticas na base origem, para receber as estatísticas atuais da tabela:</p>
<p><code><br />
SQL> exec SYS.DBMS_STATS.CREATE_STAT_TABLE(ownname => 'DBAGABOS', stattab => 'TLISTENER_STATS');<br />
Procedimento PL/SQL concluÝdo com sucesso.<br />
SQL><br />
</code></p>
<p>Passo 2: Exportar as estatísticas atuais da tabela na base de origem, para a tabela de esatísticas que você criou:</p>
<p><code><br />
SQL> exec DBMS_STATS.EXPORT_TABLE_STATS(ownname => 'DBAGABOS', tabname => 'TLISTENER', stattab => 'TLISTENER_STATS', cascade => true);<br />
Procedimento PL/SQL concluÝdo com sucesso.<br />
SQL><br />
</code></p>
<p>Passo 3: Exportar esta tabela gerada&#8230;</p>
<p><code><br />
C:\Users\GersonJr>exp dbagabos@orcl tables=TLISTENER_STATS file=dump_stats.dmp<br />
Export: Release 10.2.0.3.0 - Production on Seg Ago 1 19:23:58 2011<br />
Copyright (c) 1982, 2005, Oracle.  All rights reserved.<br />
Senha:<br />
Conectado a: Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production<br />
With the Partitioning, OLAP and Data Mining options<br />
ExportaþÒo executada no conjunto de caracteres de WE8MSWIN1252  e no conjunto de caracteres de AL16UTF16 NCHAR<br />
Sobre exportar tabelas especificadas ... via Caminho Convencional ...<br />
. . exportando tabela                TLISTENER_STATS          113 linhas exportadas<br />
ExportaþÒo encerrada com sucesso, sem advertÛncias.<br />
C:\Users\GersonJr><br />
</code></p>
<p>Passo 4: Importar a tabela de estatísticas que você exportou, no banco de destino&#8230;</p>
<p><code><br />
C:\Users\GersonJr>imp dbagabos@orcl_destino tables=TLISTENER_STATS file=dump_stats.dmp<br />
Import: Release 10.2.0.3.0 - Production on Seg Ago 1 19:24:58 2011<br />
Copyright (c) 1982, 2005, Oracle.  All rights reserved.<br />
Senha:<br />
Conectado a: Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production<br />
With the Partitioning, OLAP and Data Mining options<br />
Arquivo de exportaþÒo criado por EXPORT:V10.02.01 via caminho convencional<br />
AdvertÛncia: os objetos foram exportados por DBAGABOS; nÒo por vocÛ<br />
importaþÒo realizada nos conjuntos de caracteres WE8MSWIN1252 e NCHAR AL16UTF16<br />
. importando objetos de DBAGABOS para DBAGABOS<br />
. importando objetos de DBAGABOS para DBAGABOS<br />
. . importando table              "TLISTENER_STATS"          113 linhas importadas<br />
ImportaþÒo encerrada com sucesso, sem advertÛncias.<br />
C:\Users\GersonJr><br />
</code></p>
<p>Passo 5: Importar as estatísticas para a tabela, lendo da tabela de estatísticas que você importou.<br />
<code><br />
exec DBMS_STATS.IMPORT_TABLE_STATS(ownname => 'DBAGABOS', tabname => ‘TLISTENER’, stattab => ‘TLISTENER_STATS’, cascade => true, no_invalidate => true);<br />
</code></p>
<p>E agora é só você testar seu plano de execução e verificar se na base nova a query está se comportando da mesma forma que na base antiga.</p>
<p>Algumas considerações:<br />
1 &#8211; O problema ocorreu na base 11g, porém para criar o post refiz os comandos na base instalada no meu PC, que é 10.2.0.3, como podem ver nos comandos acima.</p>
<p>2 &#8211; Estes passos não querem dizer que há uma garantia 100% da sua query ficar igual a sua base de origem, lembre-se que em performance existem inúmeros outros pontos que são verificados para o banco montar um plano de execução.</p>
<p>3 &#8211; A idéia deste post é mostrar este recurso de export/import de estatísticas, que é simples e rápido de fazer, e pode ajudar-nos em vários casos.</p>
<p>Qualquer coisa, estou à disposição para dúvidas e/ou sugestões!</p>
<p>Grande abraço.</p>
<p>Atc.<br />
Gerson Júnior<br />
gerson.vasconcelos@gmail.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2011/08/01/oracle-tuning-exportando-estatisticas-de-tabelas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Alternativa InitCap. Upper e Lower no lugar certo.</title>
		<link>http://www.diaadiaoracle.com.br/2010/09/22/alternativa-initcap-upper-e-lower-no-lugar-certo/</link>
		<comments>http://www.diaadiaoracle.com.br/2010/09/22/alternativa-initcap-upper-e-lower-no-lugar-certo/#comments</comments>
		<pubDate>Wed, 22 Sep 2010 19:40:53 +0000</pubDate>
		<dc:creator>oracle</dc:creator>
				<category><![CDATA[banco de dados]]></category>
		<category><![CDATA[desenvolvimento]]></category>
		<category><![CDATA[dicas]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[functions]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[initcap]]></category>
		<category><![CDATA[lower]]></category>
		<category><![CDATA[lowercase]]></category>
		<category><![CDATA[maiuscula]]></category>
		<category><![CDATA[minuscula]]></category>
		<category><![CDATA[upper]]></category>
		<category><![CDATA[uppercase]]></category>

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=88</guid>
		<description><![CDATA[Fala PessoALL, Hoje falaremos de manipulação/formatação de strings, com o uso da boa e velha função InitCap do Oracle. Acho que muitos de nós já nos deparamos com este tipo de problema, temos no nosso banco, uma determinada descrição gravada da forma que o usuário achar mais bonito! Ou seja, sem ter um padrão para [...]]]></description>
			<content:encoded><![CDATA[<p>Fala PessoALL,</p>
<p>Hoje falaremos de manipulação/formatação de strings, com o uso da boa e velha função <b><code>InitCap</code></b> do <b>Oracle</b>.<br />
Acho que muitos de nós já nos deparamos com este tipo de problema, temos no nosso banco, uma determinada descrição gravada da forma que o usuário achar mais bonito! Ou seja, sem ter um padrão para gravação. Para gravar a frase: &#8220;Este blog é uma beleza&#8221;, por exemplo, podemos ter de várias formas:</p>
<p>- Este blog é uma beleza<br />
- ESTE BLOG É UMA BELEZA<br />
- EsTe BlOg É uMa BeLeZa (vai que o usuário é internetês)</p>
<p>Entre muitas outras formas. Porém na hora de fazermos um relatório, gostaríamos muitas vezes que nosso relatório mantenha um padrão de exibição da descrição, fica no mínimo estranho que tenhamos uma frase maíuscula, outra minúscula, outra mesclada, etc&#8230; para isso o <b>Oracle</b> nos dá uma função chamada <b><code>InitCap</code></b>.</p>
<p>Esta função nos dá a possibilidade de padronizar a nossa descrição, ela coloca maiúscula todas as primeiras letras das palavras da frase, por exemplo:</p>
<p>- Este Blog É Uma Beleza</p>
<p>Só que este ainda não é o padrão que utilizamos para escrever, apenas as primeiras letras da primeira palavra da frase é que são maiúsculas. Todas as demais são minúsculas, ficando a frase assim:</p>
<p>-Este blog é uma beleza</p>
<p>Bem mais bonito não??</p>
<p>Pensando nesse problema, vamos deixar de blábláblá e vamos a prática! </p>
<p>Eu desenvolvi uma função, a pedido do meu amigo Marcos Castro, que faz exatamente isso que queremos, ela só coloca maíuscula a primeira letra da primeira palavra de uma nova frase, ou seja, o que vem depois do ponto, como costumamos fazer no nosso dia-a-dia, como mostrado no exemplo acima.</p>
<p>Segue a função:</p>
<p><code><br />
create or replace function initcapmc(p_str varchar2) return varchar2 is<br />
   v_carac_anterior varchar2(1);<br />
   v_carac_atual    varchar2(1);<br />
   v_retorno        varchar2(32767);<br />
begin<br />
   --Atribui o primeiro caractere como maiúsculo.<br />
   v_retorno := upper(substr(p_str,1,1));</p>
<p>   --Varre a string a partir da segunda posição<br />
   for i in 2..length(p_str) loop<br />
      --Recupera o caractere que está sendo analisado<br />
      v_carac_atual := substr(p_str,i,1);</p>
<p>      --Se o caractere analisado anteriormente foi um ponto, vai colocar maiúsculo<br />
      if(v_carac_anterior = '.') then<br />
         v_retorno := v_retorno || upper(v_carac_atual);<br />
      else<br />
         v_retorno := v_retorno || lower(v_carac_atual);<br />
      end if;</p>
<p>      --Atribui o caractere já processado como sendo o anterior, para a proxima execucao. Ignora espaco.<br />
      if(trim(v_carac_atual) is not null) then<br />
         v_carac_anterior := v_carac_atual;<br />
      end if;<br />
   end loop;</p>
<p>   return v_retorno;</p>
<p>end; </p>
<p></code></p>
<p>Espero que gostem&#8230; em caso de bugs, favor informar.</p>
<p>Atc.<br />
Gerson Júnior<br />
(gerson.vasconcelos@gmail.com)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2010/09/22/alternativa-initcap-upper-e-lower-no-lugar-certo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Função de grupo para multiplicar, SUM -&gt; MULT</title>
		<link>http://www.diaadiaoracle.com.br/2010/04/08/funcao-de-grupo-para-multiplicar-sum-mult/</link>
		<comments>http://www.diaadiaoracle.com.br/2010/04/08/funcao-de-grupo-para-multiplicar-sum-mult/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 17:33:36 +0000</pubDate>
		<dc:creator>oracle</dc:creator>
				<category><![CDATA[aula oracle]]></category>
		<category><![CDATA[banco de dados]]></category>
		<category><![CDATA[desenvolvimento]]></category>
		<category><![CDATA[dicas]]></category>
		<category><![CDATA[dinamico]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[functions]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[functions group]]></category>
		<category><![CDATA[group by]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[select]]></category>
		<category><![CDATA[sum]]></category>

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=78</guid>
		<description><![CDATA[Fala pessoal, Recebi um email de um leitor solicitando uma solução para que fosse desenvolvida uma função semelhante ao SUM, já nativo do banco de dados Oracle, só que fizesse multiplicação e não soma, como o SUM faz atualmente! Por exemplo: Tabela: FATORIAL Campo: VALOR Valor 5 6 3 2 3 Portanto, se usarmos o [...]]]></description>
			<content:encoded><![CDATA[<p>Fala pessoal,</p>
<p>Recebi um email de um leitor solicitando uma solução para que fosse desenvolvida uma função semelhante ao SUM, já nativo do banco de dados Oracle, só que fizesse multiplicação e não soma, como o SUM faz atualmente!</p>
<p>Por exemplo:</p>
<p>Tabela: FATORIAL<br />
Campo: VALOR</p>
<p>Valor<br />
     5<br />
     6<br />
     3<br />
     2<br />
     3</p>
<p>Portanto, se usarmos o SUM, teriamos um resultado assim: 5 + 6 + 3 + 2 + 3 = 19<br />
O pretendido é: 5 * 6 * 3 * 2 * 3 = 540</p>
<p>A sugestão que dei foi: Criar uma função própria que faça a multiplicação dos valores. A implementação/testes ficou assim:</p>
<p><code><br />
SQL> --Cria tabela<br />
SQL> create table fatorial(campo1 number, valor number);<br />
Tabela criada.<br />
SQL> --Insere valores<br />
SQL> insert into fatorial values (1,2);<br />
1 linha criada.<br />
SQL> insert into fatorial values (1,3);<br />
1 linha criada.<br />
SQL> insert into fatorial values (2,4);<br />
1 linha criada.<br />
SQL> insert into fatorial values (2,4);<br />
1 linha criada.<br />
SQL><br />
</code></p>
<p>Em seguida criamos a seguinte function:</p>
<p><code><br />
SQL> create or replace function mult_vals(p_filtro number) return number is<br />
  2     v_retorno number;<br />
  3  begin<br />
  4     v_retorno := 0;<br />
  5     for i in (select valor from fatorial where campo1 = p_filtro)<br />
  6     loop<br />
  7        if (v_retorno = 0) then<br />
  8           v_retorno := 1;<br />
  9        end if;<br />
 10        v_retorno := v_retorno*i.valor;<br />
 11     end loop;<br />
 12     return v_retorno;<br />
 13  end;<br />
 14  /<br />
FunþÒo criada.<br />
SQL><br />
</code></p>
<p>E depois é só testar:</p>
<p><code><br />
SQL> select campo1, mult_vals(campo1)<br />
  2    from fatorial<br />
  3   group by campo1;<br />
    CAMPO1 MULT_VALS(CAMPO1)<br />
---------- -----------------<br />
         1                 6<br />
         2                16<br />
SQL><br />
</code></p>
<p>Funcionou como uma luva não?</p>
<p>É isso, o que não tem nativo a gente faz!<br />
Neste caso fiz algo bem específico, só pra atender a necessidade que nosso leitor precisava, mas podemos pensar em algo mais genérico, se necessário! Usando SQL Dinâmico, passando nome do campo a ser multiplicado e nome da tabela! Fica a sugestão!</p>
<p>Agradecendo ao nosso leitor Rodrigo Vieira pela solicitação!!</p>
<p>Grande abraço, espero que gostem.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2010/04/08/funcao-de-grupo-para-multiplicar-sum-mult/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dica: Como descobrir quem referencia uma coluna?</title>
		<link>http://www.diaadiaoracle.com.br/2010/02/11/dica-como-descobrir-quem-referencia-uma-coluna/</link>
		<comments>http://www.diaadiaoracle.com.br/2010/02/11/dica-como-descobrir-quem-referencia-uma-coluna/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 14:46:26 +0000</pubDate>
		<dc:creator>oracle</dc:creator>
				<category><![CDATA[banco de dados]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[desenvolvimento]]></category>
		<category><![CDATA[dicas]]></category>
		<category><![CDATA[distinct]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[select]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[dictionary]]></category>
		<category><![CDATA[foreign key]]></category>

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=72</guid>
		<description><![CDATA[Fala PessoAll, A dica de hoje é a respeito do seguinte&#8230; Muitas vezes temos a necessidade de fazer algumas alterações nas nossas tabelas, nosso modelo, etc. E aí precisamos levantar quais tabelas recerenciam uma determinada tabela ou coluna, quais as filhas dessas colunas, quais as foreign key que fazem referência a elas e etc. Aí, [...]]]></description>
			<content:encoded><![CDATA[<p>Fala PessoAll,</p>
<p>A dica de hoje é a respeito do seguinte&#8230;</p>
<p>Muitas vezes temos a necessidade de fazer algumas alterações nas nossas tabelas, nosso modelo, etc. E aí precisamos levantar quais tabelas recerenciam uma determinada tabela ou coluna, quais as filhas dessas colunas, quais as <b>foreign key</b> que fazem referência a elas e etc.</p>
<p>Aí, podemos usar o seguinte <b>select</b>:</p>
<p><code><br />
select distinct c.table_name<br />
  from dba_constraints  c,<br />
       dba_cons_columns cc<br />
 where c.constraint_type = 'R'<br />
   and cc.owner           = c.owner<br />
   and cc.constraint_name = c.r_constraint_name<br />
   and cc.owner           = &#038;SCHEMA<br />
   and cc.table_name      = &#038;TABELA<br />
   and cc.column_name     = &#038;COLUNA<br />
</code></p>
<p>Claro que temos que mudar os parâmetros &#038;SCHEMA, &#038;TABELA e &#038;COLUNA, para recuperar as tabelas que são filhas da tabela que você deseja.</p>
<p>Exemplo fica melhor não? Vamos lá:</p>
<p>Eu preciso descobrir quais as tabelas que fazem referência a alguma coluna da tabela <code>SOURCE</code>, para tal fazemos o seguinte <b>select</b>:</p>
<p><code><br />
SQL> select DISTINCT C.TABLE_NAME<br />
  2    from dba_constraints  c,<br />
  3         dba_cons_columns cc<br />
  4   where c.constraint_type = 'R'<br />
  5     and cc.owner           = c.owner<br />
  6     and cc.constraint_name = c.r_constraint_name<br />
  7     and cc.owner           = 'ORABUGIT'<br />
  8     and cc.table_name      = 'SOURCES'<br />
  9  /<br />
TABLE_NAME<br />
------------------------------<br />
PEOPLE_EQUIPS<br />
</code></p>
<p>Como podemos ver, obtemos como resposta a tabela <code>PEOPLE_EQUIPS</code>, portanto podemos ver que nesta tabela tem alguma coluna que referencia através de <b>foreign key</b> uma coluna da tabela <code>SOURCE</code>.</p>
<p>Espero que a dica seja útil!!</p>
<p>Abraços.</p>
<p>Atc.<br />
Gerson Júnior<br />
gerson.vasconcelos@gmail.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2010/02/11/dica-como-descobrir-quem-referencia-uma-coluna/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Potência / Expoentes em SQL e PL/SQL &#8211; Oracle</title>
		<link>http://www.diaadiaoracle.com.br/2010/02/08/potencia-expoentes-em-sql-e-plsql-oracle/</link>
		<comments>http://www.diaadiaoracle.com.br/2010/02/08/potencia-expoentes-em-sql-e-plsql-oracle/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 17:08:32 +0000</pubDate>
		<dc:creator>oracle</dc:creator>
				<category><![CDATA[banco de dados]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[desenvolvimento]]></category>
		<category><![CDATA[dicas]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[functions]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[oracle 10g]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[dica sql]]></category>
		<category><![CDATA[expoente]]></category>
		<category><![CDATA[potencia]]></category>

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=69</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>Fala Pessoal,</p>
<p>Hoje vai mais uma dica  de SQL e PL/SQL.</p>
<p>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. </p>
<p>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 <b>POWER</b>, isso mesmo, funciona assim:</p>
<p>Exemplo SQL:<br />
<code><br />
SQL> select power(2,3) from dual;<br />
POWER(2,3)<br />
----------<br />
         8<br />
</code><br />
Neste exemplo, temos 2 elevado a 3, que nos dá 8 como resultado&#8230;</p>
<p>Exemplo PL/SQL:<br />
<code><br />
SQL> declare<br />
  2     v_num number;<br />
  3  begin<br />
  4     v_num := power(2,3);<br />
  5     dbms_output.put_line('O numero 2 elevado a 3 é: '||to_char(v_num));<br />
  6  end;<br />
  7  /<br />
O numero 2 elevado a 3 é: 8<br />
Procedimento PL/SQL concluÝdo com sucesso.<br />
</code></p>
<p>Pronto pessoal, fica aí a dica de utilização de potência em PL/SQL.</p>
<p>Espero que gostem.</p>
<p>Grande abraço.</p>
<p>Atc.<br />
Gerson Júnior<br />
gerson.vasconcelos@gmail.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2010/02/08/potencia-expoentes-em-sql-e-plsql-oracle/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Dica de SQL &#8211; Primeiro sábado do mês seguinte</title>
		<link>http://www.diaadiaoracle.com.br/2010/02/01/dica-de-sql-primeiro-sabado-do-mes-seguinte/</link>
		<comments>http://www.diaadiaoracle.com.br/2010/02/01/dica-de-sql-primeiro-sabado-do-mes-seguinte/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 17:21:14 +0000</pubDate>
		<dc:creator>oracle</dc:creator>
				<category><![CDATA[automatizar tarefas.]]></category>
		<category><![CDATA[banco de dados]]></category>
		<category><![CDATA[desenvolvimento]]></category>
		<category><![CDATA[dicas]]></category>
		<category><![CDATA[job]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[dica sql]]></category>
		<category><![CDATA[recupera primeiro sabado]]></category>

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=65</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>Fala PessoAll,</p>
<p>Recebi um email do amigo Vitor Ugo sobre uma solicitação que ele havia recebido para criação de um Job. </p>
<p>Até aí moleza, como podemos ver no post: <a href="http://www.diaadiaoracle.com.br/2009/06/10/job-no-oracle/" target="top">Job no Oracle</a> criar um Job é fácil! Só que este Job tem uma particularidade, ele deve rodar apenas no primeiro sábado de cada mês.</p>
<p>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.</p>
<p>Foi então que o Vitor desenvolveu um select, que recupera o primeiro sábado do mês seguinte, e resolveu todos os problemas.</p>
<p>Segue o select desenvolvido por Vitor:</p>
<p><code><br />
select LEAST(NEXT_DAY(ADD_MONTHS(trunc(sysdate,'MM')+(8/24),1)-1,7),<br />
             next_day(ADD_MONTHS(trunc(sysdate,'MM')+(8/24),1),7)) from dual;<br />
</code></p>
<p>Neste select o &#8220;7&#8243; indica que é um sábado, caso desejem outro dia da semana, basta que vocês alterem esse número para o dia desejado!</p>
<p>É isso, fica aí a dica. Espero que gostem</p>
<p>Abraço a todos.</p>
<p>Atc.<br />
Gerson Júnior<br />
gerson.vasconcelos@gmail.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2010/02/01/dica-de-sql-primeiro-sabado-do-mes-seguinte/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Validando Digito Verificador Inscrição Estadual Bahia (BA)</title>
		<link>http://www.diaadiaoracle.com.br/2009/10/22/validando-digito-verificador-inscricao-estadual-bahia-ba/</link>
		<comments>http://www.diaadiaoracle.com.br/2009/10/22/validando-digito-verificador-inscricao-estadual-bahia-ba/#comments</comments>
		<pubDate>Thu, 22 Oct 2009 12:15:26 +0000</pubDate>
		<dc:creator>oracle</dc:creator>
				<category><![CDATA[banco de dados]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[desenvolvimento]]></category>
		<category><![CDATA[dicas]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[functions]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[oracle 10g]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[digito verificador IE]]></category>
		<category><![CDATA[inscricao estadual]]></category>
		<category><![CDATA[validar dig verificador]]></category>

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=39</guid>
		<description><![CDATA[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 &#8220;ninja&#8221; 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 [...]]]></description>
			<content:encoded><![CDATA[<p>Fala PessoAll,</p>
<p>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 &#8220;ninja&#8221; pra resolver alguns problemas do nosso Dia a Dia (Oracle, rsrs).</p>
<p>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á!</p>
<p>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 é: <a href="http://www.sefaz.ba.gov.br/contribuinte/informacoes_fiscais/doc_fiscal/calculodv.htm" target="top">http://www.sefaz.ba.gov.br/contribuinte/informacoes_fiscais/doc_fiscal/calculodv.htm</a>.</p>
<p>Segue abaixo a function utilizada para fazer esta validação. Essa function retorna &#8216;S&#8217; caso esteja OK e &#8216;N&#8217; caso não seja validado o dígito verificador.</p>
<p><code><br />
create or replace function valida_dig_inscest_BA(pInscEstadual varchar2) return varchar2 is<br />
   v_IE varchar2(10);</p>
<p>   idig1 number;<br />
   idig2 number;</p>
<p>   iRes1 number;<br />
   iRes2 number;</p>
<p>   cBase1 number;<br />
   cBase2 number;<br />
begin<br />
   v_IE := rtrim(replace(replace(replace(pInscEstadual, '.', ''), '-', ''), '/', ''));</p>
<p>   if length(v_IE) <> 8 then<br />
      return('N');<br />
   end if;</p>
<p>   iRes1  := 0;<br />
   iRes2  := 0;</p>
<p>   cBase1 := substr(v_IE, 1, 6);<br />
   iDig1  := substr(v_IE, 7, 1);<br />
   iDig2  := substr(v_IE, 8, 1);</p>
<p>   --Se o primeiro dígito for um dos testados, modulo 10, senao, modulo 11<br />
   if(substr(cBase1, 1, 1) in (0, 1, 2, 3, 4, 5, 8)) then<br />
      --Faz um loop de 7 até 2...<br />
      for i in reverse 2 .. 7 loop<br />
         --Verifica se o numero encontrado é válido.<br />
         if instr('0123456789', SubStr(cBase1, (7-i)+1, 1)) > 0 Then<br />
            --Sendo válido, já soma com a multiplicação pelo indice.<br />
            ires2 := ires2 + (SubStr(cBase1, (7-i)+1, 1) * i);<br />
         else<br />
            return('N');<br />
         end if;<br />
      end loop;</p>
<p>      --Recupera o resto do calculo realizado por 10<br />
      ires2 := mod(ires2, 10);</p>
<p>      --Se for 0, o digito é zero.<br />
      if(ires2 = 0) then<br />
         ires2 := 0;<br />
      --Se não for zero, subtrai o valor de 10<br />
      else<br />
         ires2 := 10 - ires2;<br />
      end if;</p>
<p>      --O numero para o calculo do primeiro digito, é os 6 primeiros + o digito 2<br />
      cBase2 := cBase1||ires2;</p>
<p>      --Faz um loop de 8 até 2...<br />
      for i in reverse 2 .. 8 loop<br />
         --Verifica se o numero encontrado é válido.<br />
         if instr('0123456789', SubStr(cBase2, (8-i)+1, 1)) > 0 Then<br />
            --Sendo válido, já soma com a multiplicação pelo indice.<br />
            ires1 := ires1 + (SubStr(cBase2, (8-i)+1, 1) * i);<br />
         else<br />
            return('N');<br />
         end if;<br />
      end loop;</p>
<p>      --Recupera o resto do calculo realizado por 10<br />
      ires1 := mod(ires1, 10);</p>
<p>      --Se for 0, o digito é zero.<br />
      if(ires1 = 0) then<br />
         ires1 := 0;<br />
      --Se não for zero, subtrai o valor de 10<br />
      else<br />
         ires1 := 10 - ires1;<br />
      end if;</p>
<p>      --Se resultado 1 e 2 iguais a digitos 1 e 2, é válido<br />
      if(ires1 = idig1 and ires2 = idig2) then<br />
         return('S');<br />
      else<br />
         return('N');<br />
      end if;<br />
   --Se começa com 6, 7 ou 9<br />
   else<br />
      --Faz um loop de 7 até 2...<br />
      for i in reverse 2 .. 7 loop<br />
         --Verifica se o numero encontrado é válido.<br />
         if instr('0123456789', SubStr(cBase1, (7-i)+1, 1)) > 0 Then<br />
            --Sendo válido, já soma com a multiplicação pelo indice.<br />
            ires2 := ires2 + (SubStr(cBase1, (7-i)+1, 1) * i);<br />
         else<br />
            return('N');<br />
         end if;<br />
      end loop;</p>
<p>      --Recupera o resto do calculo realizado por 11<br />
      ires2 := mod(ires2, 11);</p>
<p>      --Se for 0, o digito é zero.<br />
      if(ires2 = 0) then<br />
         ires2 := 0;<br />
      --Se não for zero, subtrai o valor de 11<br />
      else<br />
         ires2 := 11 - ires2;<br />
      end if;</p>
<p>      --O numero para o calculo do primeiro digito, é os 6 primeiros + o digito 2<br />
      cBase2 := cBase1||ires2;</p>
<p>      --Faz um loop de 8 até 2...<br />
      for i in reverse 2 .. 8 loop<br />
         --Verifica se o numero encontrado é válido.<br />
         if instr('0123456789', SubStr(cBase2, (8-i)+1, 1)) > 0 Then<br />
            --Sendo válido, já soma com a multiplicação pelo indice.<br />
            ires1 := ires1 + (SubStr(cBase2, (8-i)+1, 1) * i);<br />
         else<br />
            return('N');<br />
         end if;<br />
      end loop;</p>
<p>      --Recupera o resto do calculo realizado por 10<br />
      ires1 := mod(ires1, 11);</p>
<p>      --Se for 0, o digito é zero.<br />
      if(ires1 = 0) then<br />
         ires1 := 0;<br />
      --Se não for zero, subtrai o valor de 10<br />
      else<br />
         ires1 := 11 - ires1;<br />
      end if;</p>
<p>      if(ires1 = idig1 and ires2 = idig2) then<br />
         return('S');<br />
      else<br />
         return('N');<br />
      end if;<br />
   end if;<br />
end;<br />
</code></p>
<p>É isso aí gente, espero que seja útil.</p>
<p>Atc.<br />
Gerson Júnior<br />
gerson.vasconcelos@gmail.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2009/10/22/validando-digito-verificador-inscricao-estadual-bahia-ba/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JOB no ORACLE &#8211; Definindo a periodicidade. (INTERVAL)</title>
		<link>http://www.diaadiaoracle.com.br/2009/10/20/job-no-oracle-definindo-a-periodicidade-interval/</link>
		<comments>http://www.diaadiaoracle.com.br/2009/10/20/job-no-oracle-definindo-a-periodicidade-interval/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 19:05:32 +0000</pubDate>
		<dc:creator>oracle</dc:creator>
				<category><![CDATA[automatizar tarefas.]]></category>
		<category><![CDATA[banco de dados]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[desenvolvimento]]></category>
		<category><![CDATA[dicas]]></category>
		<category><![CDATA[job]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[jobs]]></category>

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=36</guid>
		<description><![CDATA[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&#8217;s! Complica não? É nada!! Vamos lá! Espero que todos tenham lido o post que fiz falando sobre Job&#8217;s, caso não tenha lido, ainda dá tempo, basta ler o post Jobs no [...]]]></description>
			<content:encoded><![CDATA[<p>Fala PessoALL,</p>
<p>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&#8217;s! Complica não? É nada!! Vamos lá!</p>
<p>Espero que todos tenham lido o post que fiz falando sobre Job&#8217;s, caso não tenha lido, ainda dá tempo, basta ler o post <a href="http://www.diaadiaoracle.com.br/2009/06/10/job-no-oracle/" target="top">Jobs no Oracle</a>.</p>
<p>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á!</p>
<p>Todo mundo lembra no post anterior que eu falei que para criar um Job usamos a package <code>DBMS_JOB</code> e a procedure <code>DBMS_JOB.SUBMIT(...)</code>, certo? Pois é, nesta procedure, um dos parâmetros que é passado é um tal de <code>INTERVAL</code>, 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.</p>
<p>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 &#8220;agora&#8221;, estaremos na data de execução do Job, sei lá, 23:00! E aí o banco vai usar este parâmetro <code>INTERVAL</code> 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.</p>
<p>Como é de rotina, vamos para os exemplos que tudo vai ficar mais claro.<br />
Exemplos mais comuns:</p>
<p>Job para rodar de hora em hora:<br />
Interval -&gt; &#8216;sysdate + 1/24&#8242;<br />
Ou seja, se este Job rodar dia 25/10/2009 às 14:00, quando for somada 1 hora, teremos 15:00 como NEXT_DATE.</p>
<p>Job para rodar a cada 5 minutos.<br />
Interval -&gt; &#8216;sysdate + 5/1440&#8242;<br />
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.</p>
<p>Job para rodar uma vez por mês:<br />
Interval -&gt; &#8216;add_months(sysdate, 1)&#8217;<br />
Ou seja, se executar dia 25/10/2009, aplicando este valor acima, teriamos 25/11/2009 como NEXT_DATE.</p>
<p>Esse foi um dos casos mais estranhos, pedido através do blog pra mim&#8230;<br />
Job para rodar em um dia específico a cada ano e numa determinada hora:<br />
&#8216;add_months(to_date(to_char(sysdate, &#8221;DD/MM/YYYY&#8221;)||&#8221; 05:00&#8221;, &#8221;DD/MM/YYYY HH24:MI&#8221;), 12)&#8217;<br />
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.</p>
<p>Uma dica legal para você fazer esta fórmula que será o NEXT_DATE do seu Job é dar <code>select</code> em <code>sysdate</code> usando a <code>dual</code>. Que eu creio ser o que o banco faz na hora de rodar o Job.</p>
<p>Por exemplo:<br />
Se executarmos o comando:<br />
<code>select sysdate, sysdate + 1/24 from dual</code><br />
Vamos obter como retorno:<br />
<code><br />
sysdate                      sysdate + 1/24<br />
20/10/2009 15:55:35	20/10/2009 16:55:35<br />
</code></p>
<p>Isso aí nos dá a hora atual e a hora atual somado 1 hora. Assim você monta seu NEXT_DATE facilmente!</p>
<p>É isso pessoal, espero que tenha ficado claro e que daqui pra frente seja mais fácil montar seus Jobs para as mais diversas necesidades.</p>
<p>Qualquer coisa, estamos por aqui!</p>
<p>Atc.<br />
Gerson Júnior<br />
gerson.vasconcelos@gmail.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2009/10/20/job-no-oracle-definindo-a-periodicidade-interval/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>SQL Dinâmico gerando arquivo</title>
		<link>http://www.diaadiaoracle.com.br/2009/05/29/sql-dinamico-gerando-arquivo/</link>
		<comments>http://www.diaadiaoracle.com.br/2009/05/29/sql-dinamico-gerando-arquivo/#comments</comments>
		<pubDate>Fri, 29 May 2009 13:28:00 +0000</pubDate>
		<dc:creator>oracle</dc:creator>
				<category><![CDATA[execute_immediate]]></category>
		<category><![CDATA[gerando arquivo no oracle]]></category>
		<category><![CDATA[gerar arquivo]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[sql dinamico]]></category>
		<category><![CDATA[utl_file]]></category>

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=9</guid>
		<description><![CDATA[Fala PessoAll, Bom, no último tópico postado Oracle Execute Immediate SQL Dinâmico eu falei um pouco sobre como montar e executar query&#8217;s dinâmicamente. Ficou bem interessante, mas&#8230; o exemplo que postei era para um único registro, e não é sempre que temos este tipo de caso. Algumas vezes temos que executar consultas que retornam mais [...]]]></description>
			<content:encoded><![CDATA[<p>Fala PessoAll,</p>
<p>Bom, no último tópico postado <a href="http://diaadiaoracle.blogspot.com/2009/04/oracle-execute-immediate-sql-dinamico.html" target="top">Oracle Execute Immediate SQL Dinâmico</a> eu falei um pouco sobre como montar e executar query&#8217;s dinâmicamente. Ficou bem interessante, mas&#8230; o exemplo que postei era para um único registro, e não é sempre que temos este tipo de caso. Algumas vezes temos que executar consultas que retornam mais de um registro, precisamos inserir isso numa tabela, gravar em um log, gerar um arquivo, e outra série de possibilidades.</p>
<p>Se vocês observarem os comentários do tópico anterior, vão ver que tem um comentário de um Anônino perguntando se não tenho um exemplo de SQL Dinâmico e que gere um arquivo. Resposta: Não tenho. Mas isso não quer dizer que não podemos fazer um.</p>
<p>Vamos ao nosso exemplo.</p>
<p><code><br />
declare<br />
type tpNome is REF CURSOR;<br />
cNome tpNome;</code></p>
<p>&#8211;Variáveis para armazenar query e retorno.<br />
v_sql  varchar2(1000);<br />
v_nome varchar2(100);</p>
<p>&#8211;Variáveis para geração do arquivo<br />
v_arq utl_file.file_type;<br />
begin<br />
&#8211;Define a query<br />
v_sql := &#8216;Select nome from pessoas where rownum &lt; 50&#8242;;</p>
<p>&#8211;Abre o arquivo<br />
v_arq := utl_file.fopen(&#8216;DIRECTORY&#8217;, &#8216;FILE_NAME&#8217;, &#8216;W&#8217;);</p>
<p>open cNome for v_sql;<br />
loop<br />
fetch cNome into v_nome;<br />
exit when cNome%notfound;</p>
<p>utl_file.put_line(v_arq, v_nome);<br />
end loop;</p>
<p>&#8211;Fecha o arquivo<br />
utl_file.fclose;<br />
end;</p>
<p>No exemplo acima, estamos lendo os 50 primeiros registros de uma tabela chamada <code>pessoas</code> e gerando um arquivo com o nome destas pessoas. Bastante simples.</p>
<p>O exemplo acima abre uma série de portas, este é o famoso &#8220;fio da meada&#8221; e a partir deste exemplo uma série de coisas podem ser feitas.</p>
<p>Querido amigo Anônimo, espero que isso te ajude, na próxima vez deixa teu email que fica mais fácil de responder pra você.</p>
<p>Grande abraço a todos.</p>
<p>Atc.<br />
Gerson Júnior<br />
(gerson.vasconcelos@gmail.com)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2009/05/29/sql-dinamico-gerando-arquivo/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Oralce PL/SQL &#8211; Funções (Funtions) e Procedures</title>
		<link>http://www.diaadiaoracle.com.br/2009/03/27/oralce-plsql-funcoes-funtions-e-procedures/</link>
		<comments>http://www.diaadiaoracle.com.br/2009/03/27/oralce-plsql-funcoes-funtions-e-procedures/#comments</comments>
		<pubDate>Fri, 27 Mar 2009 20:22:00 +0000</pubDate>
		<dc:creator>oracle</dc:creator>
				<category><![CDATA[functions]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[procedures]]></category>

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=6</guid>
		<description><![CDATA[Fala PessoAll, Bom&#8230; hoje em mais um dia a dia de trabalho, rolou mais uma dúvida sobre o uso de procedures e funções no PL/SQL. Aí fiz a seguinte pergunta: Qual a diferença entre Procedure e Function no PL/SQL? Aí surgiram aquelas velhas respostas decoradas da faculdade: &#8220;Procedure não retorna valor!&#8221;, &#8220;Função retorna valor e [...]]]></description>
			<content:encoded><![CDATA[<p>Fala PessoAll,</p>
<p>Bom&#8230; hoje em mais um dia a dia de trabalho, rolou mais uma dúvida sobre o uso de procedures e funções no PL/SQL. Aí fiz a seguinte pergunta: Qual a diferença entre Procedure e Function no PL/SQL? Aí surgiram aquelas velhas respostas decoradas da faculdade: &#8220;Procedure não retorna valor!&#8221;, &#8220;Função retorna valor e procedure não retorna.&#8221;, entre outras. Vamos lá então:</p>
<p>No Oracle a diferença básica entre uma e outra é que a Function OBRIGATÓRIAMENTE tem que retornar um valor, você pode até criar a função e compilar ela sem um Return, mas na hora que você rodar esta função você vai obter um erro oracle dizendo que: &#8220;Function Retorned withou value&#8221;, ou seja, função não retorna nenhum valor (algo parecido), e não funciona. Porque a diferença básica? Porque procedures no Oracle também podem retornar valores, isso mesmo, basta você criar um parametro do tipo OUT, assim:<br />
<code><br />
create or replace procedure pr_teste(p_t number, p_ret out varchar2) is<br />
begin<br />
if(p_t = 1) then<br />
p_ret := 'É 1';<br />
else<br />
p_ret := 'Não é 1';<br />
end if;<br />
end;<br />
</code><br />
Neste exemplo de código, note que estamos atribuindo ao parâmetro <code>p_ret</code> o valor que será retornado para o local que chamou essa procedure (veremos exemplo desta chamada nos exemplos a seguir).</p>
<p>Ah&#8230; então, se as duas retorna valor, porque eu tenho procedure e function? E porque eu uso uma e não outra ou a outra e não uma?</p>
<p>Vamos aos pontos de cada uma delas:</p>
<p><strong>Nas Funtions:</strong><br />
- Pode ser usada em comandos select, insert etc para ser retornada como uma coluna da query:<br />
<code>select codigo, nome, fn_calculaIdade(codigo) Idade from pessoas;</code> Neste exemplo, fn_calculaIdade recebe o codigo da pessoa como parametro e retorna a idade dela, isso será exibido como uma coluna na query com nome <code>Idade</code></p>
<p>- Pode ser atribuida diretamente a uma variável:<br />
<code><br />
declare<br />
v_idade number;<br />
begin<br />
.<br />
.<br />
v_idade := fn_calculaIdade(codigo);<br />
.<br />
.<br />
end;<br />
</code></p>
<p>Neste exemplo, estamos no meio de um bloco PL/SQL e atribuímos diretamente a uma variável o valor que retornará da função.</p>
<p>E mais algumas coisas sobre função.</p>
<p><strong>Nas Procedures:</strong><br />
- O grande &#8220;plus&#8221; das procedures é: Podem retornar mais de um resultado! Ah&#8230; isso mesmo, essa é a grande vantagem das procedures, existe a possibilidade de ser retornado mais de um retorno (retornar retorno, coisa feia não? você entenderá jájá), coisa que é completamente impossível usando função. Funções só retornam um único resultado.</p>
<p>Complicou? Vamos ao exemplo:</p>
<p>Primeiro vamos criar uma procedure com 3 (isso mesmo 3, três, III, rsrs) parâmetros de retorno:</p>
<p><code><br />
create or replace procedure pr_buscaEndereco(p_codigo_pessoa number, p_rua out varchar2, p_bairro out varchar2, p_cidade out varchar2) is<br />
begin<br />
begin<br />
select rua,<br />
estado,<br />
cidade<br />
into p_rua,<br />
p_bairro,<br />
p_cidade<br />
from pessoas<br />
where codigo = p_codigo_pessoa;<br />
exception<br />
when no_data_found then<br />
p_rua    := 'Rua não encontrada.';<br />
p_bairro := 'Bairro não encontrada.';<br />
p_cidade := 'Cidade não encontrada.';<br />
end;<br />
end;<br />
</code><br />
Note que os parâmetros que serão usados para retorno, tem uma cláusula OUT na frente do tipo, isso que diferencia ele de um parâmetro comum, IN.</p>
<p>Ah&#8230; bom, mas e como é que eu vou usar isso? Assim:<br />
<code><br />
declare<br />
v_pessoa_rua    varchar2(100);<br />
v_pessoa_bairro varchar2(100);<br />
v_pessoa_cidade varchar2(100);<br />
begin<br />
pr_teste(212, v_pessoa_rua, v_pessoa_bairro, v_pessoa_cidade);<br />
dbms_output.put_line('Endereço da pessoa 212: Rua: '||v_pessoa_rua||' Bairro: '||v_pessoa_bairro||' Cidade: '||v_pessoa_cidade);<br />
end;<br />
</code></p>
<p>Neste exemplo, temos três variáveis criadas, estas três variáveis são passadas na chamada da procedure e como estes parâmetros no qual elas são passadas são OUT, irão retornar algum valor, que será o valor da variável após execução da procedure.</p>
<p>É isso aí, portanto, caso você precise de uma função que retorne mais de um valor, não tente criar uma função genérica cheia de IF&#8217;s e chamar ela mais de uma vez fazendo o mesmo select em colunas diferentes, use uma procedure com mais de um parâmetro OUT que isso provavelmente resolverá seus problemas.</p>
<p>Momento DBA: Lembrem que quanto menos funções são chamadas, mais agradável para o banco. A cada função que chamamos o banco vai ter que ver, executar, retornar, isso usa memória, processador e etc. Se no lugar de 10 chamadas para uma função voce usar uma procedure com 10 parametros OUT, é bem menos &#8220;doloroso&#8221; para o banco. Outra coisa que é muito importante e que ocorre muito é usar função para retornar como uma determinada coluna de um comando select&#8230; lembre-se que se está função está na clausula <code>select</code> ela será chamada exatamente a quantidade de vezes de quantos registros existirem. No exemplo da função <code>fn_calculaIdade</code> que citei lá em cima, se tivermos 1.000.000 de registros, esta função será executada 1.000.000 de vezes, se é uma função mais robusta e complexa, imagine pra onde vai a performance da sua query. Além da perda de performance na query, de quebra você ainda perde uma credibilidade com o DBA! Que quando você degradar o banco todo, ele vai ficar bravo com você!!</p>
<p>Grande abraço a todos.</p>
<p>Fiquem a vontade para comentários e/ou e-mails.</p>
<p>Atc.<br />
Gerson Júnior<br />
gerson.vasconcelos@gmail.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2009/03/27/oralce-plsql-funcoes-funtions-e-procedures/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

