<?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</title>
	<atom:link href="http://glufke.net/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[<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[<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>Tutorial de Instalação do Oracle APEX 4.1</title>
		<link>http://glufke.net/2011/11/30/tutorial-de-instalacao-do-oracle-apex-4-1/</link>
		<comments>http://glufke.net/2011/11/30/tutorial-de-instalacao-do-oracle-apex-4-1/#comments</comments>
		<pubDate>Wed, 30 Nov 2011 17:39:42 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[DBA]]></category>
		<category><![CDATA[apex]]></category>
		<category><![CDATA[instalação]]></category>
		<category><![CDATA[xe]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=489</guid>
		<description><![CDATA[Este tutorial mostra como instalar o Apex 4.1 no Oracle XE. Aí vai um passo a passo:
1 – Baixar e instalar Oracle XE
Download nesse link: http://www.oracle.com/technetwork/database/express-edition/overview/index.html

2 – Baixar Oracle Apex 4.1
Download nesse link: http://www.oracle.com/technetwork/developer-tools/apex/downloads/index.html?ssSourceSiteId=ocombr
// 

Descompactar arquivos no C:\oraclexe\apex
CMD&#62; cd c:\oraclexe\apex
CMD&#62; sqlplus sys@xe as sysdba
SQL&#62; @apexins SYSAUX SYSAUX TEMP /i/
CMD&#62; sqlplus sys@xe as sysdba
SQL&#62; @apxldimg.sql c:\oraclexe
SQL&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>Este tutorial mostra como instalar o Apex 4.1 no Oracle XE. Aí vai um passo a passo:</p>
<h3>1 – Baixar e instalar Oracle XE</h3>
<p>Download nesse link: <a href="http://www.oracle.com/technetwork/database/express-edition/overview/index.html">http://www.oracle.com/technetwork/database/express-edition/overview/index.html</a><br />
<span id="more-489"></span></p>
<h3>2 – Baixar Oracle Apex 4.1</h3>
<p>Download nesse link: <a href="http://www.oracle.com/technetwork/developer-tools/apex/downloads/index.html?ssSourceSiteId=ocombr">http://www.oracle.com/technetwork/developer-tools/apex/downloads/index.html?ssSourceSiteId=ocombr</a></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>Descompactar arquivos no C:\oraclexe\apex</p>
<pre class="brush: plain;">CMD&gt; cd c:\oraclexe\apex
CMD&gt; sqlplus sys@xe as sysdba
SQL&gt; @apexins SYSAUX SYSAUX TEMP /i/
CMD&gt; sqlplus sys@xe as sysdba
SQL&gt; @apxldimg.sql c:\oraclexe
SQL&gt; @apxxepwd.sql &lt;password&gt;
SQL&gt; exec dbms_xdb.setListenerLocalAccess (l_access =&gt; FALSE);
SQL&gt; exit
CMD&gt; cd C:\oraclexe\apex\builder\pt-br
CMD&gt; set NLS_LANG=American_America.AL32UTF8
CMD&gt; sqlplus sys@xe as sysdba
SQL&gt; ALTER SESSION SET CURRENT_SCHEMA = APEX_040100;
SQL&gt; @load_pt-br.sql
SQL&gt; exit
CMD&gt; exit</pre>
<h3>3 – Como acessar</h3>
<p>Acesse o Apex pelo navegador: <a href="http://127.0.0.1:8080/apex">http://127.0.0.1:8080/apex</a><br />
<strong> Workspace:</strong> Internal<br />
<strong> Username:</strong> Admin<br />
<strong> Password:</strong> &lt;password&gt;<br />
Agora é só criar sua Workspace e começar a trabalhar..</p>
<p><em>Texto criado por Alex Pagliarini<br />
Comentários <a href="http://glufke.net/oracle/viewtopic.php?f=9&#038;t=8207">aqui</a></em></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2011/11/30/tutorial-de-instalacao-do-oracle-apex-4-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Impressões sobre o GUOB TECH DAY 2011</title>
		<link>http://glufke.net/2011/08/16/impressoes-sobre-o-guob-tech-day-2011/</link>
		<comments>http://glufke.net/2011/08/16/impressoes-sobre-o-guob-tech-day-2011/#comments</comments>
		<pubDate>Tue, 16 Aug 2011 16:41:50 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[Evento]]></category>
		<category><![CDATA[2011]]></category>
		<category><![CDATA[GUOB]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[sp]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=453</guid>
		<description><![CDATA[Participei do GUOB TECH DAY 2011 e posso dizer: Foi um evento memorável! Resolvi colocar aqui a opinião de algumas pessoas que participaram! Então, aí vai:



Aprender Oracle
Achei muito bom o evento, muito bem organizado, ótimos palestrantes e congressistas. Valeu cada minuto que estava lá. Parabéns a todos e ano que vem, pretendo ir de novo!!!
http://aprenderoracle.com/2011/07/review-do-evento-guob-2011/


PHPDBA
Um [...]]]></description>
			<content:encoded><![CDATA[<p>Participei do GUOB TECH DAY 2011 e posso dizer: <strong>Foi um evento memorável!</strong> Resolvi colocar aqui a opinião de algumas pessoas que participaram! Então, aí vai:</p>
<p style="text-align: center;"><img class="aligncenter" src="http://franquini.files.wordpress.com/2011/07/v6_guob_680x320px.jpg?w=614&amp;h=288" alt="GUOB Tech Day" width="476" /></p>
<p><span id="more-453"></span></p>
<blockquote>
<h3>Aprender Oracle</h3>
<p><em>Achei muito bom o evento, muito bem organizado, ótimos palestrantes e congressistas. Valeu cada minuto que estava lá. Parabéns a todos e ano que vem, pretendo ir de novo!!!</em></p>
<p><a href="http://aprenderoracle.com/2011/07/review-do-evento-guob-2011/" target="_blank">http://aprenderoracle.com/2011/07/review-do-evento-guob-2011/</a></p></blockquote>
<p style="text-align: center;"><img class="aligncenter" src="http://phpdba.files.wordpress.com/2011/07/guob_tech_day_2011_03.jpg" alt="GUOB Tech Day - Palestrantes" width="476" height="318" /></p>
<blockquote>
<h3>PHPDBA</h3>
<p><em>Um evento ótimo, mas sem excelência, seria como ganhar um iPad de presente numa caixa de papelão. Que se dane a caixa de papelão, eu ganhei um iPad!</em></p>
<p><em>O GUOB Tech Day é como ganhar um iPad das mãos do Steve Jobs, tirando uma foto com ele entregando o produto embalado, na caixa original, com uma dedicatória e ainda ganhar um bônus infinito de créditos na AppleStore!</em></p>
<p><em>Eu saio do GUOB com um espírito renovado. Cheio de idéias, cheio de intenções, cheio de vontade de crescer na área, de ser um profissional mais completo, de ajudar a comunidade. Sinto-me muito bem por participar de uma comunidade de DBAs quando estou ali, no meio daquela galera. (Paulo Henrique)</em></p>
<p><a href="http://phpdba.wordpress.com/2011/07/22/guob-tech-day-2011-attendant-feedback/" target="_blank">http://phpdba.wordpress.com/2011/07/22/guob-tech-day-2011-attendant-feedback/</a></p></blockquote>
<p style="text-align: center;"><img class="aligncenter" src="http://conteudo.imasters.com.br/21478/38546.jpg" alt="GUOB Tech Day" width="476" height="318" /></p>
<blockquote>
<h3>iMasters</h3>
<p><em>O conjunto de palestrantes nacionais e internacionais foi bem escolhido e a organização, instalações, local e demais detalhes foram ótimos. Recomendo a todos que estiverem interessados no mundo de tecnologias Oracle que se filiem gratuitamente ao GUOB e que participem da comunidade para tornar eventos como este cada vez melhores.</em></p>
<p><em></em><br />
<a href="http://www.imasters.com.br/artigo/21478/outros/cobertura-do-guob-tech-day-2011" target="_blank">http://www.imasters.com.br/artigo/21478/outros/cobertura-do-guob-tech-day-2011</a></p></blockquote>
<p style="text-align: center;"><img class="aligncenter" src="http://www.guob.com.br/uploads/images/GUOB2011_fotos/guob_tech_day_2011_100.jpg" alt="GUOB Tech Day" width="476" /></p>
<blockquote>
<h3>Eduardo Legatti</h3>
<p><em>Quem não foi, realmente perdeu uma grande oportunidade de ver excelentes palestras e prestigiar grandes profissionais do mundo Oracle. Foi sensacional.</em></p>
<p><em></em><br />
<a href="http://eduardolegatti.blogspot.com/2011/07/minha-experiencia-no-guob-tech-day-2011.html" target="_blank">http://eduardolegatti.blogspot.com/2011/07/minha-experiencia-no-guob-tech-day-2011.html</a></p></blockquote>
<p style="text-align: center;"><img class="aligncenter" src="http://aprenderoracle.com/wp-content/uploads/2011/07/IMG_0226.jpg" alt="GUOB Tech Day" width="476" height="318" /></p>
<blockquote>
<h3>CAPIN</h3>
<p><em> Eu Fui! E irei em outros.</em><br />
<a href="http://franquini.wordpress.com/2011/07/17/guob-tech-day-2011/" target="_blank">http://franquini.wordpress.com/2011/07/17/guob-tech-day-2011/</a></p></blockquote>
<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>FOTOS OFICIAIS DO GUOB</h3>
<p><a href="http://www.guob.com.br/index.php?page=album-de-fotos">http://www.guob.com.br/index.php?page=album-de-fotos</a></p>
<h3>COBERTURA PELA OTN LA</h3>
<p>Abaixo, deixo os links da cobertura feita pela OTN:</p>
<p>FOTOS:<br />
<a href="http://flic.kr/s/aHsjvknxN2">Brasil – Oracle Technology Network America Latina Tour 2011</a></p>
<p>VIDEOS:<br />
<a href="http://youtu.be/ht8f9G_NXFI">Rodrigo Almeida</a><br />
<a href="http://youtu.be/0PFRIra2FQU">Eduardo Hahn</a><br />
<a href="http://youtu.be/QpQh7E_MHk8">Marcus Vinicius</a><br />
<a href="http://youtu.be/nImSQinpV8s">Rodrigo Mufalani</a><br />
<a href="http://youtu.be/tIs6BfJXY1k">Thomas Glufke</a><br />
<a href="http://youtu.be/bDChH0FFtw4">David Siquiera</a><br />
<a href="http://youtu.be/uhfvresbVTk">Marina Neumann</a> </p>
<p><em>Se você tem um review do GUOB Tech Day, envie um email para thomas arroba glufke.net com o link do seu review que atualizaremos essa página!</em></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2011/08/16/impressoes-sobre-o-guob-tech-day-2011/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[<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>glufke.net sorteia livros no twitter</title>
		<link>http://glufke.net/2010/08/11/glufke-net-sorteia-livros-no-twitter/</link>
		<comments>http://glufke.net/2010/08/11/glufke-net-sorteia-livros-no-twitter/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 15:31:25 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[Geral]]></category>
		<category><![CDATA[promoção]]></category>
		<category><![CDATA[sorteio]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=354</guid>
		<description><![CDATA[O site glufke.net possui alguns livros que estão no acervo e vão ser sorteados para os seguidores do twitter!
Estes serão os livros sorteados:

SORTEIO ENCERRADO &#8211; LISTA DOS GANHADORES
Dia 13/08/2010 &#8211; Guia Novatec &#8211; Oracle 10g SQL &#8211; GANHADOR: @garcia_joao
Dia 20/08/2010 &#8211; Guia Novatec &#8211; Cascading Style Sheets &#8211; GANHADOR: @marcelo_hugo
Dia 27/08/2010 &#8211; Guia Novatec &#8211; [...]]]></description>
			<content:encoded><![CDATA[<p>O site glufke.net possui alguns livros que estão no acervo e vão ser sorteados para os seguidores do twitter!</p>
<p>Estes serão os livros sorteados:</p>
<p><img class="alignnone" title="Sorteio Twitter Glufke.net" src="http://glufke.net/oracle/images/promocao.png" alt="" width="478" height="171" /></p>
<p><strong><span style="color: #ff0000;">SORTEIO ENCERRADO &#8211; LISTA DOS GANHADORES</span></strong><br />
Dia 13/08/2010 &#8211; Guia Novatec &#8211; Oracle 10g SQL &#8211; GANHADOR: @<a href="http://twitter.com/garcia_joao" target="_blank">garcia_joao</a><br />
Dia 20/08/2010 &#8211; Guia Novatec &#8211; Cascading Style Sheets &#8211; GANHADOR: @<a href="http://twitter.com/marcelo_hugo" target="_blank">marcelo_hugo</a><br />
Dia 27/08/2010 &#8211; Guia Novatec &#8211; Java 2 &#8211; GANHADOR: @<a href="http://twitter.com/stefandeckert" target="_blank">stefandeckert</a><br />
Dia 03/09/2010 &#8211; Guia Novatec &#8211; JavaServer Pages &#8211; GANHADOR: @<a href="http://twitter.com/jeroqueiroz" target="_blank">jeroqueiroz</a><br />
Dia 10/09/2010 &#8211; Livro Programação de Jogos com C++ e DirectX &#8211; GANHADOR: @<a href="http://twitter.com/anitokj" target="_blank">anitokj</a></p>
<h3>Como Participar?</h3>
<p>1. Para concorrer você deve seguir no twitter o <a href="http://www.twitter.com/glufke" target="_blank">@glufke</a></p>
<p>2. Enviar a seguinte mensagem:</p>
<p><strong><span style="color: #000000;">Quero participar do sorteio de livros de oracle, java, etc do @glufke &#8211; http://bit.ly/cMIzSV</span></strong></p>
<p>3. Aguardar o sorteio nos dias acima ao MEIO DIA!</p>
<h3>Normas</h3>
<p>1. O Sorteio se dará de forma aleatória para todos que estão seguindo <a title="twitter" href="http://twitter.com/glufke" target="_blank">@glufke</a> e deram RT na mensagem.<br />
2. O vencedor será contatado via twitter e será solicitado o endereço para enviar o livro.<br />
3. O envio do livro será pago pelo GLUFKE.NET via encomenda registrada</p>
<p>Qualquer dúvida, envie para o twitter <a title="twitter" href="http://twitter.com/glufke" target="_blank">@glufke</a></p>
<p>BOA SORTE E BONS ESTUDOS</p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2010/08/11/glufke-net-sorteia-livros-no-twitter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Concorrentes no Oracle EBS com saída em Excel</title>
		<link>http://glufke.net/2010/04/15/concorrentes-no-oracle-ebs-com-saida-em-excel/</link>
		<comments>http://glufke.net/2010/04/15/concorrentes-no-oracle-ebs-com-saida-em-excel/#comments</comments>
		<pubDate>Thu, 15 Apr 2010 03:39:49 +0000</pubDate>
		<dc:creator>ricardo_rauber</dc:creator>
				<category><![CDATA[ERP]]></category>
		<category><![CDATA[Concurrent]]></category>
		<category><![CDATA[EBS]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[R11]]></category>
		<category><![CDATA[R12]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=328</guid>
		<description><![CDATA[Este artigo demonstra como criar Concurrents no Oracle EBS com saída para Microsoft Excel. Aí vai um passo a passo:
1 – Adicionar o tipo de saída Microsoft Excel
Na responsabilidade Administrador de Sistema você deve acessar o caminho abaixo:
Instalar -&#62; Idiomas
Insira um registro com estes valores:
Formato do Arquivo = Text
Tipo de Mime = application/vnd.ms-excel
Descrição = Microsoft [...]]]></description>
			<content:encoded><![CDATA[<p>Este artigo demonstra como criar Concurrents no Oracle EBS com saída para Microsoft Excel. Aí vai um passo a passo:</p>
<h3>1 – Adicionar o tipo de saída Microsoft Excel</h3>
<p>Na responsabilidade Administrador de Sistema você deve acessar o caminho abaixo:<br />
Instalar -&gt; Idiomas<br />
Insira um registro com estes valores:<br />
Formato do Arquivo = Text<br />
Tipo de Mime = application/vnd.ms-excel<br />
Descrição = Microsoft Excel<br />
<a href="http://glufke.net/wp-content/uploads/2010/04/ebsexcell11.png"><img class="alignnone size-full wp-image-331" title="Figura1" src="http://glufke.net/wp-content/uploads/2010/04/ebsexcell11.png" alt="" width="540" height="241" /></a><span id="more-328"></span>
<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 – Criar um procedimento PL/SQL</h3>
<p>A saída deve ter os campos separados pelo caractere TAB.</p>
<pre class="brush: sql;">
CREATE OR REPLACE PACKAGE PKG_REP_EXCEL IS

  PROCEDURE BUILD (ERRBUF OUT VARCHAR2,
                   RETCODE OUT NUMBER);
END PKG_REP_EXCEL;
/

CREATE OR REPLACE PACKAGE BODY PKG_REP_EXCEL IS
  PROCEDURE BUILD (ERRBUF OUT VARCHAR2,
                   RETCODE OUT NUMBER) IS
    CURSOR CUR IS
      SELECT '1' A, '2' B, '3' C FROM DUAL
      UNION
      SELECT '4' A, '5' B, '6' C FROM DUAL
      UNION SELECT '7' A, '8' B, '9' C FROM DUAL;

    REG CUR%ROWTYPE;

    V_DIV VARCHAR2(1) := CHR(9); -- TAB
    V_OUT VARCHAR2(4000);

  BEGIN

    -- HEADER
    V_OUT := 'A' || V_DIV || 'B' || V_DIV || 'C';
    FND_FILE.PUT_LINE(FND_FILE.OUTPUT, V_OUT);

    -- LINES
    FOR REG IN CUR LOOP
      V_OUT := REG.A || V_DIV || REG.B ||   V_DIV || REG.C;
      FND_FILE.PUT_LINE(FND_FILE.OUTPUT, V_OUT);
    END LOOP;

  END BUILD;

END PKG_REP_EXCEL;
/</pre>
<h3>3 – Criar o Concorrente</h3>
<p>O executável é criado normalmente como Procedimento Armazenado do PL/SQL e o programa com formato de saída Texto.<br />
<a href="http://glufke.net/wp-content/uploads/2010/04/ebsexcell2.png"><img src="http://glufke.net/wp-content/uploads/2010/04/ebsexcell2.png" alt="" title="Figura2" width="540" height="255" class="alignnone size-full wp-image-332" /></a></p>
<p><a href="http://glufke.net/wp-content/uploads/2010/04/ebsexcell3.png"><img src="http://glufke.net/wp-content/uploads/2010/04/ebsexcell3.png" alt="" title="Figura3" width="540" height="360" class="alignnone size-full wp-image-333" /></a></p>
<h3>4 – Execução</h3>
<p>Após a visualização da saída, utilize o menu <strong>Ferramentas</strong> e a opção <strong>Copiar Arquivo</strong>. Nesse momento aparecerá uma LOV para você escolher o tipo de saída.<br />
<a href="http://glufke.net/wp-content/uploads/2010/04/ebsexcell4.png"><img src="http://glufke.net/wp-content/uploads/2010/04/ebsexcell4.png" alt="" title="Figura4" width="540" height="300" class="alignnone size-full wp-image-334" /></a></p>
<p><a href="http://glufke.net/wp-content/uploads/2010/04/ebsexcell5.png"><img src="http://glufke.net/wp-content/uploads/2010/04/ebsexcell5.png" alt="" title="Figura5" width="540" height="300" class="alignnone size-full wp-image-335" /></a></p>
<h3>5 – Arquivo Microsoft Excel</h3>
<p>Selecionado o tipo de arquivo <strong>Microsoft Excel</strong>, basta salvar ou abrir e temos o nosso relatório.<br />
<strong>Observação:</strong> Tome cuidado ao salvar o arquivo para não deixar a extensão <strong>TXT</strong>. Caso o arquivo seja gravado com essa extensão, altere para <strong>XLS</strong>.<br />
<a href="http://glufke.net/wp-content/uploads/2010/04/ebsexcell6.png"><img src="http://glufke.net/wp-content/uploads/2010/04/ebsexcell6.png" alt="" title="Figura6" width="540" height="387" class="alignnone size-full wp-image-330" /></a></p>
<p><em>Texto criado por Ricardo Rauber &#8211; Tutorial disponível para download <a href="http://glufke.net/oracle/download/oracle_ebs_concorrentes_em_excel.pdf">AQUI</a><br />
Comentários <a href="http://glufke.net/oracle/viewtopic.php?t=6095">aqui</a></em></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2010/04/15/concorrentes-no-oracle-ebs-com-saida-em-excel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Local Index vs. Global Index em tabela particionada</title>
		<link>http://glufke.net/2010/03/31/local-index-vs-global-indexem-tabela-particionada/</link>
		<comments>http://glufke.net/2010/03/31/local-index-vs-global-indexem-tabela-particionada/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 12:51:45 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Index]]></category>
		<category><![CDATA[Oracle 10g]]></category>
		<category><![CDATA[Oracle 11g]]></category>
		<category><![CDATA[Partition]]></category>
		<category><![CDATA[Tuning]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=207</guid>
		<description><![CDATA[A maioria das pessoas tem essas perguntas sobre Index Partition:

O que é um Local Index?
O que é um Global Index?
Quando você forçaria a criação de um Global Index em uma partition table?
Quando você recomendaria criar um Global Index em vez de um Local Index?

Para responder a essas perguntas&#8230;.
1. O que é um Local Index?
Local Indexes [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://www.cs.duke.edu/courses/fall08/cps274/images/gear.jpg" alt="" width="164" height="164" />A maioria das pessoas tem essas perguntas sobre Index Partition:</p>
<ul>
<li><strong>O que é um Local Index?</strong></li>
<li><strong>O que é um Global Index?</strong></li>
<li><strong>Quando você forçaria a criação de um Global Index em uma partition table?</strong></li>
<li><strong>Quando você recomendaria criar um Global Index em vez de um Local Index?</strong></li>
</ul>
<p>Para responder a essas perguntas&#8230;.</p>
<h3>1. O que é um Local Index?</h3>
<p>Local Indexes particionados são mais fáceis de gerenciar, cada partição do Local Index está associado a uma partição. Eles também oferecem maior disponibilidade e são comuns em ambientes de DSS. Quando tomamos qualquer ação (MERGE, SPLIT,EXCHANGE etc) em um Local Index, isso impacta apenas aquela partição e as outras estarão disponíveis. Nós não podemos adicionar explicitamente um Local Index para uma nova partição. O Local Index será adicionado implicitamente a nova partição, quando for criada uma nova partição na tabela. Da mesma forma, não podemos dropar o índice local em uma partição específica. Ele pode ser dropado automaticamente quando nós dropamos a partição da tabela subjacente. Local Indexes podem ser UNIQUE quando a chave da partição é parte do índice composto. Unique Local Indexes são úteis para o ambiente OLTP. Podemos também criar bitmap indexes em tabelas, com a restrição de que os índices de bitmap deve ser local para a tabela particionada. Eles não podem ser Global Indexes.</p>
<pre class="brush: plain;">SQL&gt; CREATE TABLE employees
2 (employee_id NUMBER(4) NOT NULL,
3 last_name VARCHAR2(10),
4 department_id NUMBER(2))
5 PARTITION BY RANGE (department_id)
6 (PARTITION employees_part1 VALUES LESS THAN (10) TABLESPACE ODS_STAGE_DATA,
7 PARTITION employees_part2 VALUES LESS THAN (20) TABLESPACE ODS_STAGE_DATA,
8 PARTITION employees_part3 VALUES LESS THAN (30) TABLESPACE ODS_STAGE_DATA);

Table created.

SQL&gt; declare
2 v_no number :=1;
3 begin
4 delete employees;
5 for i in 1..10 loop
6 insert into employees values(v_no,'name...',v_no);
7 v_no := v_no+1;
8 end loop;
9 end;
10 /

PL/SQL procedure successfully completed.

SQL&gt;
SQL&gt; create index idx_local on employees(last_name) local;

Index created.

SQL&gt;</pre>
<p><span id="more-207"></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. O que é Global Index?</h3>
<p>Global Indexe são usado em ambientes OLTP e oferecem um acesso eficiente a qualquer registro individual. Temos dois tipos de Global Index: Eles são <strong>global Non-partitioned index</strong> e <strong>Global partitioned index</strong>. Global Non-partitioned index se comportam como um índice não particionado.</p>
<p>A chave de partição de um Global partitioned index é independente da chave de partição da tabela. A maior partição de um Global Index deve ter um limite de partição, cujos todos valores são MAXVALUE. Se você quiser adicionar uma nova partição, sempre, é preciso dividir a partição MAX. Se um Global Index Partition está vazio, você pode dropá-lo explicitamente com um ALTER INDEX DROP PARTITION. Se um Global Index Partition contém dados, ao dropar a partição faz com que a partição mais próxima seja marcada como inutilizável. Não é possível dropar a maior partição de um índice global.</p>
<p><strong>Exemplo de  Global Non-partitioned index:</strong></p>
<pre class="brush: plain;">SQL&gt; CREATE INDEX employees_global_idx ON employees(employee_id);

Index created.

SQL&gt;</pre>
<p><strong>Exemplo de Global Partitioned index:</strong></p>
<pre class="brush: plain;">SQL&gt; CREATE INDEX employees_global_part_idx ON employees(employee_id)
2 GLOBAL PARTITION BY RANGE(employee_id)
3 (PARTITION p1 VALUES LESS THAN(3),
4 PARTITION p2 VALUES LESS THAN(6),
5 PARTITION p3 VALUES LESS THAN(9));
PARTITION p3 VALUES LESS THAN(9))
*
ERROR at line 5:
ORA-14021: MAXVALUE must be specified for all columns

SQL&gt; CREATE INDEX employees_global_part_idx ON employees(employee_id)
2 GLOBAL PARTITION BY RANGE(employee_id)
3 (PARTITION p1 VALUES LESS THAN(3),
4 PARTITION p2 VALUES LESS THAN(6),
5 PARTITION p3 VALUES LESS THAN(11),
6 PARTITION p4 VALUES LESS THAN(20),
7 PARTITION p5 VALUES LESS THAN(MAXVALUE));

Index created.</pre>
<p>Agora a partição p4 está vazia. Vamos dropar a partição vazia e ver o status:</p>
<pre class="brush: plain;">SQL&gt; select count(*) from employees where
2 employee_id between 12 and 20;

COUNT(*)
----------
0
SQL&gt; ALTER index employees_global_part_idx drop partition p4;

Index altered.

SQL&gt; SELECT partition_name,status from user_ind_partitions where
2 index_name='EMPLOYEES_GLOBAL_PART_IDX';

PARTITION_NAME STATUS
------------------------------ --------
P1 USABLE
P2 USABLE
P3 USABLE
P5 USABLE</pre>
<p>Agora vamos dropar a partição P3 e ver o estado. Ao dropar essa partição, isso deve invalidar a partição mais próxima. Aqui a partição P5 é a próxima maior partição.</p>
<pre class="brush: plain;">SQL&gt; alter index employees_global_part_idx drop partition p3;

Index altered.

SQL&gt; SELECT partition_name,status from user_ind_partitions where
2 index_name='EMPLOYEES_GLOBAL_PART_IDX';

PARTITION_NAME STATUS
------------------------------ --------
P1 USABLE
P2 USABLE
P5 UNUSABLE

SQL&gt; alter index employees_global_part_idx rebuild;
alter index employees_global_part_idx rebuild
*
ERROR at line 1:
ORA-14086: a partitioned index may not be rebuilt as a whole

SQL&gt; alter index employees_global_part_idx rebuild partition p5;

Index altered.

SQL&gt; SELECT partition_name,status from user_ind_partitions where
2 index_name='EMPLOYEES_GLOBAL_PART_IDX';

PARTITION_NAME STATUS
------------------------------ --------
P1 USABLE
P2 USABLE
P5 USABLE</pre>
<p>Partition Index podem ser mantidos usando UPDATE GLOBAL INDEXES. Os índice estarão disponíveis durante a manutenção e está disponível online. Nós não precisamos de rebuild o índice após a manutenção do índice.</p>
<p>Por exemplo,</p>
<pre class="brush: plain;">SQL&gt; alter table employees drop partition employees_part3
2 update global indexes;

Table altered.

SQL&gt; SELECT partition_name,status from user_ind_partitions where
2 index_name='EMPLOYEES_GLOBAL_PART_IDX';

PARTITION_NAME STATUS
------------------------------ --------
P1 USABLE
P2 USABLE
P5 USABLE

SQL&gt;</pre>
<h3>3. Quando você forçaria a criação de Global index em uma Partition table?</h3>
<p>Quando você cria uma chave primária, você será forçado a criar um Global Index. Quando você cria Unique Index, você é forçado a criar o Global Index. Manter a coluna única é a razão mais comum para os índices globais. Se você tentar criar um Local Index em chave única, você receberá o erro abaixo.</p>
<pre class="brush: plain;">ORA-14039: partitioning columns must form a subset of key columns of a UNIQUE index</pre>
<p>Assim, podemos criar Local Index em chave única, quando adicionamos a chave de partição como parte da chave composta no índice. Vamos demonstrar isto:</p>
<p><strong>No exemplo abaixo, o Unique Index falhou já que a chave da partição não é parte da chave composta do índice.</strong></p>
<pre class="brush: plain;">SQL&gt; create unique index idx_emp_id on employees(employee_id) local;
create unique index idx_emp_id on employees(employee_id) local
*
ERROR at line 1:
ORA-14039: partitioning columns must form a subset of key columns of a UNIQUE index</pre>
<p>No caso abaixo, ele permite criar um Global Index:</p>
<pre class="brush: plain;">SQL&gt; create unique index idx_emp_id on employees(employee_id);

Index created.

SQL&gt; drop index idx_emp_id;

Index dropped.</pre>
<p>O caso abaixo, o Unique Index é criado com sucesso, pois a chave DEPARTMENT_ID é parte da chave composta.</p>
<pre class="brush: plain;">SQL&gt; create unique index idx_emp_id on employees(employee_id,department_id) local;

Index created.

SQL&gt;</pre>
<h3>4. Quando você recomendaria criar Global Index vs. Local Index?</h3>
<p>Podemos usar Global Index se uma consulta retorna um número pequeno de linhas a partir de um número potencialmente grande de partições.</p>
<p><em>Texto baseado no blog do <a href="http://myorastuff.blogspot.com">Govind</a></em></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2010/03/31/local-index-vs-global-indexem-tabela-particionada/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Larry Ellison é o Ironman</title>
		<link>http://glufke.net/2010/03/26/larry-ellison-e-o-ironman/</link>
		<comments>http://glufke.net/2010/03/26/larry-ellison-e-o-ironman/#comments</comments>
		<pubDate>Fri, 26 Mar 2010 16:00:14 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[Fun Stuff]]></category>
		<category><![CDATA[diversão]]></category>
		<category><![CDATA[Larry Ellison]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=270</guid>
		<description><![CDATA[Iniciando a categoria &#8220;Fun-Stuff&#8221;, trazemos a você a revelação do ano: Larry Ellison é o Ironman.
Você pensou que o Iron Man era mesmo o bilionário industrial Tony Stark, temos provas de que isso é apenas um apelido mal disfarçado do magnata bilionário da Oracle, Larry Ellison. A prova:
Larry Ellison &#8211; Oracle:

Tony Stark &#8211; Ironman

Tony Stark [...]]]></description>
			<content:encoded><![CDATA[<p>Iniciando a categoria &#8220;Fun-Stuff&#8221;, trazemos a você a revelação do ano: <strong>Larry Ellison é o Ironman</strong>.</p>
<p>Você pensou que o Iron Man era mesmo o bilionário industrial <strong><a href="http://en.wikipedia.org/wiki/Iron_Man">Tony Stark</a>,</strong> temos provas de que isso é apenas um apelido mal disfarçado do magnata bilionário da Oracle, Larry Ellison. A prova:</p>
<p style="text-align: center;"><strong>Larry Ellison &#8211; Oracle:</strong><br />
<img class="aligncenter" title="Larry Ellison" src="http://glufke.net/oracle/images/larry1.png" alt="" width="402" height="288" /></p>
<p style="text-align: center;"><strong>Tony Stark &#8211; Ironman</strong><br />
<img class="aligncenter" title="Ironman" src="http://glufke.net/oracle/images/iron1.png" alt="" width="402" height="288" /></p>
<p>Tony Stark tem o ROSTO do Larry, a VOZ do Larry, os CARROS do Larry, o DINHEIRO de Larry e os AVIÕES também. Pra completar a lista de evidências, temos a Oracle como um dos principais patrocinadores do filme:</p>
<p style="text-align: center;"><a href="http://ironmanmovie.marvel.com/"><img class="aligncenter" title="Ironman 2" src="http://glufke.net/oracle/images/iron2.png" alt="" width="460" height="360" /></a></p>
<p><em>Está comprovado!</em></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2010/03/26/larry-ellison-e-o-ironman/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Edition-Based Redefinition: a feature mais matadora do Oracle 11g R2</title>
		<link>http://glufke.net/2010/02/04/edition-based-redefinition/</link>
		<comments>http://glufke.net/2010/02/04/edition-based-redefinition/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 14:44:51 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[DBA]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[Edition-Based Redefinition]]></category>
		<category><![CDATA[Funções]]></category>
		<category><![CDATA[Oracle 11g]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=214</guid>
		<description><![CDATA[Eu considero Edition-Based Redefinition a nova característica mais matadora do Oracle Database 11g Release 2. Em suma, é a capacidade de executar uma atualização de aplicações online. É também um recurso gigante, tão grande que vai demorar pelo menos três colunas para descrevê-lo. Vou começar em Como usar Edition-Based Redefinition afim de aplicar &#8220;patches&#8221; em [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" title="Oracle 11g R2" src="http://glufke.net/wp-content/uploads/2010/02/oracle_db11g.jpg" alt="" width="246" height="78" />Eu considero <strong>Edition-Based Redefinition</strong> a nova característica mais matadora do Oracle Database 11g Release 2. Em suma, é a capacidade de executar uma atualização de aplicações online. É também um recurso gigante, tão grande que vai demorar pelo menos três colunas para descrevê-lo. Vou começar em <em>Como usar Edition-Based Redefinition afim de aplicar &#8220;patches&#8221; em sistemas</em>.</p>
<p>Ao longo dos anos, o banco Oracle permite realizrmos muitas operações online, como:</p>
<ul>
<li>Modificar a maioria dos parâmetros (Apenas 90 dos 350 não são modificáveis online.)</li>
<li>Reorganização de objetos (transformar uma tabela não particionada em uma particionada, recuperando um espaço livre, e assim por diante)</li>
<li>Criar índices</li>
<li>Aplicação de patches no Banco de dados com o Oracle Real Application Clusters</li>
<li>Atualizar o banco de dados Oracle de release em release</li>
</ul>
<p>O resultado é que quase todas mudanças em nível de banco de dados pode ser feito enquanto o banco está funcionando e realizando transações &#8211; com algumas raras excepções gritantes, como re-criar uma procedure, alterar triggers, adicionar grants, revoke de grant, e modificar views. Em suma, os objetos que constituem esse tipo de modificação não podiam ser modificadas, enquanto os usuários estavam utilizando. Se uma procedure estava sendo executada e um DBA tentou atualizar ela (CREATE OR REPLACE o código com o novo código mexido, afim de corrigir um bug), o DBA iria ficar esperando (BLOCKED) por essa pessoa até terminar sua execução.</p>
<p>Além disso, qualquer pessoa que tentou posteriormente executar uma procedure que o DBA está tentando substituir também ficaria bloqueado pelo DBA. E na maioria dos casos, o DBA não modifica apenas uma única procedure, mas muitas,  e o CREATE OR REPLACE do novo código da procedure tenderia a invalidar outros objetos dependentes também. O banco de dados parece &#8220;congelar&#8221;, o DBA não pode realizar as tarefas de patch (substituir alguns procedimentos, pacotes, views, triggers, e assim por diante), e os usuários finais não podem realizar as suas tarefas. Eles acabaram bloqueando e travando-se mutuamente.</p>
<p>Isto tudo termina tudo com o <strong>Oracle Database 11g Release 2</strong> e o <strong>Edition-Based Redefinition</strong>, que permite aos DBAs e usuários finais acessar mais de uma ocorrência de uma stored procedure, trigger, view, e outros objetos e, portanto, isolar as mudanças em um esquema. Começando com o Oracle Database 11g Release 2, um único esquema pode agora ter duas ou mais ocorrências (vamos pensar em &#8220;versões&#8221;) de um stored procedure (função, trigger, e assim por diante) ou uma view ou de sinônimos e todos seus metadados relacionados, tais como GRANTS a esses objetos. (Estas duas ocorrências são independentes, eles coexistem, mas não interferem umas com as outras.) A &#8220;mágica&#8221; que permite isso é o novo objeto de <strong>edição</strong> (EDITION),  que introduz um novo namespace transparente que permite mais de uma ocorrência ao mesmo tempo de uma stored procedure, trigger e assim por diante.<span id="more-214"></span></p>
<p>No passado, um objeto de esquema era referenciado com dois componentes: o owner do objeto e o nome. Isso impedira a existência de dois procedimentos armazenados como &#8220;P&#8221; em um único esquema. Ou seja, você poderia ter apenas um objeto referenciado por &#8220;OWNER.P&#8221;.</p>
<p>O objeto de edição no Oracle Database 11g Release 2 introduz uma <em>terceira dimensão</em> no esquema de resolução de nomes: todos os objetos são referenciados pela <strong>edição da sessão</strong>, o <strong>owner do objeto</strong> e o<strong> nome do objeto</strong>. Cada banco de dados tem pelo menos uma edição a ela associados, e a base de dados tem sempre uma edição padrão. Quando você cria uma sessão no Oracle Database 11g Release 2, a sua sessão terá um atributo associado a ela que indica a edição que sua sessão estará usando (por padrão, esta será a edição padrão do banco de dados). Usando ALTER SESSION, você pode especificar qualquer edição para a qual tiver sido concedido o acesso em sua sessão.</p>
<p>Quando você invocar ou referenciar objetos no Oracle Database 11g Release 2, esses objetos são referenciado também com a edição fixada na sua sessão. Isso significa que um administrador do aplicativo pode agora logar, alterar uma sessão para utilizar uma <strong>edição chamada VERSION2</strong>, por exemplo, e compilar o código para esta <strong>edição</strong>. O trabalho realizado pelo administrador da aplicação na edição VERSION2 é visível apenas em sessões usando a edição VERSION2. &#8220;VERSION2&#8243; porque não é a edição padrão, ninguém mais vê essas mudanças (novas procedures, views, drop de pacotes, e assim por diante) a menos que a pessoa solicita especificamente (via ALTER SESSION) e tem o privilégio de usar e &#8220;ver&#8221; aquela edição. O administrador do aplicativo é capaz de criar ou substituir qualquer código sem concorrer com os outros que estão executando o código. Se o administrador do aplicativo precisa substituir 50 unidades de PL/SQL, essa pessoa pode fazê-lo em isolamento durante todo o tempo enquanto aplicação de produção continua rodando.</p>
<p>O exemplo a seguir demonstra este pequeno conceito. Vou começar como DBA, criando uma conta de demonstração e concedendo o mínimo de privilégios necessário:</p>
<pre class="brush: plain;">SQL&gt; create user demo
  2    identified by demo;
User created.

SQL&gt; grant create session,
  2       create procedure
  3    to demo;
Grant succeeded.</pre>
<p>Agora vou iniciar o processo que me permitirá criar mais de uma ocorrência de objetos do meu código na base de dados. Vou precisar de uma nova edição, a fim de fazer isso. O seguinte comando cria a nova edição:</p>
<pre class="brush: plain;">SQL&gt; create edition version2
  2      as child of ora$base;
Edition created.</pre>
<p>Criei uma edição chamada VERSION2 no meu banco de dados, e ela começa sendo filha de ORA$BASE. Como mencionado acima, cada banco de dados tem pelo menos uma edição e cada banco de dados tem uma edição padrão. Por exemplo, todo Oracle Database 11g Release 2 vai ter uma edição padrão chamado ORA$BASE. Como filha de ORA$BASE, minha edição VERSION2 começa a vida como uma <strong>cópia completa</strong> da edição padrão ORA$BASE. Tudo que está valendo em ORA$BASE também está em VERSION2.</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>É importante notar, contudo, que esta VERSION2 é uma cópia virtual. A instrução CREATE EDITION não copia fisicamente cada objeto da ORA$BASE. Pelo contrário, VERSION2 aponta para os objetos ORA$BASE, e não vai começar a usar espaço no dicionário até que eu modifique os objetos no contexto da edição VERSION2.</p>
<p>Então, agora eu vou instalar a versão 1 da minha aplicação na conta DEMO:</p>
<pre class="brush: plain;">DEMO&gt; create or replace
  2      procedure my_procedure
  3      as
  4      begin
  5         dbms_output.put_line
  6         ( 'I am version 1.0' );
  7      end;
  8      /
Procedure created.

DEMO&gt; create or replace
  2      procedure my_procedure2
  3      as
  4      begin
  5         my_procedure;
  6      end;
  7      /
Procedure created.
</pre>
<p>Até agora muito simples, e quando eu executo essa &#8220;aplicação&#8221; eu vejo o seguinte:</p>
<pre class="brush: plain;">DEMO&gt; exec my_procedure2
I am version 1.0

PL/SQL procedure successfully completed.</pre>
<p>Agora, vamos supor que este código esteja executando em produção por um tempo e eu descubro um bug, algo que precise reparar na stored procedure. No passado, eu precisaria que o usuário parasse de rodar, a fim de instalar o novo código.</p>
<p>Agora, no entanto, eu posso levantar a mudança no banco de dados enquanto o banco está funcionando, e os usuários estão executando o meu código com a edição padrão (ORA$BASE). Primeiro, como o DBA, eu preciso permitir que a conta DEMO use edições, e então eu preciso permitir que a conta DEMO veja e use a edição VERSION2. Além disso, para esta demonstração, vou deixar que a conta SCOTT veja e use VERSION2:</p>
<pre class="brush: plain;">SQL&gt; alter user demo
  2    enable editions;
User altered.

SQL&gt; grant use
  2    on edition version2
  3    to demo;
Grant succeeded.

SQL&gt; grant use
  2    on edition version2
  3    to scott;
Grant succeeded.</pre>
<p>A instrução ALTER USER permite que  a conta DEMO use edições dos códigos. Sem este GRANT, a conta DEMO seria capaz de ter apenas de ter uma cópia do código em vigor, em determinado momento, assim como na versão 7.0 até a versão 11.1 do Oracle Database. A instrução GRANT USE em seguida, permite que a conta DEMO e SCOTT vejam a edição VERSION2. Como a conta DEMO é habilitada para edição, ela será capaz de modificar a edição VERSION2 assim como alterar implementação de vários objetos, nesta edição, sem afetar outras edições. A conta SCOTT será capaz de usar apenas a edição deste VERSION2 &#8211; para definir a sua edição atual, na sua sessão de VERSION2 e ver os objetos como eles existem naquela edição.</p>
<p>Agora eu vou &#8220;patchear&#8221; a minha aplicação. Logando novamente com a conta DEMO, vou ver primeiro o que eu tenho no local após alterar a minha sessão de usar a edição VERSION2, como mostrado na Listagem 1.</p>
<p><strong>Listagem de código 1:</strong> Definindo a edição VERSION2 e selecionando procedures</p>
<pre class="brush: plain;">DEMO&gt; alter session
  2       set edition = version2;
Session altered. 

DEMO&gt; select object_name,
  2               object_type,
  3               status,
  4               edition_name
  5      from user_objects;

OBJECT_NAME      OBJECT_TYPE    STATUS    EDITION_NAME
-------------    -----------    ------    ------------
MY_PROCEDURE2    PROCEDURE      VALID     ORA$BASE
MY_PROCEDURE     PROCEDURE      VALID     ORA$BASE</pre>
<p>Então, agora, na edição VERSION2, eu tenho ambas unidades de PL/SQL (MY_PROCEDURE e MY_PROCEDURE2), mas como denota a coluna EDITION_NAME, eles são &#8220;herdadas&#8221; da ORA$BASE. A edição VERSION2 está apontando para a cópia em ORA$BASE, mas não é uma cópia física do código.</p>
<p>Digamos que eu tenha que corrigir dois bugs. Primeiro, eu tenho um bug na implementação de MY_PROCEDURE, e eu vou substituir esse código. Em segundo lugar, eu perdi um GRANT, quando estava fazendo deploy do meu aplicativo, o usuário SCOTT era pra ter o privilégio EXECUTE MY_PROCEDURE2, mas de alguma forma isso não aconteceu quando eu instalei a última aplicação. Eu vou começar atualizando o código:</p>
<pre class="brush: plain;">DEMO&gt; create or replace
  2      procedure my_procedure
  3      as
  4      begin
  5         dbms_output.put_line
  6         ( 'I am version 2.0' );
  7      end;
  8      /
Procedure created.

DEMO&gt; select object_name,
  2         edition_name
  3      from user_objects;

OBJECT_NAME      EDITION_NAME
-------------    ------------
MY_PROCEDURE2    ORA$BASE
MY_PROCEDURE     VERSION2</pre>
<p>Como você pode ver, eu ainda tenho apenas dois objetos, mas existem três objetos físicos lá, como você verá em seguida. Tenho MY_PROCEDURE2, que é herdado ORA$BASE, e eu tenho MY_PROCEDURE, que agora existe fisicamente na edição VERSION2. Isso é chamado de colocar em prática o código quando eu tenho uma cópia física na edição, eu atualizei o código naquela edição.</p>
<p>Usando um novo conjunto de views pra ver em todas as edições e final em <strong>_AE</strong> &#8211; Eu posso ver todo o estado do meu esquema DEMO. Eu consulto a view USER_OBJECTS_AE para OBJECT_NAME e EDITION_NAME:</p>
<pre class="brush: plain;">DEMO&gt; select object_name,
  2         edition_name
  3      from user_objects_AE;

OBJECT_NAME      EDITION_NAME
-------------    ------------
MY_PROCEDURE     ORA$BASE
MY_PROCEDURE2    ORA$BASE
MY_PROCEDURE     VERSION2</pre>
<p>Olhando para as diferentes edições, você pode ver que eu atualizei duas cópias físicas de MY_PROCEDURE agora: uma na edição padrão ORA$BASE e uma na nova edição VERSION2 que estou trabalhando. Agora vou aplicar o grant de EXECUTE para SCOTT:</p>
<pre class="brush: plain;">DEMO&gt; grant execute
  2      on my_procedure2
  3      to scott;
Grant succeeded.

DEMO&gt; select object_name,
  2          edition_name
  3       from user_objects;

OBJECT_NAME      EDITION_NAME
-------------    ------------
MY_PROCEDURE2    VERSION2
MY_PROCEDURE     VERSION2

DEMO&gt; select object_name,
  2         edition_name
  3       from user_objects_AE;

OBJECT_NAME      EDITION_NAME
-------------    ------------
MY_PROCEDURE2    ORA$BASE
MY_PROCEDURE     ORA$BASE
MY_PROCEDURE2    VERSION2
MY_PROCEDURE     VERSION2</pre>
<p>Se você olhar para USER_OBJECTS, verá que eu tenho as duas procedures, mas ambas já foram atualizadas na edição VERSION2. Ao conceder o grant de EXECUTE nas procedures MY_PROCEDURE2 para SCOTT, eu fiz uma versão física da stored procedure aparecer na edição VERSION2, e eu apliquei o grant para que a edição em isolamento, sem encontrar quaisquer problemas de concorrência (problemas de bloqueios / lock porque alguém estava rodando a procedure). Olhando a USER_OBJECTS_AE, você pode ver que há agora quatro objetos físicos, dois em cada edição.</p>
<p>Agora, quando eu executo a procedure MY_PROCEDURE2 na edição VERSION2, eu vejo</p>
<pre class="brush: plain;">DEMO&gt; SELECT SYS_CONTEXT
  2         ('userenv',
  3          'current_edition_name') sc
  4       FROM DUAL;

SC
----------------------
VERSION2

DEMO&gt; exec my_procedure2
I am version 2.0

PL/SQL procedure successfully completed.</pre>
<p>A versão 2.0 do código é executada.</p>
<p>Agora, simplesmente por conectar e depois usar o banco com edição padrão (ainda ORA$BASE), iremos ver</p>
<pre class="brush: plain;">DEMO&gt; connect demo/demo
Connected.

DEMO&gt; SELECT SYS_CONTEXT
  2         ('userenv',
  3          'current_edition_name') sc
  4      FROM DUAL;

SC
-----------------------
ORA$BASE

DEMO&gt; exec my_procedure2
I am version 1.0

PL/SQL procedure successfully completed.</pre>
<p>A versão 1.0 do código ainda está lá, e por padrão, ele será executado.</p>
<p>Além disso, para ver o efeito do privilégio EXECUTE que eu concedi ao SCOTT, eu posso conectar como SCOTT e tentar executar o procedimento armazenado MY_PROCEDURE2 na edição padrão e a edição VERSION2, como mostrado na Listagem 2.</p>
<p><strong>Listagem de código 2:</strong> Executando my_procedure2 em edições atuais e na VERSION2</p>
<pre class="brush: plain;">DEMO&gt; connect scott/tiger
Connected.

SCOTT&gt; SELECT SYS_CONTEXT
  2         ('userenv',
  3          'current_edition_name') sc
  4       FROM DUAL;

SC
-----------------------
ORA$BASE

SCOTT&gt; exec demo.my_procedure2
BEGIN demo.my_procedure2; END;

      *
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00201: identifier 'DEMO.MY_PROCEDURE2' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

SCOTT&gt; alter session
  2       set edition = version2;
Session altered.

SCOTT&gt; exec demo.my_procedure2
I am version 2.0

PL/SQL procedure successfully completed.
</pre>
<p>Como você pode ver, quando SCOTT está usando a edição ORA$BASE, ele não pode ver ou executar a stored procedure MY_PROCEDURE2. No entanto, na edição VERSION2 o usuário SCOTT pode ver e executar esse procedimento, por isso, quando a versão 2.0 do aplicativo entra em produção, SCOTT terá a capacidade de executar esse procedimento por padrão.</p>
<p>Neste ponto, estou pronto para liberar este código para a produção para ser utilizado pela comunidade geral. Um único, simples ALTER DATABASE feito pelo DBA define a edição atual do banco de dados para VERSION2, e esse código se torna imediatamente acessível.</p>
<p>Gostaria de salientar que esta é apenas a ponta do iceberg. Aqui eu tive que fazer operações relativamente comums: substituir algumas unidades PL/SQL existentes e mudar GRANTS em alguns objetos. Eu não tomei toda a aplicação da versão 1.0 para a versão 2.0, porque isso implicaria mudar tabelas e outros objetos que não são &#8220;editáveis&#8221;. Então, o que esta coluna discutiu até agora é uma necessidade muito comum de aplicar correções em um sistema, em que você precise aplicar alterações e mudanças de código e privilégio, mas não alterações físicas, como alterações de esquema como adicionar colunas, acrescentar índices ou alterar tabelas. Estarei abordando a forma de realizar essas tarefas na próxima coluna.</p>
<p>Até então, veja o Capítulo 19 &#8220;Oracle Database Advanced Application Developer’s Guide 11g Release 2 (11.2)&#8221; encontrado em <a href="www.bit.ly/1m2n0J">www.bit.ly/1m2n0J</a>.</p>
<p><em>Esta é uma tradução literal do artigo escrito por <a href="http://www.oracle.com/technology/oramag/oracle/10-jan/o10asktom.html">Tom Kyte na Oracle Magazine de Janeiro/2010</a> por <a href="http://glufke.net">glufke.net</a>.</em></p>
<p>Comente <a href="http://glufke.net/oracle/viewtopic.php?p=22501">AQUI</a></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2010/02/04/edition-based-redefinition/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

