<?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>Thu, 04 Feb 2010 21:06:12 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<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://blogs.oracle.com/stevenChan/images/oracle_db11g_clr.gif" 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>
		<item>
		<title>Converter datas do Excel para Oracle</title>
		<link>http://glufke.net/2009/12/08/converter-datas-do-excel-para-oracle/</link>
		<comments>http://glufke.net/2009/12/08/converter-datas-do-excel-para-oracle/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 18:04:29 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[Datas]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[Funções]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=177</guid>
		<description><![CDATA[MS Excel usa um formato de data chamado &#8220;Serial Date format&#8221; ao armazenar e lidar com datas e horas. A &#8220;Data serial&#8221; é calculada pegando o número de dias entre uma data qualquer e o dia 01/01/1900.
Por que isso é importante para um desenvoledor Oracle ? Se você está criando um documento em PL/SQL que [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://glufke.net/upload/upload_files/excel_oracle.JPG" title="excel_oracle" class="alignleft" width="134" height="135"  />MS Excel usa um formato de data chamado &#8220;Serial Date format&#8221; ao armazenar e lidar com datas e horas. A &#8220;Data serial&#8221; é calculada pegando o número de dias entre uma data qualquer e o dia 01/01/1900.</p>
<p>Por que isso é importante para um desenvoledor Oracle ? Se você está criando um documento em PL/SQL que será aberto no Excel, a data ficará incorreta a não ser que você converta antes para o padrão do Excel.</p>
<p>Felizmente, a formula de conversão de datas é muito simples. A seguinte função fará a conversão de uma data no Oracle para o padrão do Excel:</p>
<pre class="brush: sql;">CREATE OR REPLACE FUNCTION convertOracleToSerialDate(p_date DATE) RETURN NUMBER
IS
BEGIN
RETURN (p_date – TO_DATE(’01-JAN-1900?))+2;
END;
/</pre>
<p><span id="more-177"></span>
<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>Veja:</p>
<pre class="brush: plain;">SQL*Plus: Release 10.2.0.4.0 – Production on Mon Nov 23 22:31:54 2009

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.

Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 – Production

SQL> select convertOracleToSerialDate(’05-MAY-1968?) from dual;

CONVERTORACLETOSERIALDATE(’05-MAY-1968?)
—————————————-
24963</pre>
<p>Se passarmos o valor &#8220;05-MAY-1968&#8243; para a função acima, teremos como resopsta 24963. Agora, se colocarmos esse valor numa planilha excel e mudar o tipo da celula para DATA, teremos esse número convertido para &#8220;05/05/1968&#8243;, ou qualquer outro formato que você escolher.</p>
<p>O reverso também é possível. Caso desejamos converter do formato excel para oracle, usamos essa simples função:</p>
<pre class="brush: sql;">CREATE OR REPLACE FUNCTION convertSerialToOracleDate(p_serial_date NUMBER) RETURN DATE
IS
BEGIN
  RETURN (TO_DATE(’01-JAN-1900?) + p_serial_date)-2;
END;
/</pre>
<p>Exemplo:</p>
<pre class="brush: plain;">SQL*Plus: Release 10.2.0.4.0 – Production on Mon Nov 23 22:45:44 2009

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.

Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 – Production

SQL> select convertSerialToOracleDate(24963) from dual;

CONVERTSE
———
05-MAY-68

SQL></pre>
<p><em>Agradecimentos a Jason Bennett pelas dicas acima.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2009/12/08/converter-datas-do-excel-para-oracle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Aplicativos Oracle para iPhone</title>
		<link>http://glufke.net/2009/11/18/aplicativos-oracle-para-iphone/</link>
		<comments>http://glufke.net/2009/11/18/aplicativos-oracle-para-iphone/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 19:57:07 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[ERP]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Oracle R12]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=162</guid>
		<description><![CDATA[
Oracle Business Indicators é um aplicativo de B.I. que provê informações em tempo real, com acesso seguro sobre performance no iPhone.

 Oracle Business Approvals for Managers permite que gerentes e executivos revisem tarefas chaves, acessem relatórios de B.I., tomem decisões e levem imediatamente as ações ao ambiente em modo seguro.
Oracle iReceipts é uma aplicação que [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://glufke.net/oracle/uploads/oracle_iphone.PNG" alt="Oracle iPhone Apps" /></p>
<p><a href="http://itunes.apple.com/us/app/oracle-business-indicators/id284793704?mt=8"><strong>Oracle Business Indicators</strong></a> é um aplicativo de B.I. que provê informações em tempo real, com acesso seguro sobre performance no iPhone.</p>
<p><img class="alignleft" title="Managers" src="http://blogs.oracle.com/stevenChan/managers.jpg" alt="" width="240" height="360" /></p>
<p><strong><a href="http://itunes.apple.com/us/app/oracle-business-approvals-for/id294535403?mt=8"> Oracle Business Approvals for Managers</a></strong> permite que gerentes e executivos revisem tarefas chaves, acessem relatórios de B.I., tomem decisões e levem imediatamente as ações ao ambiente em modo seguro.</p>
<p><strong><a href="http://itunes.apple.com/us/app/oracle-ireceipts/id333581170?mt=8">Oracle iReceipts</a> </strong>é uma aplicação que é parte do Oracle PeopleSoft Expenses, que permite aos usuários criar e submeter despesas para transações de caixa em tempo real..</p>
<p><strong><a href="http://itunes.apple.com/us/app/oracle-mobile-sales-assistant/id296929975?mt=8">Oracle Mobile Sales Assistant</a></strong> é uma aplicação CRM que trás informação em tempo real segura que sua emprea precisa no aparelho móvel. Tarefas frequentes, colaboração com colegas e compradores, fechar negócios na estrada.</p>
<p><strong><a href="http://itunes.apple.com/us/app/oracle-mobile-sales-forecast/id295991142?mt=8">Oracle Mobile Sales Forecast</a></strong> é um aplicativo fácil de usar que mostra em tempo real uma visibilidade de oportunidade para organização.</p>
<p><strong><a href="http://itunes.apple.com/us/app/oracle-enterprise-asset-management/id310120136?mt=8">Oracle Enterprise Asset Maintenance Workbench</a></strong> é um aplicativo que ajuda o departamento de manutenção a aumentar sua produtividade. A aplicação ajudará os engenheiros de campo e trabalhadores a tirar vantagem do GPS que o iPhone possui.<span id="more-162"></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><a href="http://itunes.apple.com/us/app/oracle-business-approvals-for/id295494515?mt=8"><strong>Oracle Business Approvals for Sales Managers</strong></a> permite que executivos na área de vendas realizem tarefas chave, acessem informações relevantes ao negócio e visualizem relatório afim de tomar decisões em minutos onde estiver.</p>
<p><img class="aligncenter" title="iPhone x Oracle" src="http://blogs.oracle.com/stevenChan/indicators.jpg" alt="" width="360" height="240" /></p>
<p>Se você está interessado em desenvolver aplicativos para o iPhone usando Oracle jDeveloper, veja <a title="jDeveloper and iPhone" href="http://www.oracle.com/technology/pub/articles/huang-iphone.html" target="_blank">esse artigo</a></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2009/11/18/aplicativos-oracle-para-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PLAN_TABLE faz aniversário de 21 anos em 19-out-2009</title>
		<link>http://glufke.net/2009/10/13/plan_table-faz-aniversario-de-21-anos-em-19-out-2009/</link>
		<comments>http://glufke.net/2009/10/13/plan_table-faz-aniversario-de-21-anos-em-19-out-2009/#comments</comments>
		<pubDate>Tue, 13 Oct 2009 17:00:35 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Curiosidade]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=40</guid>
		<description><![CDATA[Pois é isso mesmo! A querida tabela do ORACLE que nos mostra o plano de execução dos SQLs hoje completa 21 anos!
Hoje eu fui olhar um plano de execução e me deparei com a seguinte mensagem:
SET AUTOTRACE ON
SELECT bla bla bla...

Execution Plan
----------------------------------------------------------

--------------------------------------------------------------
&#124; Id  &#124; Operation          [...]]]></description>
			<content:encoded><![CDATA[<p>Pois é isso mesmo! A querida tabela do ORACLE que nos mostra o plano de execução dos SQLs hoje completa 21 anos!<br />
Hoje eu fui olhar um plano de execução e me deparei com a seguinte mensagem:</p>
<pre class="brush: plain;">SET AUTOTRACE ON
SELECT bla bla bla...

Execution Plan
----------------------------------------------------------

--------------------------------------------------------------
| Id  | Operation          | Name       | Rows  | Cost (%CPU)|
--------------------------------------------------------------
|   0 | SELECT STATEMENT   |            |     1 |   102   (0)|
|   1 |  SORT AGGREGATE    |            |     1 |            |
|   2 |   TABLE ACCESS FULL| TABELA     |  4322 |   102   (0)|
--------------------------------------------------------------

Note
-----
   - 'PLAN_TABLE' is old version</pre>
<p>PLAN_TABLE is old version ???<span id="more-40"></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>Olhei no script de criação da nova PLAN_TABLE e descobri nos comentários a data de cada modificação: 19 de Outubro de 1988 !</p>
<pre class="brush: plain;">
rem
rem $Header: utlxplan.sql 29-oct-2001.20:28:58 mzait Exp $ xplainpl.sql
rem
Rem Copyright (c) 1988, 2001, Oracle Corporation.  All rights reserved.
Rem NAME
REM    UTLXPLAN.SQL
Rem  FUNCTION
Rem  NOTES
Rem  MODIFIED
Rem     mzait      10/26/01  - add keys and filter predicates to the plan table
Rem     ddas       05/05/00  - increase length of options column
Rem     ddas       04/17/00  - add CPU, I/O cost, temp_space columns
Rem     mzait      02/19/98 -  add distribution method column
Rem     ddas       05/17/96 -  change search_columns to number
Rem     achaudhr   07/23/95 -  PTI: Add columns partition_{start, stop, id}
Rem     glumpkin   08/25/94 -  new optimizer fields
Rem     jcohen     11/05/93 -  merge changes from branch 1.1.710.1 - 9/24
Rem     jcohen     09/24/93 - #163783 add optimizer column
Rem     glumpkin   10/25/92 -  Renamed from XPLAINPL.SQL
Rem     jcohen     05/22/92 - #79645 - set node width to 128 (M_XDBI in gendef)
Rem     rlim       04/29/91 -         change char to varchar2
Rem   Peeler     10/19/88 - Creation
Rem
Rem This is the format for the table that is used by the EXPLAIN PLAN
Rem statement.  The explain statement requires the presence of this
Rem table in order to store the descriptions of the row sources.

create table PLAN_TABLE (
	statement_id 	varchar2(30),
	timestamp    	date,
	remarks      	varchar2(80),
	operation    	varchar2(30),
	options       	varchar2(255),
	object_node  	varchar2(128),
	object_owner 	varchar2(30),
	object_name  	varchar2(30),
	object_instance numeric,
	object_type     varchar2(30),
	optimizer       varchar2(255),
	search_columns  number,
	id		numeric,
	parent_id	numeric,
	position	numeric,
	cost		numeric,
	cardinality	numeric,
	bytes		numeric,
	other_tag       varchar2(255),
	partition_start varchar2(255),
        partition_stop  varchar2(255),
        partition_id    numeric,
	other		long,
	distribution    varchar2(30),
	cpu_cost	numeric,
	io_cost		numeric,
	temp_space	numeric,
        access_predicates varchar2(4000),
        filter_predicates varchar2(4000));
</pre>
<p>Atingiu a maioridade! <img src='http://glufke.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />   Feliz aniversário PLAN_TABLE!</p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2009/10/13/plan_table-faz-aniversario-de-21-anos-em-19-out-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Colunas Virtuais no 11g &#8211; Parte 2</title>
		<link>http://glufke.net/2009/08/17/colunas-virtuais-no-11g-parte-2/</link>
		<comments>http://glufke.net/2009/08/17/colunas-virtuais-no-11g-parte-2/#comments</comments>
		<pubDate>Tue, 18 Aug 2009 02:43:22 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[Coluna Virtual]]></category>
		<category><![CDATA[Oracle 11g]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=101</guid>
		<description><![CDATA[Colunas Virtuais no 11g &#8211; Parte 2 &#8211; Índices e Constraints
Continuando o artigo sobre colunas virtuais no Oracle 11g, veremos outras possibilidades do uso dessa feature.
Se tentarmos inserir dados que resultem em uma coluna virtual duplicada, podemos esperar uma violação de Unique Constraint:
SQL> INSERT INTO t (n1, n2) VALUES (10, 20);
INSERT INTO t (n1, n2) [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Colunas Virtuais no 11g &#8211; Parte 2 &#8211; Índices e Constraints</strong></p>
<p>Continuando o artigo sobre colunas virtuais no Oracle 11g, veremos outras possibilidades do uso dessa feature.</p>
<p>Se tentarmos inserir dados que resultem em uma coluna virtual duplicada, podemos esperar uma violação de Unique Constraint:<span id="more-101"></span></p>
<pre class="brush: sql;">SQL> INSERT INTO t (n1, n2) VALUES (10, 20);
INSERT INTO t (n1, n2) VALUES (10, 20)
*
ERROR at line 1:
ORA-00001: unique constraint (SCOTT.T_PK) violated</pre>
<p>Como vimos, gerou o exception ORA-00001.</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>Em seguida, veremos que, como podemos criar uma chave primária em uma coluna virtual, também podemos referenciá-la a uma constraint Foreign Key. No próximo exemplo, vamos criar uma tabela filha com uma foreign key para a coluna virtual N3.</p>
<pre class="brush: sql;">SQL> CREATE TABLE t_child
  2  ( n3 INT
  3  , CONSTRAINT tc_fk
  4       FOREIGN KEY  (n3)
  5       REFERENCES  t(n3)
  6  );

Table created.</pre>
<p>Iremos agora inserir alguns valores válidos e inválidos:</p>
<pre class="brush: sql;">SQL> INSERT INTO t_child VALUES (30);

1 row created.

SQL> INSERT INTO t_child VALUES (40);
INSERT INTO t_child VALUES (40)
*
ERROR at line 1:
ORA-02291: integrity constraint (SCOTT.TC_FK) violated - parent key not found</pre>
<p><a href="http://glufke.net/2009/07/31/colunas-virtuais-no-oracle-11g/">Colunas Virtuais no 11g &#8211; Parte 1 &#8211; Introdução</a><br />
Colunas Virtuais no 11g &#8211; Parte 2 &#8211; Índices e Constraints</p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2009/08/17/colunas-virtuais-no-11g-parte-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Colunas Virtuais no 11g &#8211; Parte 1</title>
		<link>http://glufke.net/2009/07/31/colunas-virtuais-no-oracle-11g/</link>
		<comments>http://glufke.net/2009/07/31/colunas-virtuais-no-oracle-11g/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 19:54:06 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[Coluna Virtual]]></category>
		<category><![CDATA[Oracle 11g]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=99</guid>
		<description><![CDATA[Oracle suportou expressões armazenadas por muitos anos, em views e índices baseados em função. Mais principalmente, são as views que nos permitem armazenar e modularisar expressões calculadas baseados em outras colunas da tabela. 
Em versões mais recentes (a partir do 8i), temos como indexar as colunas baseados em função. (Function based indexes). Agora, a partir [...]]]></description>
			<content:encoded><![CDATA[<p>Oracle suportou expressões armazenadas por muitos anos, em views e índices baseados em função. Mais principalmente, são as views que nos permitem armazenar e modularisar expressões calculadas baseados em outras colunas da tabela. </p>
<p>Em versões mais recentes (a partir do 8i), temos como indexar as colunas baseados em função. (Function based indexes). Agora, a partir da versão 11g, o banco Oracle nos permite também armazenar expressões diretamente nas tabelas como colunas virtuais.</p>
<p>Como veremos neste artigo, colunas virtuais são mais flexíveis que as outras alternativas citadas. Vamos examinar seu uso básico e também considerar alguns outros aspectos dessa nova feature.<span id="more-99"></span></p>
<p><strong>CRIANDO UMA COLUNA VIRTUAL</strong></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>Começaremos criando uma simples tabela com uma única coluna virtual</p>
<pre class="brush: sql;">SQL> CREATE TABLE t
  2  ( n1 INT
  3  , n2 INT
  4  , n3 INT GENERATED ALWAYS AS (n1 + n2) VIRTUAL
  5  );

Table created.</pre>
<p>Vemos que uma coluna virtual é gerada de uma simples expressão envolvendo as outras colunas da tabela. A palavra chave VIRTUAL é opcional. Foi incluída pelo que a Oracle chama da &#8220;Clareza sintática&#8221;.</p>
<p>Colunas virutais não são armazenadas em disco. Elas são geradas em tempo de execução usando as expressões associadas (em nosso exemplo, N1 + N2). Existe algumas implicações na forma de inserir dados em tabelas que usam colunas virtuais:</p>
<pre class="brush: sql;">SQL> INSERT INTO t VALUES (10, 20, 30);
INSERT INTO t VALUES (10, 20, 30)
            *
ERROR at line 1:
ORA-54013: INSERT operation disallowed on virtual columns</pre>
<p>Outra forma que não pode ser feita:</p>
<pre class="brush: sql;">SQL> INSERT INTO t VALUES (10, 20);
INSERT INTO t VALUES (10, 20)
            *
ERROR at line 1:
ORA-00947: not enough values</pre>
<p>Tirando o fato que não podemos inserir ou alterar as colunas virtuais, elas ainda assim são consideradas parte da lista de colunas. Isso significa portanto, que precisamos referenciar as colunas físicas explicitamente nos comandos INSERT, como abaixo:</p>
<pre class="brush: sql;">SQL> INSERT INTO t (n1, n2) VALUES (10, 20);

1 row created.</pre>
<p>É claro que a prática acima já faz parte das melhores práticas que todo dsenevolvedor deve ter. Agora que temos dados dentro do nosso exemplo, podemos consultar a coluna virtual:</p>
<pre class="brush: sql;">SQL> SELECT * FROM t;

        N1         N2         N3
---------- ---------- ----------
        10         20         30

1 row selected.</pre>
<p>Nossa expressão é montada em tempo de execução e nos dá a saída acima!</p>
<p>Colunas Virtuais no 11g &#8211; Parte 1 &#8211; Introdução<br />
<a href="http://glufke.net/2009/08/17/colunas-virtuais-no-11g-parte-2/">Colunas Virtuais no 11g &#8211; Parte 2 &#8211; Índices e Constraints</a></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2009/07/31/colunas-virtuais-no-oracle-11g/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fazer o Forms abrir um novo Form ao perder conexão, é possível?</title>
		<link>http://glufke.net/2009/07/30/fazer-o-forms-abrir-um-novo-form-ao-perder-conexao-e-possivel/</link>
		<comments>http://glufke.net/2009/07/30/fazer-o-forms-abrir-um-novo-form-ao-perder-conexao-e-possivel/#comments</comments>
		<pubDate>Thu, 30 Jul 2009 13:02:32 +0000</pubDate>
		<dc:creator>Rodrigo Valentim</dc:creator>
				<category><![CDATA[Oracle Forms]]></category>
		<category><![CDATA[conexão]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=98</guid>
		<description><![CDATA[Sim, é possível! Porém, não serve para todas as aplicações&#8230; Essa rotina seria mais usada em alguns form que fazem integração entre os sistemas, etc&#8230;
Digamos que você tenha um software responsável pelo controle de créditos telefônicos em um banco separado da sua aplicação principal.
o cliente paga um valor, esse valor é creditado e através de [...]]]></description>
			<content:encoded><![CDATA[<p>Sim, é possível! Porém, não serve para todas as aplicações&#8230; Essa rotina seria mais usada em alguns form que fazem integração entre os sistemas, etc&#8230;<br />
Digamos que você tenha um software responsável pelo controle de créditos telefônicos em um banco separado da sua aplicação principal.</p>
<p>o cliente paga um valor, esse valor é creditado e através de um usuário e senha você consegue usar ligar normalmente até acabar os créditos.</p>
<p>Com isso, no meu sistema principal, preciso ter a informação do quanto de crédito já foi utilizado ou algo parecido, então, a cada ligação, faço o débito da conta do cliente.</p>
<p>Como não tenho uma integração direta entre as aplicações, vou precisar de um Robô que faça a leitura de um lado e jogue no outro, porém, por algum motivo, esse robô perdeu a conexão e ninguém foi avisado, então, teremos que ficar nos preocupando vendo se o robô está sempre ativo, etc&#8230;</p>
<p>Vamos lá!<br />
<span id="more-98"></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>Preciso criar 3 parâmetros para receber os valores de usuário, senha, banco. Depois de criado e alimentado esses parâmetros (se é um robô, usuário e senha ficam fixados nesses parâmetros. caso desejem, podem passar esses valores por linha de comando como vou mostrar mais pra frente).<br />
Preciso então criar uma trigger WHEN-NEW-FORM-INSTANCE e então atribuir esses valores ao seu bloco de login.<br />
ex:</p>
<pre class="brush: sql;">
IF :parameter.usuario IS NOT NULL
AND :parameter.senha IS NOT NULL
AND :parameter.banco IS NOT NULL THEN
  :BlLogin.Usuario := UPPER(:parameter.usuario) ;
  :BlLogin.Senha := UPPER(:parameter.senha);
  :BlLogin.Banco := UPPER(:parameter.banco);
  EXECUTE_TRIGGER( 'On-Logon' ) /* Chamo a trigger ON-LOGON */
END IF;
</pre>
<p>Próximo passo é implementar a trigger ON-LOGON.</p>
<pre class="brush: sql;">
BEGIN
  Logon( :BlLogin.Usuario, :BlLogin.Senha || '@' || :BlLogin.Banco, False );
  -- Este procedimento está sendo chamado duas vezes a cada Logon
  IF vConectado IS NULL THEN
    IF Form_Failure Then
      vConectado := False;
    ELSE
      vConectado := True;
    END IF;
  END IF;
END;
</pre>
<p>No próximo passo vamos implementar a trigger que irá nos ajudar a identificar os tipos de erro, é a ON-ERROR.<br />
Todo erro existente no forms, passa por ela para que seja possível um tratamento&#8230; se não tem nada ali, o erro aparece normalmente&#8230;</p>
<pre class="brush: sql;">
--Faixa de erros que se referem a perda de conexão,
--caso alguém saiba mais alguns, pode me enviar que faço inclusão aqui
IF DBMS_ERROR_CODE IN (-03114,-03113,-00028,-01012,-01041) THEN
  vTimer := Find_Timer( 'RELOG' );
  --Caso exista algum timer com nome de RELOG,
  --deleto o time para recriar o mesmo
  If Not Id_Null( vTimer ) Then
    Delete_Timer( vTimer );
  END IF;
  --Criando timer que irá disparar rotina de reconectar
  vTimer := Create_Timer( 'RELOG', 1500, Repeat );
END IF;
</pre>
<p>Agora que tudo foi criado e tratado, resta apenas a rotina final e mais importante&#8230; que é fazer a rotina para quando o timer disparar, fazer a abertura do novo form por linha de comando&#8230;</p>
<p>então, na trigger WHEN-TIMER-EXPIRED, vamos ter o seguinte código.</p>
<pre class="brush: sql;">
if Get_Application_Property( Timer_Name ) = 'RELOG' Then
  If :parameter.usuario Is Not Null
  and :parameter.senha Is Not Null
  and :parameter.banco Is Not Null Then
    --Preencho a variável com o valor da chave ORACLE_HOME
    Tool_Env.Getvar('ORACLE_HOME', v);
    --Pego o nome do modulo em execução
    vModulo := UPPER( GET_FORM_PROPERTY( GET_APPLICATION_PROPERTY( CURRENT_FORM_NAME), FILE_NAME  ));
    --Monto aqui a linha de comando que irá abrir o novo form
    v := v|| '\bin\ifrun60.exe ' || vModulo || ' usuario=' || :parameter.login || ' banco='|| :parameter.banco || ' senha=' || :parameter.senha;
    --Faço a abertura do mesmo
    Win_API_Shell.WinExec( v , WIN_API.SW_SHOWMINIMIZED, false);
    WIN_API_UTILITY.SLEEP(2000);/*Delay de 2 segundos*/
    --fecho o form que deu erro de conexão
    exit_form(no_validate);
  End If;
End If;
</pre>
<p>Pronto, Dessa forma, não preciso me preocupar tanto com a rotina do robô responsável pela integração&#8230; se a conexão parar, ele mesmo identifica isso, abre novo form e tudo resolvido! <img src='http://glufke.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Essa solução ajuda para aqueles casos em que sua empresa trabalha em RAC, pois, se uma instância cair, automaticamente ele fecha a que deu erro e abre outra na instância que ficou ativa.</p>
<p><em>Rodrigo Valentim é Analista de Sistemas Oracle Developer</em><br />
<a href="http://www.rodrigovalentim.com/blog">http://www.rodrigovalentim.com/blog</a></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2009/07/30/fazer-o-forms-abrir-um-novo-form-ao-perder-conexao-e-possivel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trabalhando com Strings no Oracle</title>
		<link>http://glufke.net/2009/06/03/trabalhando-com-strings-no-oracle/</link>
		<comments>http://glufke.net/2009/06/03/trabalhando-com-strings-no-oracle/#comments</comments>
		<pubDate>Thu, 04 Jun 2009 01:36:11 +0000</pubDate>
		<dc:creator>Rodrigo Valentim</dc:creator>
				<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[String]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=96</guid>
		<description><![CDATA[Vou agora tentar mostrar como trabalha com string no Oracle&#8230; Venho acompanhando alguns Foruns de Desenvolvimento e sempre estou me deparando com questões sobre o correto uso de funções para trabalhar com String&#8230; 

Concatenando 2 Strings
Colocando a primeira letra do texto como Maiúscula
Transformando o texto em texto Minúsculo e Maiúsculo
Convertendo letras em códigos ASCII
Localizando a [...]]]></description>
			<content:encoded><![CDATA[<p>Vou agora tentar mostrar como trabalha com string no Oracle&#8230; Venho acompanhando alguns Foruns de Desenvolvimento e sempre estou me deparando com questões sobre o correto uso de funções para trabalhar com String&#8230; </p>
<ol>
<li>Concatenando 2 Strings</li>
<li>Colocando a primeira letra do texto como Maiúscula</li>
<li>Transformando o texto em texto Minúsculo e Maiúsculo</li>
<li>Convertendo letras em códigos ASCII</li>
<li>Localizando a posição uma string no meio do texto</li>
<li>Atribuindo dígitos no final e/ou no inicio do texto</li>
<li>Removendo espaços no inicio e/ou fim do texto</li>
<li>Como inverter o texto</li>
<li>Substituindo Strings por outras Strings</li>
<li>Cortando o conteúdo do texto</li>
<li>Descobrindo o tamanho da string</li>
<li>Retornando colunas com valor não nulo</li>
<li>Exemplo da utilização de algumas funções
<ul>
<li>Pesquisando em uma string por um digito e exibindo o resto da string pegando como base esse digito localizado.</li>
<li>Repartindo uma string e inserindo um valor no meio.</li>
</ul>
</li>
</ol>
<p><span id="more-96"></span>
<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>1. Concatenando 2 strings</strong></p>
<p>Existem duas formas de trabalhar concatenando strings.  CONCAT e PIPE<br />
Concat: </p>
<pre class="brush: sql;">SQL: SELECT CONCAT ('Rodrigo ', 'Valentim') FROM dual;
CONCAT('RODRIGO','VALENTIM')
----------------------------
Rodrigo Valentim
</pre>
<p>Usando PIPE: </p>
<pre class="brush: sql;">SQL: SELECT 'Rodrigo '||'Valentim' FROM dual;
'RODRIGO'||'VALENTIM'
---------------------
Rodrigo Valentim
</pre>
<p><strong>2. Colocando a primeira letra do texto como Maiúscula.<br />
</strong>
<pre class="brush: sql;">SQL: SELECT INITCAP('rodrigo valentim') FROM dual;
INITCAP('RODRIGOVALENTIM')
--------------------------
Rodrigo Valentim
</pre>
<p><strong>3. Alternar entre Maiúscula e Minúscula</strong></p>
<pre class="brush: sql;">SQL: SELECT LOWER('RODRIGO ')||UPPER('valentim') FROM dual;
LOWER('RODRIGO')||UPPER('VALEN
------------------------------
rodrigo VALENTIM
</pre>
<p><strong>4. Convertendo letras em códigos ASCII</strong></p>
<pre class="brush: sql;">SQL: SELECT ASCII('A') FROM dual;
ASCII('A')
----------
65

SQL: SELECT ASCII('Z') FROM dual;
ASCII('Z')
----------
90

SQL: SELECT ASCII('a') FROM dual;
ASCII('A')
----------
97

SQL: SELECT ASCII('z') FROM dual;
ASCII('Z')
----------
122

SQL: SELECT ASCII(' ') FROM dual;
ASCII('')
----------
32
</pre>
<p><strong>5. Localizando a posição uma string no meio do texto</strong><br />
Com a função INSTR, é possível localizar caracteres dentro de um texto, de forma normal ou inversa.</p>
<p>Localizando a primeira posição da string no texto</p>
<pre class="brush: sql;">
SQL: SELECT INSTR('Exemplo de como realizar pesquisa em uma string', 'r', 1, 1) localiza_1 from dual;
LOCALIZA_1
----------
17
</pre>
<p>Localizando a segunda posição da string no texto</p>
<pre class="brush: sql;">SQL: SELECT INSTR('Exemplo de como realizar pesquisa em uma string', 'r', 1, 2) localiza_2 from dual;
LOCALIZA_2
----------
24
</pre>
<p>Localizando a terceira posição da string no texto</p>
<pre class="brush: sql;">SQL: SELECT INSTR('Exemplo de como realizar pesquisa em uma string', 'r', 1, 3) localiza_3 from dual;
LOCALIZA_3
----------
44
</pre>
<p>Localizando a quarta posição da string no texto, como não existe mais de 3 letras r no texto, ele retorna zero.</p>
<pre class="brush: sql;">SQL: SELECT INSTR('Exemplo de como realizar pesquisa em uma string', 'r', 1, 4) localiza_4 from dual;
LOCALIZA_4
----------
0
</pre>
<p>Para realizar a mesma pesquisa so que de ordem inversa, basta usar o valor negativo na função</p>
<pre class="brush: sql;">SQL: SELECT INSTR('Exemplo de como realizar pesquisa em uma string', 'r', -1, 1) localiza_1 from dual;
LOCALIZA_1
----------
44
</pre>
<p>Nestas condições, ele me retorna a primeira posição na ordem inversa, ou seja, a última.</p>
<p><strong>6. Atribuindo dígitos no final e/ou no inicio do texto.</strong><br />
Temos como usar o LPAD para inserir digitos na esquerda e RPAD para inserir digitos na direita.<br />
LPAD:</p>
<pre class="brush: sql;">SQL: SELECT LPAD('Rodrigo Valentim', 25, 'x') FROM dual;
LPAD('RODRIGOVALENTIM',25,'X')
------------------------------
xxxxxxxxxRodrigo Valentim
</pre>
<p>RPAD:
<pre class="brush: sql;">SQL: SELECT RPAD('Rodrigo Valentim', 25, 'x') FROM dual;
RPAD('RODRIGOVALENTIM',25,'X')
------------------------------
Rodrigo Valentimxxxxxxxxx
</pre>
<p><strong>7.Removendo dígitos do inicio ou do fim ou de ambos do texto</strong><br />
Podendo ser espaços em branco ou letras (TRIM só remove espaços em branco).<br />
LTRIM:</p>
<pre class="brush: sql;">SQL: SELECT '*' || LTRIM('               Rodrigo Valentim               ') || '*' FROM dual;
'*'||LTRIM('RODRIGOVALENTIM')|
---------------------------------
*Rodrigo Valentim               *
</pre>
<p>RTRIM:</p>
<pre class="brush: sql;">SQL: SELECT '*' || RTRIM('               Rodrigo Valentim               ') || '*' FROM dual;
'*'||RTRIM('RODRIGOVALENTIM')|
---------------------------------
*               Rodrigo Valentim*
</pre>
<p>TRIM:
<pre class="brush: sql;">SQL: SELECT '*'||TRIM('   Rodrigo Valentim   ')||'*' FROM dual;
'*'||TRIM('RODRIGOVALENTIM')||
------------------------------
*Rodrigo Valentim*
</pre>
<p><strong>8. Como inverter o conteúdo em uma string</strong></p>
<pre class="brush: sql;">SQL: select reverse('MITNELAV OGIRDOR') from dual;
REVERSE('MITNELAVOGIRDOR')
--------------------------
RODRIGO VALENTIM
</pre>
<p><strong>9. Substituindo Strings por outras Strings</strong><br />
Com a Função Replace é possível substituir o conjunto de caracteres por outro, no exemplo abaixo, ele vai alterar o valor DE para A</p>
<pre class="brush: sql;">SQL: SELECT REPLACE('ABCDE','DE','A') FROM dual;
REPLACE('ABCDE','DE','A')
-------------------------
ABCA
</pre>
<p><strong>10. Cortando conteúdo do texto com SUBSTR<br />
</strong>Com essa função, é possível exibir somente partes do texto. No exemplo abaixo, digo que quero iniciar meu texto da posição 3 e andar mais 9 dígitos.</p>
<pre class="brush: sql;">SQL: SELECT SUBSTR('Rodrigo Valentim', 3, 9) FIRST_FOUR FROM dual;
FIRST_FOUR
----------
drigo Val
</pre>
<p><strong>11. Descobrindo o tamanho da string com a função LENGTH.</strong></p>
<pre class="brush: sql;">SQL: SELECT LENGTH('Rodrigo Valentim') FROM dual;
LENGTH('RODRIGOVALENTIM')
-------------------------
16
</pre>
<p><strong>12. Retornando colunas com valor não nulo</strong><br />
Com a função COALESCE. Ela pesquisa entre as colunas passada e retorna o primeiro valor não nulo que foi encontrado.</p>
<pre class="brush: sql;">SQL: create table artigo_coalesce(col1 varchar2(10), col2 varchar2(10), col3 varchar2(10), col4 varchar2(10));
Table created
</pre>
<pre class="brush: sql;">
SQL: insert into artigo_coalesce values (NULL, NULL, 'C','D');
1 row inserted
SQL: insert into artigo_coalesce values (NULL, 'A', 'C','D');
1 row inserted
SQL: insert into artigo_coalesce values ('B', 'A', 'C','D');
1 row inserted
SQL: insert into artigo_coalesce values (NULL, 'D', NULL,'A');
1 row inserted
SQL: SELECT COALESCE(COL1, COL2, COL3, COL4) FROM artigo_coalesce;
COALESCE(COL1,COL2,COL3,COL4)
-----------------------------
C
A
B
D
</pre>
<p><strong>13.1 Pesquisando em uma string por um digito e exibindo o resto</strong><br />
Pesquisando em uma string por um digito e exibindo o resto da string pegando como base esse digito localizado. Bom, primeiro preciso saber qual a posição que preciso começar, neste caso, vou iniciar pela &#8216;\&#8217;. Vou pesquisar do fim para o inicio e localizar neste caso, a localização da ultima barra.</p>
<pre class="brush: sql;">SQL: select INSTR('c:\arquivo\arquivo.txt', '\', -1, 1) from dual;
INSTR('C:\ARQUIVO\ARQUIVO.TXT'
------------------------------
11
</pre>
<p>Depois de localizar, preciso então usar ela como ponto inicial e ir até o final da string completa. Como não sei o tamanho total da minha string, pois, pode ser que ela mude algum dia, vou usar a função LENGTH que me retornará o tamanho total.</p>
<pre class="brush: sql;">SQL: SELECT substr('c:\arquivo\arquivo.txt',INSTR('c:\arquivo\arquivo.txt', '\', -1, 1) ,length('c:\arquivo\arquivo.txt')) from dual;
SUBSTR('C:\ARQUIVO\ARQUIVO.TXT
------------------------------
\arquivo.txt
</pre>
<p>Depois de localizar o inicio e fim da minha string através das funções acima, preciso ajustar para que a barra não saia&#8230; a função SUBSTR está iniciando da posição 11 e indo até a posição final da string, por isso está me retornando a barra, então, preciso somar + 1 ao retorno da localização da &#8216;\&#8217;, para então ela não aparecer no meu resutlado.</p>
<pre class="brush: sql;">SQL: SELECT substr('c:\arquivo\arquivo.txt',INSTR('c:\arquivo\arquivo.txt', '\', -1, 1) + 1 ,length('c:\arquivo\arquivo.txt')) from dual;
SUBSTR('C:\ARQUIVO\ARQUIVO.TXT
------------------------------
arquivo.txt
</pre>
<p>Então, andando da posição 12 até a ultima posição, consigo através do substr cortar parte do texto e extrair somente o que desejo.</p>
<p><strong>13.2 Pegar uma String e inserir um valor no meio dela</strong><br />
Eu tenho uma String chamada &#8216;Existe Perfeita?&#8217; e quero inserir o Lógica no meio dela utilizando uma query&#8230;</p>
<p>Pegando trechos do ultimo exemplo (13.1) vamos montar nossa query e assim ter nosso retorno&#8230;</p>
<p>Primeiro preciso pegar o espaço em branco, levando em consideração que é o meio da string.</p>
<pre class="brush: sql;">SQL: SELECT instr('Existe Perfeita?',' ') FROM dual;
INSTR('EXISTEPERFEITA?','')
---------------------------
7
</pre>
<p>Agora vamos cortar somente o inicio da string, com SUBSTR vamos pegar da posição 1 até o espaço em branco (posição 7)</p>
<pre class="brush: sql;">SQL: SELECT substr('Existe Perfeita?',1,instr('Existe Perfeita?',' ')) FROM dual;
SUBSTR('EXISTEPERFEITA?',1,INS
------------------------------
Existe
</pre>
<p>Temos então somente o Existe. Vamos então inserir (concatenar) o texto que queremos e ter como resultado o Existe Lógica</p>
<pre class="brush: sql;">SQL: SELECT substr('Existe Perfeita?',1,instr('Existe Perfeita?',' '))||'Lógica' FROM dual;
SUBSTR('EXISTEPERFEITA?',1,INS
------------------------------
Existe Lógica
</pre>
<p>Agora falta inserir a parte final&#8230; vamos então pegar a String inicial e então cortar a parte do meio até o fim. Já sei qual o meio e para descobrir o fim é só usar a função LENGTH e então temos o resultado que queremos.</p>
<pre class="brush: sql;">SQL: SELECT substr('Existe Perfeita?',1,instr('Existe Perfeita?',' '))||'Logica'||substr('Existe Perfeita?',instr('Existe Perfeita?',' '),length('Existe Perfeita?')) "Existe?" FROM dual;
Existe?
-----------------------
Existe Logica Perfeita?
</pre>
<p>Acredito que tenha conseguido passar um pouco do que é trabalhar com Strings no Oracle&#8230;</p>
<p>Espero ter esclarecido algumas dúvidas e as que não foram esclarecidas, podem me procurar que eu vou tentar ajudar!</p>
<p>Abraço e até a próxima.</p>
<p><em>Rodrigo Valentim é Analista de Sistemas Oracle Developer</em><br />
<a href="http://www.rodrigovalentim.com/blog">http://www.rodrigovalentim.com/blog</a></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2009/06/03/trabalhando-com-strings-no-oracle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Execução ordenada nas triggers</title>
		<link>http://glufke.net/2009/05/14/execucao-ordenada-nas-triggers_oracle11g/</link>
		<comments>http://glufke.net/2009/05/14/execucao-ordenada-nas-triggers_oracle11g/#comments</comments>
		<pubDate>Thu, 14 May 2009 12:41:49 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[Triggers]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=95</guid>
		<description><![CDATA[A partir do Oracle 8i é possível criar mais de uma trigger do mesmo tipo na mesma tabela. Exemplo: duas triggers AFTER EACH ROW on INSERT. O tipo de trigger determina a ordem de execução: As BEFORE são executadas antes, e as AFTER depois. Contudo, como saber qual trigger executará primeiro quando se tem duas [...]]]></description>
			<content:encoded><![CDATA[<p>A partir do Oracle 8i é possível criar mais de uma trigger do mesmo tipo na mesma tabela. Exemplo: duas triggers AFTER EACH ROW on INSERT. O tipo de trigger determina a ordem de execução: As BEFORE são executadas antes, e as AFTER depois. Contudo, como saber qual trigger executará primeiro quando se tem duas AFTER EACH ROW on INSERT ?<span id="more-95"></span><br />
A execução das triggers neste caso seria algo &#8220;randomico&#8221;, pois não havia uma forma de definir a ordem de execução.
<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>No Oracle 11g, você pode adicionar uma cláusula que força a ordem de execução das triggers:</p>
<pre class="brush: sql;">create or replace trigger tr_pay_follow_up
before update
on payments
for each row
FOLLOWS TRIGGER_ANTERIOR
begin
... etc ...</pre>
<p>Neste caso a cláusula FOLLOWS força que a trigger seja disparada apenas após a trigger citada.</p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2009/05/14/execucao-ordenada-nas-triggers_oracle11g/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Utilizando Table of Record</title>
		<link>http://glufke.net/2009/05/04/utilizando-table-of-record/</link>
		<comments>http://glufke.net/2009/05/04/utilizando-table-of-record/#comments</comments>
		<pubDate>Mon, 04 May 2009 16:19:39 +0000</pubDate>
		<dc:creator>glufke</dc:creator>
				<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[table of record]]></category>

		<guid isPermaLink="false">http://glufke.net/?p=93</guid>
		<description><![CDATA[Hoje vamos ver o quanto é bom explorar certos recursos da ferramenta de Desenvolvimento Oracle. Sabe aquela rotina bem dinâmica que você não imagina como poderá resolver? Agora, imagine tentar guardar tudo isso em memória… Melhorou um pouco, correto? Vamos ver como é bom trabalhar com registros de memória no Oracle.




Primeiro passo é criar a [...]]]></description>
			<content:encoded><![CDATA[<p>Hoje vamos ver o quanto é bom explorar certos recursos da ferramenta de Desenvolvimento Oracle. Sabe aquela rotina bem dinâmica que você não imagina como poderá resolver? Agora, imagine tentar guardar tudo isso em memória… Melhorou um pouco, correto? Vamos ver como é bom trabalhar com registros de memória no Oracle.<br />
<span id="more-93"></span>
<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>Primeiro passo é criar a especificação de uma Package.</p>
<pre class="brush: sql;">PACKAGE PKG_EX_TABLE_RECORD IS
--Um Cursor é necessário para criar a “Table Of Cursor%ROWTYPE”,
--mesmo que não seja usado, pois o tipo a ser criado deve se
--basear em uma tabela ou um cursor
  CURSOR cExemplo IS
    SELECT cod_funcionario
      FROM empresa;

   -- Tipo: Coleção de registros
   TYPE tExemplo IS TABLE Of cExemplo%Rowtype INDEX BY binary_integer;

   -- Variável do tipo coleção de registros
   vExemplo tExemplo;

   --variável para os valores do cursor (não se pode atribuir
   --diretamente um registro do cursor à variável da coleção)
   vRec cExemplo%rowtype;
   -- índice
   x integer;
END;</pre>
<p>Agora, vamos ver como armazenar informações nesse registro de memória.</p>
<pre class="brush: sql;">DECLARE
  --vamos ver os funcionarios que tem salario menor que 2000 reais.
  CURSOR cEmpregados IS
  SELECT cod_funcionario
  FROM empresa
  WHERE func_sal <= 2000;

BEGIN
  –-iniciando o valor do indice
  PKG_EX_TABLE_RECORD.x := 0;
  FOR regfunc IN cEmpregados LOOP
    -- x é o indice para o registro, estou atritubindo mais 1 a ele de
    -- acordo com o que já existe, tipo uma sequence. Pego o ultimo
    -- valor e somo mais um.
    PKG_EX_TABLE_RECORD.x := nvl(PKG_EX_TABLE_RECORD.vExemplo.last,0) + 1;

    --atribui os valores do cursor (cConta_Produtos)
    --ao array de elementos
    PKG_EX_TABLE_RECORD.vExemplo(PKG_EX_TABLE_RECORD.x).cod_funcionario := regfunc.cod_funcionario;
  END LOOP;
END;</pre>
<p>Agora, chegou a hora de ver conteúdo do registro de memória.</p>
<pre class="brush: sql;">--Com um for loop, vamos varrer todo o registro
--de memória afim de recuperar os valores

--dessa forma, pego o ultimo valor caso exista.
FOR j IN 1..nvl(PKG_EX_TABLE_RECORD.vExemplo.last,0) LOOP 

  --uma nova opção está sendo utilizada, para então
  --ser possível ver se existe registro antes de
  --excluir, caso contrario, dará um erro por nao achar o registro
  IF PKG_EX_TABLE_RECORD.vExemplo.EXISTS(j) THEN
    --Verifica se o código do funcionario é igual ao listado abaixo,
    --assim, posso destaca-lo de alguma forma na tela
     IF PKG_EX_TABLE_RECORD.vExemplo(j).cod_funcionario = consulta.cod_funcionario THEN
       --ao localizar, uma ação será realizada
        (…)
     END IF;
  END IF;
END LOOP;</pre>
<p>Pronto. Agora, não podemos esquecer de inserir uma função para limpar a memória quando você achar que não mais irá utiliza-la.</p>
<pre class="brush: sql;">--vamos então varrer todo o registro de memória
FOR j IN 1..nvl(PKG_EX_TABLE_RECORD.vExemplo.last,0) LOOP

  --uma nova opção está sendo utilizada, para então ser possível
  --ver se existe registro antes de excluir, caso contrario,
  --dará um erro por nao achar o registro
  IF PKG_EX_TABLE_RECORD.vExemplo.EXISTS(j) THEN

    --Deletando registro de memoria. Uma vez deletado, a posição J
    --ficará sempre vazia, por isso a necessidade de usar o exists
     pkg_aviso_cirurgia.vAvisoCir.DELETE(j);
  END IF;

--Fim do Loop para verificar os agendamentos localizados
END LOOP;  </pre>
<p>Pronto, agora já é possível arriscar na solução de algum problema que precise dessa rotina, ela pode ser utilizada da forma mais fácil até a mais complexa…</p>
<p><em>Rodrigo Valentim é Analista de Sistemas Oracle Developer</em><br />
<a href="http://www.rodrigovalentim.com/blog">http://www.rodrigovalentim.com/blog</a></p>
]]></content:encoded>
			<wfw:commentRss>http://glufke.net/2009/05/04/utilizando-table-of-record/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
