<?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>glufke.net &#187; SQL</title>
	<atom:link href="http://glufke.net/tag/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://glufke.net</link>
	<description></description>
	<lastBuildDate>Mon, 16 Apr 2012 19:33:42 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Fazendo Rateio através de Funções Analíticas</title>
		<link>http://glufke.net/2012/04/11/fazendo-rateio-atraves-de-funcoes-analiticas/</link>
		<comments>http://glufke.net/2012/04/11/fazendo-rateio-atraves-de-funcoes-analiticas/#comments</comments>
		<pubDate>Wed, 11 Apr 2012 20:43:50 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Analíticas]]></category>
		<category><![CDATA[Funções]]></category>
		<category><![CDATA[Matemática]]></category>
		<category><![CDATA[Rateio]]></category>
		<category><![CDATA[Utilidade]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=508</guid>
		<description><![CDATA[
			
			
			
			
			
			
			
						
			Neste post, vamos mostrar como utilizar funções analíticas para fazer o rateio de um valor em diversas linhas de uma tabela.
Primeiro, vamos criar a tabela de teste:
CREATE TABLE glufke_teste
(nro_nota  NUMBER, item NUMBER, valor NUMBER);
INSERT INTO glufke_teste VALUES ( 50, 1, 1.45);
INSERT INTO glufke_teste VALUES ( 50, 2, 3.91);
INSERT INTO glufke_teste VALUES ( 50, 3, [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2012%2F04%2F11%2Ffazendo-rateio-atraves-de-funcoes-analiticas%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2012/04/11/fazendo-rateio-atraves-de-funcoes-analiticas/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2012/04/11/fazendo-rateio-atraves-de-funcoes-analiticas/"  data-text="Fazendo Rateio através de Funções Analíticas" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2012/04/11/fazendo-rateio-atraves-de-funcoes-analiticas/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p><a href="http://glufke.net/wp-content/uploads/2012/04/rateio.jpg"><img class="size-full wp-image-533 alignright" title="Rateio" src="http://glufke.net/wp-content/uploads/2012/04/rateio.jpg" alt="" width="89" height="90" /></a>Neste post, vamos mostrar como utilizar <strong>funções analíticas</strong> para fazer o rateio de um valor em diversas linhas de uma tabela.</p>
<p>Primeiro, vamos criar a tabela de teste:</p>
<pre class="brush: sql;">CREATE TABLE glufke_teste
(nro_nota  NUMBER, item NUMBER, valor NUMBER);
INSERT INTO glufke_teste VALUES ( 50, 1, 1.45);
INSERT INTO glufke_teste VALUES ( 50, 2, 3.91);
INSERT INTO glufke_teste VALUES ( 50, 3, 5.04);</pre>
<pre class="brush: plain;">SQL&gt; SELECT * FROM glufke_teste;

  NRO_NOTA       ITEM      VALOR
---------- ---------- ----------
        50          1       1,45
        50          2       3,91
        50          3       5,04

SQL&gt;</pre>
<p>Nosso objetivo é ratear um valor proporcionalmente nessas linhas. Como exemplo prático, vamos distribuir o valor R$ 49,30!<span id="more-508"></span></p>
<div id="ads_336x280"><script type="text/javascript">// <![CDATA[
    google_ad_client = "pub-8964513116661040"; google_alternate_color = "ffffFF"; google_ad_width = 336; google_ad_height = 280; google_ad_format = "336x280_as"; google_ad_type = "text_image"; //2007-09-07: wp_quadrado_gra google_ad_channel = "0247072216"; google_color_border = "FFFFFF"; google_color_bg = "FFFFff"; google_color_link = "4F82CB"; google_color_text = "000000"; google_color_url = "4F82CB";
// ]]&gt;</script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
</script></div>
<p>Sabemos que a soma das 3 linhas é 10,40:</p>
<pre class="brush: plain;">SQL&gt; SELECT SUM(VALOR) FROM GLUFKE_TESTE;

SUM(VALOR)
----------
      10,4

SQL&gt;</pre>
<p>Então, através de uma simples regra de 3, vemos o percentual de cada linha! Ou seja, temos que aplicar o valor de 49,30 conforme esses percentuais!</p>
<pre class="brush: plain;">SQL&gt; SELECT VALOR, VALOR/10.4*100 PERC FROM GLUFKE_TESTE;

     VALOR       PERC
---------- ----------
      1,45 13,9423076
      3,91 37,5961538
      5,04 48,4615384

SQL&gt;</pre>
<p>Com isso, basta colocar o valor 49.30 ali que temos distribuído! Repare que a soma do valor rateado é exatamente os 49,30 ! Ou seja, está distribuído conforme nossa necessidade!</p>
<pre class="brush: plain;">SQL&gt; select valor, valor/10.4* 49.3 vlr_rateado from glufke_teste;

     VALOR VLR_RATEADO
---------- -----------
      1,45 6,873557692
      3,91 18,53490384
      5,04 23,89153846

SQL&gt;</pre>
<h3>Usando funções analíticas pra obter esse resultado!</h3>
<p>Agora, usando a função analitica SUM, pra buscar &#8220;em tempo de execução&#8221; a soma da coluna valor (abaixo, a coluna TOTAL), e fazer o cálculo todo numa única tacada!</p>
<pre class="brush: sql;">SELECT
  nro_nota
, item
, valor
, sum(valor) over (order by nro_nota) total
, valor / sum(valor) over (order by nro_nota) * 49.3 vlr_rateado
FROM GLUFKE_teste
WHERE nro_nota = 50
/</pre>
<pre class="brush: plain;">  NRO_NOTA       ITEM      VALOR      TOTAL VLR_RATEADO
---------- ---------- ---------- ---------- -----------
        50          1       1,45       10,4 6,873557692
        50          2       3,91       10,4 18,53490384
        50          3       5,04       10,4 23,89153846

SQL></pre>
<p>Vamos adicionar mais um campo chamado VLR_RATEADO, que arredonda pra 2 casas decimais o valor:</p>
<pre class="brush: sql;">SELECT
  nro_nota
, item
, valor
, sum(valor) over (order by nro_nota) total
, valor / sum(valor) over (order by nro_nota) * 50 vlr_rateado
, ROUND(   valor / sum(valor) over (order by nro_nota) * 49.3 ,2 ) vlr_arr
FROM glufke_teste
WHERE nro_nota = 50
/</pre>
<pre class="brush: plain;">  NRO_NOTA       ITEM      VALOR      TOTAL VLR_RATEADO VLR_ARR
---------- ---------- ---------- ---------- ----------- -----------
        50          1       1,45       10,4 6,971153846        6,87
        50          2       3,91       10,4 18,79807692       18,53
        50          3       5,04       10,4 24,23076923       23,89

SQL&gt;</pre>
<p><strong>PROBLEMA A VISTA!</strong><br />
Quando fazemos rateios e arredondamos o valor, a chance de dar uma diferença de 1 centavo ou mais é muito grande! Se somarmos o valor rateado <em>não fecha com os 49.3</em>!</p>
<p>Veja:   6.87 + 18.53 + 23.89 = 49.29 !!! (diferença de 1 centavo!)</p>
<h3>Resolvendo problema do centavo</h3>
<p>Vamos usar funções analíticas pra jogar essa diferença de 1 centavo para uma das linhas da nota! (no caso, vamos jogar para a linha de maior valor).</p>
<p>Primeiro, vamos descobrir se realmente existe uma diferença de 1 centavo ou mais:</p>
<pre class="brush: sql;">
SELECT
  VLR_RATEADO
, ROUND(VLR_RATEADO,2)                        VLR_ARR
, COUNT(1) OVER (ORDER BY 1)                  QTD_LIN
, ROW_NUMBER()    OVER (ORDER BY VLR_RATEADO) LIN
, SUM(VLR_RATEADO) OVER (ORDER BY 1)          SOMA
, SUM(ROUND(VLR_RATEADO,2)) OVER (ORDER BY 1) SOMA_ARR
FROM
(
 SELECT
   nro_nota
 , item
 , valor
 , valor / SUM(valor) OVER (ORDER BY nro_nota) * 49.3 vlr_rateado
 FROM glufke_teste
 WHERE nro_nota = 50
 )
/</pre>
<pre class="brush: plain;">VLR_RATEADO    VLR_ARR    QTD_LIN        LIN       SOMA   SOMA_ARR
----------- ---------- ---------- ---------- ---------- ----------
6,873557692       6,87          3          1       49,3      49,29
18,53490384      18,53          3          2       49,3      49,29
23,89153846      23,89          3          3       49,3      49,29

SQL></pre>
<p>Acima, as colunas QTD_LIN e LIN vão nos ser úteis pra aplicar a diferença apenas na última linha, ou seja, quando QTD_LIN = LIN  (no caso 3=3).<br />
A coluna SOMA, contém o valor total.<br />
A coluna SOMA_ARR é a soma do valor arredondado! Repare que tem 1 centavo a menos!</p>
<p>Então, basta fazer um DECODE que aplica essa diferença (49.3 &#8211; 49.2 &#8211;&gt;  SOMA &#8211; SOMA_ARR )<br />
Veja:</p>
<pre class="brush: sql;">
SELECT
  VLR_RATEADO
, ROUND(VLR_RATEADO,2) VLR_RATEADO_ARR
, DECODE( COUNT( 1) OVER (ORDER BY 1)
       , ROW_NUMBER()    OVER (ORDER BY VLR_RATEADO)
       , SUM( VLR_RATEADO) OVER (ORDER BY 1) - SUM( ROUND(VLR_RATEADO,2)) OVER (ORDER BY 1)+ ROUND(VLR_RATEADO,2)
       , ROUND(VLR_RATEADO,2)
       )  VLR_COM_DIF
FROM
(
SELECT
  nro_nota
, item
, valor
, (valor) / SUM(valor) OVER (ORDER BY nro_nota) * 49.3 vlr_rateado
FROM GLUFKE_teste
WHERE nro_nota = 50
)
/</pre>
<pre class="brush: plain;">VLR_RATEADO VLR_RATEADO_ARR VLR_COM_DIF
----------- --------------- -----------
6,873557692            6,87        6,87
18,53490384           18,53       18,53
23,89153846           23,89       23,90

SQL></pre>
<p>O select acima, aplica a diferença de 1 centavo apenas na ultima linha. Dessa forma, a diferença de centavo vai pra uma das linhas e o total rateado sempre fecha corretamente!<br />
A soma do VLR_RATEADO está errada! ( 6,87 + 18,53 + 23,89 = 49,29)<br />
Já o campo VLR_COM_DIF está com a soma correta, fechando os 49,30 !</p>
<p>Dessa forma, com apenas 1 select foi possível realizar o rateio e ainda aplicar a diferença do arredondamento em uma das linhas, graças as funções analíticas!</p>
<h3>Outro Exemplo:</h3>
<pre class="brush: sql;">INSERT INTO glufke_teste VALUES ( 51, 1, 5);
INSERT INTO glufke_teste VALUES ( 51, 2, 5);
INSERT INTO glufke_teste VALUES ( 51, 3, 5);
INSERT INTO glufke_teste VALUES ( 51, 4, 7.5);
INSERT INTO glufke_teste VALUES ( 51, 5, 7.5);</pre>
<p>Vamos aplicar o valor 10 nesses valores:</p>
<pre class="brush: sql;">SELECT
  NRO_NOTA
, ITEM
, VALOR
, ROUND(VLR_RATEADO,2) VLR_RATEADO_ARR
, DECODE( COUNT( 1) OVER (ORDER BY 1)
       , ROW_NUMBER()    OVER (ORDER BY VLR_RATEADO)
       , SUM( VLR_RATEADO) OVER (ORDER BY 1)
       - SUM( ROUND(VLR_RATEADO,2)) OVER (ORDER BY 1)
       + ROUND(VLR_RATEADO,2)
       , ROUND(VLR_RATEADO,2)
       )  VLR_COM_DIF
FROM
(
SELECT
  nro_nota
, item
, valor
, (valor) / SUM(valor) OVER (ORDER BY nro_nota) * 10 vlr_rateado
FROM GLUFKE_teste
WHERE nro_nota = 51
)</pre>
<pre class="brush: plain;">  NRO_NOTA       ITEM      VALOR VLR_RATEADO_ARR VLR_COM_DIF
---------- ---------- ---------- --------------- -----------
        51          1          5            1,67        1,67
        51          2          5            1,67        1,67
        51          3          5            1,67        1,67
        51          4        7,5            2,50        2,50
        51          5        7,5            2,50        2,49

SQL&gt;</pre>
<p>Para terminar a saga, vamos adicionar a palavra-chave PARTITION BY, e dessa forma, podemos fazer o calculo acima para todas as notas! No exemplo abaixo, vamos ratear o valor 10 pra cada nota. Ou seja, no total, a soma vai dar 20, pois temos apenas 2 notas no exemplo:</p>
<pre class="brush: sql;">SELECT
  NRO_NOTA
, ITEM
, VALOR
, ROUND(VLR_RATEADO,2) VLR_RATEADO_ARR
, DECODE( COUNT( 1) OVER (partition by nro_nota  ORDER BY 1)
       , ROW_NUMBER()    OVER (partition by nro_nota ORDER BY VLR_RATEADO)
       , SUM( VLR_RATEADO) OVER (partition by nro_nota ORDER BY 1)
       - SUM( ROUND(VLR_RATEADO,2)) OVER (partition by nro_nota ORDER BY 1)
       + ROUND(VLR_RATEADO,2)
       , ROUND(VLR_RATEADO,2)
       )  VLR_COM_DIF
FROM
(
SELECT
  nro_nota
, item
, valor
, (valor) / SUM(valor) OVER (partition by nro_nota ORDER BY nro_nota) * 10 vlr_rateado
FROM GLUFKE_teste
)</pre>
<pre class="brush: plain;">  NRO_NOTA       ITEM      VALOR VLR_RATEADO_ARR VLR_COM_DIF
---------- ---------- ---------- --------------- -----------
        50          1       1,45            1,39        1,39
        50          2       3,91            3,76        3,76
        50          3       5,04            4,85        4,85
        51          1       5,00            1,67        1,67
        51          3       5,00            1,67        1,67
        51          2       5,00            1,67        1,67
        51          5       7,50            2,50        2,50
        51          4       7,50            2,50        2,49

8 rows selected

SQL> </pre>
<p>Observe que a soma da coluna VLR_COM_DIF fecha exatamente os 20. Ja a coluna VLR_RATEADO_ARR dá diferença de centavo!   </p>
<p>Neste <a href="http://glufke.net/oracle/download/funcoes_ANALITICAS.html">LINK</a> tem diversos exemplos muito bons! Até mais!</p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2012/04/11/fazendo-rateio-atraves-de-funcoes-analiticas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Buscar por INSERT/UPDATE dentro da ALL_SOURCE</title>
		<link>http://glufke.net/2012/02/15/buscar-por-insertupdate-dentro-da-all_source/</link>
		<comments>http://glufke.net/2012/02/15/buscar-por-insertupdate-dentro-da-all_source/#comments</comments>
		<pubDate>Wed, 15 Feb 2012 19:04:16 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[all_source]]></category>
		<category><![CDATA[fonte]]></category>
		<category><![CDATA[source]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=502</guid>
		<description><![CDATA[
			
			
			
			
			
			
			
						
			É comum termos que procurar qual package ou qual procedure de banco que faz INSERT dentro de uma determinada tabela. 
Nestes casos, podemos usar a ALL_SOURCE, que contém os códigos de todos programas de banco. Normalmente um select com LIKE resolve o problema:
SELECT * FROM all_source
WHERE UPPER(text) LIKE '%INSERT%TABELA%'
O problema é que nem sempre o [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2012%2F02%2F15%2Fbuscar-por-insertupdate-dentro-da-all_source%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2012/02/15/buscar-por-insertupdate-dentro-da-all_source/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2012/02/15/buscar-por-insertupdate-dentro-da-all_source/"  data-text="Buscar por INSERT/UPDATE dentro da ALL_SOURCE" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2012/02/15/buscar-por-insertupdate-dentro-da-all_source/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>É comum termos que procurar qual package ou qual procedure de banco que faz INSERT dentro de uma determinada tabela. </p>
<p>Nestes casos, podemos usar a ALL_SOURCE, que contém os códigos de todos programas de banco. Normalmente um select com LIKE resolve o problema:</p>
<pre class="brush: sql;">SELECT * FROM all_source
WHERE UPPER(text) LIKE '%INSERT%TABELA%'</pre>
<p>O problema é que nem sempre o código está no padrão, por exemplo, o nome da tabela pode estar no lado ou na próxima linha!</p>
<pre class="brush: sql;">INSERT INTO tabelax...

INSERT
INTO tabelax...
</pre>
<p>O mesmo vale pra UPDATES! Ou seja, se o comando INSERT estiver na linha anterior, essa consulta simples <strong>não vai retornar o que procuramos</strong>!</p>
<pre class="brush: sql;">UPDATE tabelax SET...

UPDATE
tabelax
SET...
</pre>
<p><span id="more-502"></span></p>
<div id="ads_336x280"><script type="text/javascript">// <![CDATA[
   google_ad_client = "pub-8964513116661040"; google_alternate_color = "ffffFF"; google_ad_width = 336; google_ad_height = 280; google_ad_format = "336x280_as"; google_ad_type = "text_image"; //2007-09-07: wp_quadrado_gra google_ad_channel = "0247072216"; google_color_border = "FFFFFF"; google_color_bg = "FFFFff"; google_color_link = "4F82CB"; google_color_text = "000000"; google_color_url = "4F82CB";
// ]]&gt;</script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
</script></div>
<p>Para resolver o problema, eu fiz esse SQL que busca no banco todas linhas que contém a tabelax E a linha anterior! Com isso você pode encontrar os INSERTS e UPDATES que estão na linha antes também!</p>
<pre class="brush: sql;">SELECT *
FROM (
      SELECT a.owner, a.name, a.line, a.text
      FROM all_source a
      , (
          SELECT owner, name, line, type
          FROM all_source
          WHERE UPPER(text) LIKE '%%ENG_REVISED_ITEMS%'    ----> TABELA A PROCURAR !!!!
            AND owner='APPS'
            AND type <>'PACKAGE'
         )   B
      WHERE a.owner = b.owner
        AND a.name  = b.name
        AND a.type  = b.type
        AND (a.line  = b.line or a.line  = b.line-1)
      )
WHERE UPPER(text) LIKE '%INSERT%'                          ----> COMANDO QUE PODE ESTAR NA LINHA ANTERIOR !!!!
ORDER BY 1,2,3,4;</pre>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2012/02/15/buscar-por-insertupdate-dentro-da-all_source/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pipelined Table Functions &#8211; Funções para retornar &#8220;tabelas virtuais&#8221;</title>
		<link>http://glufke.net/2011/07/21/pipelined-table-functions-funcoes-para-retornar-tabelas-virtuais/</link>
		<comments>http://glufke.net/2011/07/21/pipelined-table-functions-funcoes-para-retornar-tabelas-virtuais/#comments</comments>
		<pubDate>Thu, 21 Jul 2011 15:42:41 +0000</pubDate>
		<dc:creator>fabio_prado</dc:creator>
				<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[pipelined]]></category>
		<category><![CDATA[tabelas]]></category>
		<category><![CDATA[virtuais]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=432</guid>
		<description><![CDATA[
			
			
			
			
			
			
			
						
			Neste artigo irei apresentar um recurso muito bom que existe no Oracle Database desde a versão 9i e chama-se Pipelined Table Function.
Este recurso permite criar funções que retornam dados como se fossem uma tabela virtual, podendo transformar os dados de retorno enquanto eles são produzidos, ou seja, é possível alterar os dados pesquisados em uma [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2011%2F07%2F21%2Fpipelined-table-functions-funcoes-para-retornar-tabelas-virtuais%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2011/07/21/pipelined-table-functions-funcoes-para-retornar-tabelas-virtuais/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2011/07/21/pipelined-table-functions-funcoes-para-retornar-tabelas-virtuais/"  data-text="Pipelined Table Functions &#8211; Funções para retornar &#8220;tabelas virtuais&#8221;" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2011/07/21/pipelined-table-functions-funcoes-para-retornar-tabelas-virtuais/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>Neste artigo irei apresentar um recurso muito bom que existe no Oracle Database desde a versão 9i e chama-se <strong>Pipelined Table Function</strong>.</p>
<p>Este recurso permite criar funções que retornam dados como se fossem uma <em>tabela virtual</em>, podendo transformar os dados de retorno enquanto eles são produzidos, ou seja, é possível alterar os dados pesquisados em uma tabela, linha por linha, enquanto eles são processados, sem ter que esperar pelo retorno completo do &#8220;<em>result set</em>&#8221; (conjunto de dados que são retornados pela função).</p>
<p>Este recurso é ótimo para ETL (Extract, Transform, and Load), pois é rápido e consome menos memória que outros métodos que podem ser utilizados para o mesmo objetivo, como por exemplo, preencher um cursor e percorrê-lo para transformar e retornar dados.</p>
<p>Seguem abaixo 3 scripts que demonstram como criar e testar uma <strong>Pipelined Table Function</strong>. Os scripts utilizam a tabela EMPLOYEES do schema de exemplo HR.</p>
<p><em>Para iniciar o passo-a-passo dos itens abaixo, é necessário conectar-se previamente no Banco de Dados desejado, através do SQL Plus, com um usuário com privilégios administrativos (usuário contendo a role DBA ou o privilégio de sistema SYSDBA) ou com o usuário HR.</em></p>
<h3>1- Criando a package HR.PKG_TYPES</h3>
<p>A package <strong>HR.PKG_TYPES</strong> contém os tipos de dados que são criados para retornarem uma tabela virtual na função que será criada no próximo passo:</p>
<pre class="brush: sql;">create or replace package HR.PKG_TYPES as
  TYPE TABLEEMPTYPE IS TABLE OF EMPLOYEES%ROWTYPE;
  TYPE ROWEMPTYPE IS RECORD(
          EMPLOYEE_ID    EMPLOYEES.EMPLOYEE_ID%TYPE,
          FIRST_NAME     EMPLOYEES.FIRST_NAME%TYPE,
          LAST_NAME      EMPLOYEES.LAST_NAME%TYPE,
          EMAIL          EMPLOYEES.EMAIL%TYPE,
          PHONE          EMPLOYEES.PHONE_NUMBER%TYPE,
          HIRE_DATE      EMPLOYEES.HIRE_DATE%TYPE,
          JOB_ID         EMPLOYEES.JOB_ID%TYPE,
          SALARY         EMPLOYEES.SALARY%TYPE,
          COMMISSION_PCT EMPLOYEES.COMMISSION_PCT%TYPE,
          MANAGER_ID     EMPLOYEES.MANAGER_ID%TYPE,
          DEPARTMENT_ID  EMPLOYEES.DEPARTMENT_ID%TYPE
         );
END;
/</pre>
<p><span id="more-432"></span></p>
<div id="ads_336x280"><script type="text/javascript">// <![CDATA[
 google_ad_client = "pub-8964513116661040"; google_alternate_color = "ffffFF"; google_ad_width = 336; google_ad_height = 280; google_ad_format = "336x280_as"; google_ad_type = "text_image"; //2007-09-07: wp_quadrado_gra google_ad_channel = "0247072216"; google_color_border = "FFFFFF"; google_color_bg = "FFFFff"; google_color_link = "4F82CB"; google_color_text = "000000"; google_color_url = "4F82CB";
// ]]&gt;</script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
</script></div>
<h3>2- Criando a função HR.FC_OBTER_EMPREGADOS</h3>
<p>A função <strong>HR.FC_OBTER_EMPREGADOS</strong> lê e retorna os dados de apenas 4 colunas da tabela HR.EMPLOYEES, transformando os dados das colunas LAST_NAME e EMAIL:</p>
<pre class="brush: sql;">CREATE OR REPLACE function HR.FC_OBTER_EMPREGADOS
  return PKG_TYPES.TABLEEMPTYPE
  PIPELINED IS
  var_linha PKG_TYPES.ROWEMPTYPE;
BEGIN
  FOR CUR_ROW IN (SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, EMAIL
                    FROM HR.EMPLOYEES) LOOP
    var_linha.EMPLOYEE_ID := CUR_ROW.EMPLOYEE_ID;
    var_linha.FIRST_NAME  := CUR_ROW.FIRST_NAME;
    var_linha.LAST_NAME   := UPPER(CUR_ROW.LAST_NAME);
    var_linha.EMAIL       := UPPER(cur_row.EMAIL || '@ORACLE.COM');

    PIPE ROW(VAR_LINHA);
  END LOOP;

  RETURN;
END;
/</pre>
<p>Obs.: A instrução PIPE ROW retorna os resultados para a sessão de usuário Oracle, linha por linha. Isso otimiza o tempo de resposta da aplicação.</p>
<h3>3- Testando a função HR.FC_OBTER_EMPREGADOS</h3>
<p>A query abaixo retorna os dados da função <strong>HR.FC_OBTER_EMPREGADOS</strong>, como se fossem uma tabela virtual:</p>
<pre class="brush: sql;">SELECT * FROM TABLE(HR.FC_OBTER_EMPREGADOS);
/</pre>
<h3>Observações:</h3>
<p>O exemplo deste artigo foi criado apenas para demonstrar o uso de Pipelined Table Functions. Para mais informações e exemplos deste tipo de função, consulte as referências no final deste artigo.</p>
<h3>Comentários Finais:</h3>
<p>Apesar das <em>Pipelined Table Functions</em> serem trabalhosas para criar, elas são ótimas para otimizar performance de queries complexas que utilizam funções de transformação para alterar os valores originais das consultas.</p>
<p>Na empresa em que trabalho temos um caso de uma query que demorava <strong>54 segundos</strong> para gerar os dados da folha de ponto mensal de cada empregado. Essa query estava literalmente &#8220;parando&#8221; o servidor de Banco de Dados. Eu orientei o desenvolvedor da query a alterá-la utilizando a <strong>Cláusula WITH </strong>(ver artigo &#8220;Cláusula WITH (para tunar queries)&#8221; que eu postei neste blog em 01/10/2010) <strong>+ Pipelined Table Function</strong>. Após as alterações o tempo de execução da query caiu para <strong>0.4 segundos</strong>.</p>
<h3>Referências:</h3>
<p>- <a href="http://www.praetoriate.com/10g_139.htm">http://www.praetoriate.com/10g_139.htm</a><br />
- <a href="http://oraclelon1.oracle.com/docs/cd/B14117_01/appdev.101/b10800/dcitblfnsref.htm">http://oraclelon1.oracle.com/docs/cd/B14117_01/appdev.101/b10800/dcitblfnsref.htm</a><br />
- <a href="http://www.codeguru.com/cpp/data/mfc_database/oracle/article.php/c4285/">http://www.codeguru.com/cpp/data/mfc_database/oracle/article.php/c4285/</a><br />
- <a href="http://www.databasejournal.com/features/oracle/article.php/2222781">http://www.databasejournal.com/features/oracle/article.php/2222781</a><br />
- <a href="http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28425/pipe_paral_tbl.htm#CHDJEGHC">http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28425/pipe_paral_tbl.htm</a></p>
<p><strong>Fonte: <a href="http://www.fabioprado.net/2010/12/pipelined-table-functions-funcao-para.html">http://www.fabioprado.net/2010/12/pipelined-table-functions-funcao-para.html</a></strong></p>
<p><strong><span style="color: #ff0000;">Fábio Prado &#8211; <a href="http://www.fabioprado.net/">http://www.fabioprado.net/</a><br />
Oracle Certified (OCA)<br />
Microsoft Certified (MCT + MCPD + MCAD + MCSD + MCDBA)</p>
<p></span></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2011/07/21/pipelined-table-functions-funcoes-para-retornar-tabelas-virtuais/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Melhorias nos EXTERNAL TABLES do 10g</title>
		<link>http://glufke.net/2009/01/13/melhorias-nos-external-tables-do-10g/</link>
		<comments>http://glufke.net/2009/01/13/melhorias-nos-external-tables-do-10g/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 23:48:10 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[External Table]]></category>
		<category><![CDATA[Oracle 10g]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=37</guid>
		<description><![CDATA[
			
			
			
			
			
			
			
						
			A partir do Oracle 9i foi criado o conceito de EXTERNAL TABLES, ou seja, você cria uma tabela baseado num arquivo texto no sistema operacional e pode fazer consultas SQL nessa tabela (ou seja, diretamente no arquivo texto como se fosse uma tabela)
Agora a partir do oracle 10g é possível também criar um arquivo texto [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2009%2F01%2F13%2Fmelhorias-nos-external-tables-do-10g%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2009/01/13/melhorias-nos-external-tables-do-10g/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2009/01/13/melhorias-nos-external-tables-do-10g/"  data-text="Melhorias nos EXTERNAL TABLES do 10g" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2009/01/13/melhorias-nos-external-tables-do-10g/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>A partir do Oracle 9i foi criado o conceito de EXTERNAL TABLES, ou seja, você cria uma tabela baseado num arquivo texto no sistema operacional e pode fazer consultas SQL nessa tabela (ou seja, diretamente no arquivo texto como se fosse uma tabela)<br />
Agora a partir do oracle 10g é possível também criar um arquivo texto baseado numa tabela do banco usando o novo driver de Data Pump existente.<span id="more-37"></span> </p>
<p>A possibilidade de gravar um arquivo texto se limita ao CREATE TABLE AS SELECT apenas. Não é permitido fazer UPDATE, DELETE ou INSERT numa external table.</p>
<p>Vamos a um exemplo:</p>
<pre class="brush: sql;">SQL> CREATE DIRECTORY external_directory AS
'c:\oracle\admin\betatwo\directory';

SQL> GRANT READ, WRITE ON DIRECTORY external_directory
TO scott;
SQL> CREATE TABLE emp_history_ext
(ename, retire_date,
last_retirement_pay_date, pay_amount)
ORGANIZATION EXTERNAL
( TYPE oracle_datapump
  DEFAULT DIRECTORY external_directory
LOCATION ('emp_history_01.exp', 'emp_history_02.exp') )
parallel
AS
SELECT a.ename, b.retire_date,
b.last_retirement_pay_date, b.pay_amount
FROM emp a, retire_pay b
WHERE a.empno=b.empno;</pre>
<p>Primeiramente, criamos um DIRECTORY e damos permissão de leitura e escrita. Isso apenas é requerido caso o usuário que criou o diretório não é o usuário que vai criar a external table. Após isso, criamos uma external table que será populada com o SELECT informado!</p>
<div id="ads_336x280"><script type="text/javascript"><!--
google_ad_client = "pub-8964513116661040";
google_alternate_color = "ffffFF";
google_ad_width = 336;
google_ad_height = 280;
google_ad_format = "336x280_as";
google_ad_type = "text_image";
//2007-09-07: wp_quadrado_gra
google_ad_channel = "0247072216";
google_color_border = "FFFFFF";
google_color_bg = "FFFFff";
google_color_link = "4F82CB";
google_color_text = "000000";
google_color_url = "4F82CB";
//--></script><script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div>
<p>Após a criação, basta fazer a consulta diretamente no arquivo texto:</p>
<pre class="brush: sql;">SQL> SELECT * FROM emp_history_ext;

ENAME      RETIRE_DA LAST_RETI PAY_AMOUNT
---------- --------- --------- ----------
SMITH      25-NOV-03 15-DEC-03       1000</pre>
<p>A criação dessa external table resulta na criação de um arquivo texto no sistema operacional com os dados informados no SELECT. Também é gerado um arquivo de LOG no mesmo diretório:</p>
<pre class="brush: plain;">C:\> dir c:\oracle\admin\betatwo\directory
 Volume in drive C has no label.
 Volume Serial Number is 3CE9-7321
 Directory of c:\oracle\admin\betatwo\directory
12/15/2003 07:52  PM      90    EMP_HISTORY_EXT_2528_1760.log
12/15/2003 07:52  PM   1,808    emp_history.exp</pre>
<p>Outras informações:<br />
Quando você dropa uma external table os arquivos textos continuam no sistema operacional! Isso pode ser um problema pois caso você execute novamente o comando pra recriar a external table, os arquivos já existirão e ocasionará um ERRO. Você deve excluir esses arquivos manualmente.</p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2009/01/13/melhorias-nos-external-tables-do-10g/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Novas funcionalidades com CONNECT BY</title>
		<link>http://glufke.net/2009/01/12/novas-funcionalidades-com-connect-by/</link>
		<comments>http://glufke.net/2009/01/12/novas-funcionalidades-com-connect-by/#comments</comments>
		<pubDate>Mon, 12 Jan 2009 11:23:42 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Connect By]]></category>
		<category><![CDATA[Oracle 10g]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=38</guid>
		<description><![CDATA[
			
			
			
			
			
			
			
						
			A partir do Oracle 10g temos mais algumas funcionalidades no uso da cláusula CONNECT BY dentro dos comandos SELECT. Essas mudanças se aplicam a queries hiearquicas permitindo o retorno de não apenas PAIS, FILHOS mas também &#8220;ancestrais&#8221;. São 3 as novas cláusulas disponíveis com CONNECT BY. 



connect_by_iscycle
Determina se a linha corrente tem uma linha filha [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2009%2F01%2F12%2Fnovas-funcionalidades-com-connect-by%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2009/01/12/novas-funcionalidades-com-connect-by/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2009/01/12/novas-funcionalidades-com-connect-by/"  data-text="Novas funcionalidades com CONNECT BY" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2009/01/12/novas-funcionalidades-com-connect-by/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>A partir do Oracle 10g temos mais algumas funcionalidades no uso da cláusula CONNECT BY dentro dos comandos SELECT. Essas mudanças se aplicam a queries hiearquicas permitindo o retorno de não apenas PAIS, FILHOS mas também &#8220;ancestrais&#8221;. São 3 as novas cláusulas disponíveis com CONNECT BY.<span id="more-38"></span> </p>
<div id="ads_336x280"><script type="text/javascript"><!--
google_ad_client = "pub-8964513116661040";
google_alternate_color = "ffffFF";
google_ad_width = 336;
google_ad_height = 280;
google_ad_format = "336x280_as";
google_ad_type = "text_image";
//2007-09-07: wp_quadrado_gra
google_ad_channel = "0247072216";
google_color_border = "FFFFFF";
google_color_bg = "FFFFff";
google_color_link = "4F82CB";
google_color_text = "000000";
google_color_url = "4F82CB";
//-->
</script><script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div>
<p><strong>connect_by_iscycle</strong><br />
Determina se a linha corrente tem uma linha filha que também é seu ancestral.</p>
<pre class="brush: sql;">SQL>  SELECT ename Emp, CONNECT_BY_ISCYCLE leaf, mgr "Manager",
  2     LEVEL-1 "Pathlen", SYS_CONNECT_BY_PATH(empno, '/') "Path"
  3     FROM emp
  4     Where level-1 < 3
  5     CONNECT BY NOCYCLE PRIOR empno = mgr;

EMP              LEAF Manager    Pathlen Path
---------- ---------- ------- ---------- ------------------------------
SCOTT               0    7566          0 /7788
ADAMS               0    7788          1 /7788/7876
FORD                0    7566          0 /7902
SMITH               0    7902          1 /7902/7369
ALLEN               0    7698          0 /7499
WARD                0    7698          0 /7521
MARTIN              0    7698          0 /7654
TURNER              0    7698          0 /7844
JAMES               0    7698          0 /7900
MILLER              0    7782          0 /7934
ADAMS               0    7788          0 /7876
JONES               0    7839          0 /7566
SCOTT               0    7566          1 /7566/7788
ADAMS               0    7788          2 /7566/7788/7876
FORD                0    7566          1 /7566/7902
SMITH               0    7902          2 /7566/7902/7369
BLAKE               0    7839          0 /7698
ALLEN               0    7698          1 /7698/7499
WARD                0    7698          1 /7698/7521
MARTIN              0    7698          1 /7698/7654
TURNER              0    7698          1 /7698/7844
JAMES               0    7698          1 /7698/7900
CLARK               0    7839          0 /7782
MILLER              0    7782          1 /7782/7934
SMITH               0    7902          0 /7369
KING                0                  0 /7839
JONES               0    7839          1 /7839/7566
SCOTT               0    7566          2 /7839/7566/7788
FORD                0    7566          2 /7839/7566/7902
BLAKE               0    7839          1 /7839/7698
ALLEN               0    7698          2 /7839/7698/7499
WARD                0    7698          2 /7839/7698/7521
MARTIN              0    7698          2 /7839/7698/7654
TURNER              0    7698          2 /7839/7698/7844
JAMES               0    7698          2 /7839/7698/7900
CLARK               0    7839          1 /7839/7782
MILLER              0    7782          2 /7839/7782/7934

37 rows selected

SQL> </pre>
<p><strong>connect_by_isleaf</strong><br />
Determina se a linha corrente é uma FOLHA na árvore definida pela operação connect by.</p>
<pre class="brush: sql;">SQL> SELECT ename "Emp", CONNECT_BY_ISLEAF leaf, mgr "Manager",
  2     LEVEL-1 "Pathlen", SYS_CONNECT_BY_PATH(empno, '/') "Path"
  3     FROM emp
  4     Where level-1 < 3
  5     CONNECT BY NOCYCLE PRIOR empno = mgr;

Emp              LEAF Manager    Pathlen Path
---------- ---------- ------- ---------- ------------------------------
SCOTT               0    7566          0 /7788
ADAMS               1    7788          1 /7788/7876
FORD                0    7566          0 /7902
SMITH               1    7902          1 /7902/7369
ALLEN               1    7698          0 /7499
WARD                1    7698          0 /7521
MARTIN              1    7698          0 /7654
TURNER              1    7698          0 /7844
JAMES               1    7698          0 /7900
MILLER              1    7782          0 /7934
ADAMS               1    7788          0 /7876
JONES               0    7839          0 /7566
SCOTT               0    7566          1 /7566/7788
ADAMS               1    7788          2 /7566/7788/7876
FORD                0    7566          1 /7566/7902
SMITH               1    7902          2 /7566/7902/7369
BLAKE               0    7839          0 /7698
ALLEN               1    7698          1 /7698/7499
WARD                1    7698          1 /7698/7521
MARTIN              1    7698          1 /7698/7654
TURNER              1    7698          1 /7698/7844
JAMES               1    7698          1 /7698/7900
CLARK               0    7839          0 /7782
MILLER              1    7782          1 /7782/7934
SMITH               1    7902          0 /7369
KING                0                  0 /7839
JONES               0    7839          1 /7839/7566
SCOTT               0    7566          2 /7839/7566/7788
FORD                0    7566          2 /7839/7566/7902
BLAKE               0    7839          1 /7839/7698
ALLEN               1    7698          2 /7839/7698/7499
WARD                1    7698          2 /7839/7698/7521
MARTIN              1    7698          2 /7839/7698/7654
TURNER              1    7698          2 /7839/7698/7844
JAMES               1    7698          2 /7839/7698/7900
CLARK               0    7839          1 /7839/7782
MILLER              1    7782          2 /7839/7782/7934

37 rows selected

SQL> </pre>
<p><strong>connect_by_root</strong><br />
Retorna o valor da coluna da linha Raíz.</p>
<pre class="brush: sql;">SQL> SELECT ename "Emp", CONNECT_BY_ROOT mgr "Manager",
  2     LEVEL-1 "Pathlen", SYS_CONNECT_BY_PATH(empno, '/') "Path"
  3     FROM emp
  4     Where level-1 < 3
  5     CONNECT BY NOCYCLE PRIOR empno = mgr;

Emp           Manager    Pathlen Path
---------- ---------- ---------- ------------------------------
SCOTT            7566          0 /7788
ADAMS            7566          1 /7788/7876
FORD             7566          0 /7902
SMITH            7566          1 /7902/7369
ALLEN            7698          0 /7499
WARD             7698          0 /7521
MARTIN           7698          0 /7654
TURNER           7698          0 /7844
JAMES            7698          0 /7900
MILLER           7782          0 /7934
ADAMS            7788          0 /7876
JONES            7839          0 /7566
SCOTT            7839          1 /7566/7788
ADAMS            7839          2 /7566/7788/7876
FORD             7839          1 /7566/7902
SMITH            7839          2 /7566/7902/7369
BLAKE            7839          0 /7698
ALLEN            7839          1 /7698/7499
WARD             7839          1 /7698/7521
MARTIN           7839          1 /7698/7654
TURNER           7839          1 /7698/7844
JAMES            7839          1 /7698/7900
CLARK            7839          0 /7782
MILLER           7839          1 /7782/7934
SMITH            7902          0 /7369
KING                           0 /7839
JONES                          1 /7839/7566
SCOTT                          2 /7839/7566/7788
FORD                           2 /7839/7566/7902
BLAKE                          1 /7839/7698
ALLEN                          2 /7839/7698/7499
WARD                           2 /7839/7698/7521
MARTIN                         2 /7839/7698/7654
TURNER                         2 /7839/7698/7844
JAMES                          2 /7839/7698/7900
CLARK                          1 /7839/7782
MILLER                         2 /7839/7782/7934

37 rows selected

SQL> </pre>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2009/01/12/novas-funcionalidades-com-connect-by/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cláusula RETURNING com funções somatórias</title>
		<link>http://glufke.net/2009/01/09/clausula-returning-com-funcoes-somatorias/</link>
		<comments>http://glufke.net/2009/01/09/clausula-returning-com-funcoes-somatorias/#comments</comments>
		<pubDate>Fri, 09 Jan 2009 12:57:54 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Oracle 10g]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=39</guid>
		<description><![CDATA[
			
			
			
			
			
			
			
						
			Oracle 10g agora permite o uso de funções somatórias na cláusula RETURNING. O seguinte exemplo faz um UPDATE no salário de todos empregados e retorna a média salarial resultante para as linhas afetadas. 
SQL> VARIABLE a NUMBER
SQL> UPDATE employee
  2  SET sal=sal*1.10 RETURNING AVG(sal) INTO :a;
SQL> PRINT a
      [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2009%2F01%2F09%2Fclausula-returning-com-funcoes-somatorias%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2009/01/09/clausula-returning-com-funcoes-somatorias/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2009/01/09/clausula-returning-com-funcoes-somatorias/"  data-text="Cláusula RETURNING com funções somatórias" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2009/01/09/clausula-returning-com-funcoes-somatorias/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>Oracle 10g agora permite o uso de funções somatórias na cláusula RETURNING. O seguinte exemplo faz um UPDATE no salário de todos empregados e retorna a média salarial resultante para as linhas afetadas.<span id="more-39"></span> </p>
<pre class="brush: sql;">SQL> VARIABLE a NUMBER
SQL> UPDATE employee
  2  SET sal=sal*1.10 RETURNING AVG(sal) INTO :a;
SQL> PRINT a
           a
    --------
      655.22</pre>
<div id="ads_336x280"><script type="text/javascript"><!--
google_ad_client = "pub-8964513116661040";
google_alternate_color = "ffffFF";
google_ad_width = 336;
google_ad_height = 280;
google_ad_format = "336x280_as";
google_ad_type = "text_image";
//2007-09-07: wp_quadrado_gra
google_ad_channel = "0247072216";
google_color_border = "FFFFFF";
google_color_bg = "FFFFff";
google_color_link = "4F82CB";
google_color_text = "000000";
google_color_url = "4F82CB";
//-->
</script><script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div>
<p>O mesmo exemplo acima mostrado dentro de um bloco PL/SQL:</p>
<pre class="brush: sql;">Declare
     a   number;
begin
     update employee set sal=sal*1.10 returning avg(sal) into a;
     dbms_output.put_line(a);
end;</pre>
<p>Lembre-se que essa média é apenas das linhas afetadas pelo UPDATE!</p>
<p>Também é possível utilizar em comandos DELETE:</p>
<pre class="brush: sql;">Declare
     a   number;
begin
     delete from employee where sal > 1000 returning avg(sal) into a;
     dbms_output.put_line(a);
end;</pre>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2009/01/09/clausula-returning-com-funcoes-somatorias/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ignorando Acentos e Maiúsculas/Minúsculas no 10g</title>
		<link>http://glufke.net/2009/01/08/ignorando-acentos-e-maiusculasminusculas-no-10g/</link>
		<comments>http://glufke.net/2009/01/08/ignorando-acentos-e-maiusculasminusculas-no-10g/#comments</comments>
		<pubDate>Thu, 08 Jan 2009 12:19:12 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Acentuação]]></category>
		<category><![CDATA[Oracle 10g]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=36</guid>
		<description><![CDATA[
			
			
			
			
			
			
			
						
			O Oracle 10g agora permite fazer consultas considerando ou não acentos e maiúsculas/minúsculas. Isso é feito pelo uso do parâmetro NLS_SORT. Vamos aos exemplos.
Temos que adicionar o prefixo _ai para &#8220;accent insensitive&#8221; (ignora os acentos). Ou _ci para &#8220;case insensitive&#8221; (ignora se é maiúsculo ou minúsculo).
O nls_sort afeta uma série de funções SQL e operações, [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2009%2F01%2F08%2Fignorando-acentos-e-maiusculasminusculas-no-10g%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2009/01/08/ignorando-acentos-e-maiusculasminusculas-no-10g/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2009/01/08/ignorando-acentos-e-maiusculasminusculas-no-10g/"  data-text="Ignorando Acentos e Maiúsculas/Minúsculas no 10g" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2009/01/08/ignorando-acentos-e-maiusculasminusculas-no-10g/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>O Oracle 10g agora permite fazer consultas considerando ou não acentos e maiúsculas/minúsculas. Isso é feito pelo uso do parâmetro <strong>NLS_SORT</strong>. Vamos aos exemplos.<span id="more-36"></span></p>
<p>Temos que adicionar o prefixo <strong>_ai</strong> para &#8220;accent insensitive&#8221; (ignora os acentos). Ou <strong>_ci</strong> para &#8220;case insensitive&#8221; (ignora se é maiúsculo ou minúsculo).</p>
<p>O nls_sort afeta uma série de funções SQL e operações, incluindo essas:<br />
* WHERE<br />
* ORDER BY<br />
* START WITH<br />
* HAVING<br />
* IN / NOT IN<br />
* BETWEEN<br />
* CASE-WHEN</p>
<p>Algumas funções entretanto, não são afetadas pelo nls_sort. (Como LIKE, TRIM, INSTR).</p>
<div id="ads_336x280"><script type="text/javascript">// <![CDATA[
google_ad_client = "pub-8964513116661040";
google_alternate_color = "ffffFF";
google_ad_width = 336;
google_ad_height = 280;
google_ad_format = "336x280_as";
google_ad_type = "text_image";
//2007-09-07: wp_quadrado_gra
google_ad_channel = "0247072216";
google_color_border = "FFFFFF";
google_color_bg = "FFFFff";
google_color_link = "4F82CB";
google_color_text = "000000";
google_color_url = "4F82CB";
// ]]&gt;</script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
</script></div>
<p>Observe o comportamento normal do ORDER BY:</p>
<pre class="brush: sql;">SQL&gt; select * from thomas_teste order by 1;

NOME
-------------------------------------------
THOMAS 2
Thomas 3
thomas 1

SQL&gt; </pre>
<p>Agora, a mesma consulta, mas antes mudamos o NLS_SORT para ignorar os maiúsculos e minúsculos:</p>
<pre class="brush: sql;">SQL&gt; ALTER SESSION SET NLS_SORT=generic_m_ci;

Session altered.

SQL&gt; select * from thomas_teste order by 1;

NOME
-----------------------------------------------
thomas 1
THOMAS 2
Thomas 3

SQL&gt; </pre>
<p>Agora, o mesmo resultado acima SEM mudar a sessão:</p>
<pre class="brush: sql;">SQL&gt; select * from thomas_teste
2  order by nlssort( nome, 'NLS_SORT=generic_m_ci');

NOME
-------------------------------------------------------
thomas 1
THOMAS 2
Thomas 3

SQL&gt; </pre>
<p>E é claro, também pode usar o <strong>_ai</strong> para ignorar os acentos.<br />
NOTA: o <strong>_ai</strong> inclui a funcionalidade do CASE INSENSITIVE também!</p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2009/01/08/ignorando-acentos-e-maiusculasminusculas-no-10g/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Select que retorna os Números Primos</title>
		<link>http://glufke.net/2007/10/11/select-que-retorna-os-numeros-primos/</link>
		<comments>http://glufke.net/2007/10/11/select-que-retorna-os-numeros-primos/#comments</comments>
		<pubDate>Thu, 11 Oct 2007 22:40:31 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Curiosidade]]></category>
		<category><![CDATA[Matemática]]></category>

		<guid isPermaLink="false">http://glufke.net/2007/10/11/select-que-retorna-os-numeros-primos/</guid>
		<description><![CDATA[
			
			
			
			
			
			
			
						
			Esse post vai mais a título de curiosidade. Sabemos que os números primos são números naturais que podem ser divididos apenas por dois números naturais, o 1 (um) e ele mesmo. Pois a tempos que eu queria um SQL que retornasse esses números! 
Após um pouco de tentativas, saiu o SQL abaixo:
select z.zz PRIMOS
from
 (select [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2007%2F10%2F11%2Fselect-que-retorna-os-numeros-primos%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2007/10/11/select-que-retorna-os-numeros-primos/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2007/10/11/select-que-retorna-os-numeros-primos/"  data-text="Select que retorna os Números Primos" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2007/10/11/select-que-retorna-os-numeros-primos/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>Esse post vai mais a título de curiosidade. Sabemos que os <a href="http://pt.wikipedia.org/wiki/N%C3%BAmero_primo">números primos</a> são números naturais que podem ser divididos apenas por dois números naturais, o 1 (um) e ele mesmo. Pois a tempos que eu queria um SQL que retornasse esses números! <span id="more-20"></span></p>
<p>Após um pouco de tentativas, saiu o SQL abaixo:</p>
<pre class="brush: sql;">select z.zz PRIMOS
from
 (select rownum+1 zz
  from user_tables
  where rownum < 100
 ) z
where zz not in (
                select y.bb
                from (select rownum+1 aa from user_tables a where rownum < 100) x
                ,    (select rownum+1 bb from user_tables b where rownum < 100) y
                where bb<>aa
                  and mod(bb, aa)=0
                  and aa<=bb
                )
/</pre>
<div id="ads_336x280"><script type="text/javascript"><!--
google_ad_client = "pub-8964513116661040";
google_alternate_color = "ffffFF";
google_ad_width = 336;
google_ad_height = 280;
google_ad_format = "336x280_as";
google_ad_type = "text_image";
//2007-09-07: wp_quadrado_gra
google_ad_channel = "0247072216";
google_color_border = "FFFFFF";
google_color_bg = "FFFFff";
google_color_link = "4F82CB";
google_color_text = "000000";
google_color_url = "4F82CB";
//-->
</script><script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div>
<p>Abaixo, colocaremos uma amostra dos resultados:</p>
<pre class="brush: sql;">SQL> select z.zz PRIMOS
  2  from
  3   (select rownum+1 zz
  4    from user_tables
  5    where rownum < 100
  6   ) z
  7  where zz not in (
  8                  select y.bb
  9                  from (select rownum+1 aa from user_tables a where rownum < 100) x
 10                  ,    (select rownum+1 bb from user_tables b where rownum < 100) y
 11                  where bb<>aa
 12                    and mod(bb, aa)=0
 13                    and aa<=bb
 14                  )
 15  /

   PRIMOS
---------
        2
        3
        5
        7
       11
       13
       17
       19
       23
       29
       31
       37
       41
       43
       47
       53
       59
       61
       67
       71
       73
       79
       83
       89
       97

25 rows selected.
SQL></pre>
<p>Talvez essa não seja a melhor forma de fazer isso (obviamente, que usar SQL pra calcular isso não é a melhor saída). Mesmo assim, fica como um "desafio vencido". </p>
<p>Comentários <a href="http://glufke.net/oracle/viewtopic.php?t=637">aqui</a></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2007/10/11/select-que-retorna-os-numeros-primos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Como usar Índices Virtuais &#8211; NOSEGMENT INDEXES</title>
		<link>http://glufke.net/2007/09/25/como-usar-indices-virtuais-nosegment-indexes/</link>
		<comments>http://glufke.net/2007/09/25/como-usar-indices-virtuais-nosegment-indexes/#comments</comments>
		<pubDate>Tue, 25 Sep 2007 22:49:51 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[DBA]]></category>
		<category><![CDATA[Tuning]]></category>

		<guid isPermaLink="false">http://glufke.net/2007/09/25/como-usar-indices-virtuais-nosegment-indexes/</guid>
		<description><![CDATA[
			
			
			
			
			
			
			
						
			Essa é para quem faz tunning de SQL. Digamos que você quer verificar se a criação de um novo í­ndice vai ser realmente usada pelo otimizador. Antes de criá-lo, você pode testar se ele resolverá seu problema atraves de INDICE VIRTUAL.
O Oracle vai criar o í­ndice no dicionário de dados mas não vai criar o [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2007%2F09%2F25%2Fcomo-usar-indices-virtuais-nosegment-indexes%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2007/09/25/como-usar-indices-virtuais-nosegment-indexes/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2007/09/25/como-usar-indices-virtuais-nosegment-indexes/"  data-text="Como usar Índices Virtuais &#8211; NOSEGMENT INDEXES" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2007/09/25/como-usar-indices-virtuais-nosegment-indexes/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>Essa é para quem faz tunning de SQL. Digamos que você quer verificar se a criação de um novo í­ndice vai ser realmente usada pelo otimizador. Antes de criá-lo, você pode testar se ele resolverá seu problema atraves de INDICE VIRTUAL.<span id="more-17"></span></p>
<p>O Oracle vai criar o í­ndice no dicionário de dados mas não vai criar o í­ndice fisicamente. Nada será armazenado nem acessado!</p>
<pre class="brush: sql;">SQL> set autotrace traceonly explain

SQL> select name from emp where name = 'Alex';

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=164 Card=1 Bytes=500)
   1    0   TABLE ACCESS (FULL) OF 'EMP' (Cost=164 Card=1 Bytes=500)</pre>
<p><strong>Criando o Í­ndice</strong></p>
<pre class="brush: sql;">
SQL> create index emp_vir_idx1 on emp(name) nosegment;

Index created.</pre>
<div id="ads_336x280"><script type="text/javascript"><!--
google_ad_client = "pub-8964513116661040";
google_alternate_color = "ffffFF";
google_ad_width = 336;
google_ad_height = 280;
google_ad_format = "336x280_as";
google_ad_type = "text_image";
//2007-09-07: wp_quadrado_gra
google_ad_channel = "0247072216";
google_color_border = "FFFFFF";
google_color_bg = "FFFFff";
google_color_link = "4F82CB";
google_color_text = "000000";
google_color_url = "4F82CB";
//-->
</script><script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div>
<p>Agora, vamos ver se ele vai usar:</p>
<pre class="brush: sql;">
SQL> set autotrace traceonly explain

SQL> select name from emp where name = 'Alex';

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=164 Card=1 Bytes=500)
   1    0   TABLE ACCESS (FULL) OF 'EMP' (Cost=164 Card=1 Bytes=500)</pre>
<p>Hei! Acesso FULL? Porque o oracle não está usando meu novo í­ndice?<br />
Você deve primeiro alterar sua sessão com o parâmetro oculto &#8220;_use_nosegment_indexes&#8221;.</p>
<pre class="brush: sql;">
SQL> alter session set "_use_nosegment_indexes" = true;

Session altered.

SQL> select name from emp where name = 'Alex';

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=500)
   1    0   INDEX (RANGE SCAN) OF 'EMP_VIR_IDX1' (NON-UNIQUE) (Cost=1 Card=1 Bytes=500) </pre>
<p>Comente <a href="http://glufke.net/oracle/viewtopic.php?t=417">aqui</a></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2007/09/25/como-usar-indices-virtuais-nosegment-indexes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ver Plano de execução de um SQL rodando</title>
		<link>http://glufke.net/2007/09/25/ver-plano-de-execucao-de-um-sql-rodando/</link>
		<comments>http://glufke.net/2007/09/25/ver-plano-de-execucao-de-um-sql-rodando/#comments</comments>
		<pubDate>Tue, 25 Sep 2007 14:36:31 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Trace]]></category>
		<category><![CDATA[Tuning]]></category>

		<guid isPermaLink="false">http://glufke.net/2007/09/25/ver-plano-de-execucao-de-um-sql-rodando/</guid>
		<description><![CDATA[
			
			
			
			
			
			
			
						
			Imagine que você rodou um SQL que está demorando muito. O Trace está desligado e você quer saber o que pode estar errado com o SQL. Com essa dica, você enxerga o plano de execução deste SQL.
1. Escolha o SQL que está rodando
select address, hash_value, child_number, sql_text
from v$sql
where users_executing  0
/



2. Rode o sql abaixo, [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2007%2F09%2F25%2Fver-plano-de-execucao-de-um-sql-rodando%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2007/09/25/ver-plano-de-execucao-de-um-sql-rodando/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2007/09/25/ver-plano-de-execucao-de-um-sql-rodando/"  data-text="Ver Plano de execução de um SQL rodando" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2007/09/25/ver-plano-de-execucao-de-um-sql-rodando/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>Imagine que você rodou um SQL que está demorando muito. O Trace está desligado e você quer saber o que pode estar errado com o SQL. Com essa dica, você enxerga o plano de execução deste SQL.<span id="more-18"></span></p>
<p><strong>1. Escolha o SQL que está rodando</strong></p>
<pre class="brush: sql;">select address, hash_value, child_number, sql_text
from v$sql
where users_executing <> 0
/</pre>
<div id="ads_336x280"><script type="text/javascript"><!--
google_ad_client = "pub-8964513116661040";
google_alternate_color = "ffffFF";
google_ad_width = 336;
google_ad_height = 280;
google_ad_format = "336x280_as";
google_ad_type = "text_image";
//2007-09-07: wp_quadrado_gra
google_ad_channel = "0247072216";
google_color_border = "FFFFFF";
google_color_bg = "FFFFff";
google_color_link = "4F82CB";
google_color_text = "000000";
google_color_url = "4F82CB";
//-->
</script><script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div>
<p><strong>2. Rode o sql abaixo, informando o address, hash_value, child_number retornado do Primeiro SQL.</strong></p>
<pre class="brush: sql;">SET VERIFY OFF
COL id          FORMAT 999
COL parent_id   FORMAT 999 HEADING "PARENT"
COL operation   FORMAT a35 TRUNCATE
COL object_name FORMAT a30
SELECT  id, parent_id, LPAD (' ', LEVEL - 1) ||
        operation || ' ' || options operation, object_name
FROM    (
        SELECT id, parent_id, operation, options, object_name
        FROM   v$sql_plan
        WHERE  address = '&#038;address'
        AND    hash_value = &#038;hash_value
        AND    child_number = &#038;child_number
        )
START WITH id = 0
CONNECT BY PRIOR id = parent_id; </pre>
<p>Obrigado a Roger Schrag que é o autor dessa dica!<br />
Comente <a href="http://glufke.net/oracle/viewtopic.php?t=538">aqui</a></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2007/09/25/ver-plano-de-execucao-de-um-sql-rodando/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

