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

<channel>
	<title>glufke.net &#187; Oracle 11g</title>
	<atom:link href="http://glufke.net/tag/oracle-11g/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>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[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2010%2F03%2F31%2Flocal-index-vs-global-indexem-tabela-particionada%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2010/03/31/local-index-vs-global-indexem-tabela-particionada/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2010/03/31/local-index-vs-global-indexem-tabela-particionada/"  data-text="Local Index vs. Global Index em tabela particionada" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2010/03/31/local-index-vs-global-indexem-tabela-particionada/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><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>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[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2010%2F02%2F04%2Fedition-based-redefinition%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2010/02/04/edition-based-redefinition/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2010/02/04/edition-based-redefinition/"  data-text="Edition-Based Redefinition: a feature mais matadora do Oracle 11g R2" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2010/02/04/edition-based-redefinition/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><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>
		<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[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2009%2F08%2F17%2Fcolunas-virtuais-no-11g-parte-2%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2009/08/17/colunas-virtuais-no-11g-parte-2/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2009/08/17/colunas-virtuais-no-11g-parte-2/"  data-text="Colunas Virtuais no 11g &#8211; Parte 2" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2009/08/17/colunas-virtuais-no-11g-parte-2/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><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[<div class="bottomcontainerBox" style="">
			<div style="float:left; width:50px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fglufke.net%2F2009%2F07%2F31%2Fcolunas-virtuais-no-oracle-11g%2F&amp;layout=button_count&amp;show_faces=false&amp;width=50&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:50px; height:21px;"></iframe></div>
			<div style="float:left; width:60px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://glufke.net/2009/07/31/colunas-virtuais-no-oracle-11g/"></g:plusone>
			</div>
			<div style="float:left; width:70px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://glufke.net/2009/07/31/colunas-virtuais-no-oracle-11g/"  data-text="Colunas Virtuais no 11g &#8211; Parte 1" data-count="horizontal" data-via="glufke"></a>
			</div><div style="float:left; width:110px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://glufke.net/2009/07/31/colunas-virtuais-no-oracle-11g/" data-counter="right"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><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>
	</channel>
</rss>

