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

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

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

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=74</guid>
		<description><![CDATA[Fala pessoAll, Com a contribuição do nosso amigo e leitor Robson Cristovão, está aí um guia básico de SQL que pode ser bastante útil para quem está começando no mundo SQL e tem algumas dúvidas quanto ao uso e sitaxe de alguns comandos SQL! Fica a dica! AND &#124; OR: SELECT nome_coluna(s) FROM nome_tabela WHERE [...]]]></description>
			<content:encoded><![CDATA[<p>Fala pessoAll,</p>
<p>Com a contribuição do nosso amigo e leitor <strong>Robson Cristovão</strong>, está aí um guia básico de SQL que pode ser bastante útil para quem está começando no mundo SQL e tem algumas dúvidas quanto ao uso e sitaxe de alguns comandos SQL! Fica a dica! </p>
<p><code>AND | OR:<br />
	SELECT nome_coluna(s)<br />
	FROM    nome_tabela<br />
	WHERE condiçao<br />
	AND | OR condiçao<br />
</code></p>
<p><code>ALTER TABLE (add coluna):<br />
	ALTER TABLE nome_tabela<br />
	ADD nome_coluna datatype<br />
</code></p>
<p><code>ALTER TABLE (drop column):<br />
	ALTER TABLE nome_tabela<br />
	DROP COLUMN nome_coluna<br />
</code></p>
<p><code>AS (alias for column):<br />
	SELECT nome_coluna AS coluna_apelido<br />
	FROM nome_tabela<br />
</code></p>
<p><code>AS (alias for table):<br />
	SELECT nome_coluna<br />
	FROM nome_tabela  AS tabela_apelido<br />
</code></p>
<p><code>BETWEEN:<br />
	SELECT nome_coluna(s)<br />
	FROM nome_tabela<br />
	WHERE nome_coluna<br />
	BETWEEN valor1 AND valor2<br />
</code></p>
<p><code>CREATE (database):<br />
	CREATE DATABASE nome_base_de_dados<br />
</code></p>
<p><code>CREATE (index):<br />
	CREATE INDEX nome_indice<br />
	ON nome_tabela (nome_coluna)<br />
</code></p>
<p><code>CREATE (table):<br />
	CREATE TABLE nome_tabela(<br />
	nome_coluna1 tipo_dado,<br />
	nome_coluna2 tipo_dado,...)<br />
</code></p>
<p><code>CREATE (unique index):<br />
	CREATE UNIQUE INDEX nome_indice<br />
	ON nome_tabela (nome_coluna)<br />
</code></p>
<p><code>CREATE (view):<br />
	CREATE VIEW nome_da_view AS<br />
	SELECT nome_coluna(s)<br />
	FROM nome_tabela<br />
	WHERE condiçao<br />
</code></p>
<p><code>DELETE:<br />
	DELETE FROM nome_tabela<br />
OU<br />
	DELETE FROM nome_tabela<br />
	WHERE condiçao<br />
</code></p>
<p><code>DROP (database):<br />
	DROP DATABASE nome_base_de_dados<br />
</code></p>
<p><code>DROP (index):<br />
	DROP INDEX nome_tabela.nome_indice<br />
</code></p>
<p><code>DROP (table):<br />
	DROP TABLE nome_tabela<br />
</code></p>
<p><code>GROUP BY:<br />
	SELECT nome_coluna1,SUM(nome_coluna2)<br />
	FROM nome_tabela<br />
	GROUP BY nome_coluna1<br />
</code></p>
<p><code>HAVING:<br />
	SELECT nome_coluna1,SUM(nome_coluna2)<br />
	FROM nome_tabela<br />
	GROUP BY nome_coluna1<br />
	HAVING SUM(nome_coluna2) valor_da_condiçao<br />
</code></p>
<p><code>IN:<br />
	SELECT nome_coluna(s)<br />
	FROM nome_tabela<br />
	WHERE nome_coluna<br />
	IN (valor1,valor2,..)<br />
</code></p>
<p><code>INSERT:<br />
	INSERT INTO nome_tabela<br />
	VALUES (valor1, valor2,....)<br />
OU<br />
	INSERT INTO nome_tabela<br />
	(nome_coluna1, nome_coluna2,...)<br />
	VALUES (valor1, valor2,....)<br />
</code></p>
<p><code>LIKE:<br />
	SELECT nome_coluna(s)<br />
	FROM nome_tabela<br />
	WHERE nome_coluna<br />
	LIKE padrao<br />
</code></p>
<p><code>ORDER BY:<br />
	SELECT nome_coluna(s)<br />
	FROM nome_tabela<br />
	ORDER BY nome_coluna [ASC | DESC<br />
</code></p>
<p><code>SELECT:<br />
	SELECT nome_coluna(s)<br />
	FROM nome_tabela<br />
</code></p>
<p><code>SELECT (all):<br />
	SELECT * FROM nome_tabela<br />
</code></p>
<p><code>SELECT (distinct):<br />
	SELECT DISTINCT nome_coluna(s)<br />
	FROM nome_tabela<br />
</code></p>
<p><code>SELECT (into - usado para criar cópias auxiliares das tabelas):<br />
	SELECT * INTO new_nome_tabela<br />
	FROM original_nome_tabela<br />
OU<br />
	SELECT nome_coluna(s)<br />
	INTO new_nome_tabela<br />
	FROM original_nome_tabela<br />
</code></p>
<p><code>TRUNCATE:<br />
	TRUNCATE TABLE nome_tabela<br />
</code></p>
<p><code>UPDATE:<br />
	UPDATE nome_tabela<br />
	SET nome_coluna=novo_valor<br />
	[, nome_coluna=novo_valor]<br />
	WHERE nome_coluna = algum_valor<br />
</code></p>
<p><code>WHERE:<br />
	SELECT nome_coluna(s)<br />
	FROM nome_tabela<br />
	WHERE condiçao<br />
</code></p>
<p>Espero que gostem.</p>
<p>Atc.<br />
Gerson Júnior<br />
gerson.vasconcelos@gmail.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2010/03/08/guida-de-referencia-de-sql-basico/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dica: Como descobrir quem referencia uma coluna?</title>
		<link>http://www.diaadiaoracle.com.br/2010/02/11/dica-como-descobrir-quem-referencia-uma-coluna/</link>
		<comments>http://www.diaadiaoracle.com.br/2010/02/11/dica-como-descobrir-quem-referencia-uma-coluna/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 14:46:26 +0000</pubDate>
		<dc:creator>oracle</dc:creator>
				<category><![CDATA[banco de dados]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[desenvolvimento]]></category>
		<category><![CDATA[dicas]]></category>
		<category><![CDATA[distinct]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[select]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[dictionary]]></category>
		<category><![CDATA[foreign key]]></category>

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

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=12</guid>
		<description><![CDATA[Fala PessoAll, Hoje vamos falar de Construção de SQL. As vezes precisamos fazer umas coisas mais avançadas num comando SQL e aí precisamos utilizar alguns recursos mais interessantes que o Oracle nos proporciona. Quem nunca pensou: &#8220;Ai como seria bom se tivesse um IF no select&#8221;. Tem sim! O primeiro recurso que podemos utilizar é [...]]]></description>
			<content:encoded><![CDATA[<p>Fala PessoAll,</p>
<p>Hoje vamos falar de <strong>Construção de SQL</strong>.</p>
<p>As vezes precisamos fazer umas coisas mais avançadas num comando SQL e aí precisamos utilizar alguns recursos mais interessantes que o <strong>Oracle</strong> nos proporciona.</p>
<p>Quem nunca pensou: &#8220;Ai como seria bom se tivesse um IF no select&#8221;. Tem sim!</p>
<p>O primeiro recurso que podemos utilizar é o <strong>DECODE</strong>, essa <strong>função</strong> é bem interessante e quebra um bocado de galhos, vamos ver um exemplo pra &#8220;clarear&#8221; as idéias.</p>
<p>Suponha que você tem uma tabela que contém o sexo das pessoas, mas na tabela só armazena F ou M e você quer que seja mostrado &#8220;Masculino&#8221; e &#8220;Feminino&#8221; no retorno do seu <strong>select</strong>, como fazemos isso no select? Com <strong>DECODE</strong>!</p>
<p>Assim:</p>
<p><code><br />
select nome,<br />
dt_nascimento,<br />
decode(sexo,<br />
'M', 'Masculino',<br />
'F', 'Feminino',<br />
'Indefinido') sexo<br />
from pessoas;<br />
</code></p>
<p>Como funciona isso&#8230; o <strong>DECODE</strong> testa o valor que você passa no primeiro parâmetro e vai comparando com o que você especifica e retorna o que você deseja. Complexo não? NÃO!! Vamos explicar o nosso exemplo:</p>
<p>No exemplo acima é passado o campo <code>sexo</code>, em seguida passamos o primeiro valor de teste e o que vai retornar caso encontre este valor, que neste caso é: Se encontrar <code>'M'</code> retorne <code>'Masculino'</code>, sempre aos pares. Ou seja, valor encontrado e logo depois o valor que vai retornar. Como podemos ver, depois vem mais um par&#8230; <code>'F'</code> e <code>'Feminino'</code> o que nos diz que se encontrar um <code>'F'</code>, traga <code>'Feminino'</code> na coluna.</p>
<p>Tá, mas e esse último valor que tem <code>'Indefinido'</code>? Ele não tem par!! Vai dar erro? Não, esse é uma espécie de <strong>ELSE</strong> do <strong>DECODE</strong>&#8230; se ele não encontrar nenhuma das alternativas passadas para retornar um valor especificado, ele retorna esse último valor. No nosso exemplo, podemos ver que caso não encontre <code>'M'</code> nem <code>'F'</code> no campo, ele irá retornar o valor <code>'Indefinido'</code> para a coluna&#8230; agora ficou claro!</p>
<p>O <strong>DECODE</strong> não tem um limite mínimo nem máximo de &#8220;pares de teste e retorno&#8221;, você pode ir especificando os valores e os retornos de acordo com sua necessidade.</p>
<p>Bom, esse é um recurso do <strong>Oracle</strong> que pode ser bem útil para pessoas que fazem <strong>SQL</strong>, que elaboram <strong>relatórios</strong>, que vivem fazendo <strong>query</strong> entre outros casos.</p>
<p>Como podemos verificar, para usar o <strong>DECODE</strong> nós temos que saber os valores que estão na coluna para que possamos informar qual o retorno caso determinado valor seja encontrado, mas&#8230; e se eu quiser utilizar uma faixa de valores por exemplo? Tipo&#8230; se coluna <code>nota</code> estiver entre <code>0</code> e <code>3</code> retorno <code>'Péssimo'</code>, entre <code>4</code> e <code>5</code> retorne <code>'Ruim'</code>, entre <code>6</code> e <code>8</code> retorne <code>'Bom'</code> e acima de <code>8</code> retorne <code>'Ótimo'</code>? Não dá pra fazer isso com <strong>DECODE</strong> né? Mas, tenha calma&#8230; no próximo post falaremos sobre uma outra <strong>função</strong> do <strong>Oracle</strong> que é uma espécie de <strong>DECODE</strong> avançado, que permite esse tipo de teste e muito mais.</p>
<p>Espero que gostem e que seja útil. Até a próxima.</p>
<p>Não exitem em comentar e/ou mandar e-mails.</p>
<p>Atc.<br />
Gerson Júnior<br />
gerson.vasconcelos@gmail.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2009/07/15/funcao-decode-no-oracle-sql/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Oracle Execute Immediate SQL Dinâmico</title>
		<link>http://www.diaadiaoracle.com.br/2009/04/28/oracle-execute-immediate-sql-dinamico/</link>
		<comments>http://www.diaadiaoracle.com.br/2009/04/28/oracle-execute-immediate-sql-dinamico/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 02:05:00 +0000</pubDate>
		<dc:creator>oracle</dc:creator>
				<category><![CDATA[dinamico]]></category>
		<category><![CDATA[execute immediate]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=8</guid>
		<description><![CDATA[Fala pessoAll, Vamos nós novamente. A pedido do amigo Marcos Castro dessa vez estaremos falando sobre SQL Dinâmicos, um recurso muito interessante no PL/SQL que em diversas vezes não é utilizado por nossos excelentíssimos desenvolvedores, fazendo com que nossos códigos sejam bem maiores, bem mais complexos e bem mais chatos de dar manutenção. Mas&#8230; o [...]]]></description>
			<content:encoded><![CDATA[<p>Fala pessoAll,</p>
<p>Vamos nós novamente.<br />
A pedido do amigo Marcos Castro dessa vez estaremos falando sobre SQL Dinâmicos, um recurso muito interessante no PL/SQL que em diversas vezes não é utilizado por nossos excelentíssimos desenvolvedores, fazendo com que nossos códigos sejam bem maiores, bem mais complexos e bem mais chatos de dar manutenção. Mas&#8230; o lado B dessa história é: Se você complicar muito no uso de SQL Dinâmico, não tenha dúvida de que seu código vai ficar muito complexo e todo mundo que for dar manutenção vai te xingar um bocado! Rsrs.</p>
<p>Vamos lá, ao exemplo prático e simples, que é o que interessa.</p>
<p>Suponha que você tem uma função para ser feita, que deve retornar o nome de uma determinada pessoa&#8230; essa pesquisa pode ser pelo seu RG, CPF ou Habilitação. Como podemos fazer isso?</p>
<p>Exemplo 1 (sem SQL Dinâmico):</p>
<p>create or replace function pesquisa_pessoa(pcodigo number, pfiltro varchar2) return varchar2 is<br />
   v_nome_pessoa pessoas.nome%type;<br />
begin<br />
   if(pfiltro = &#8216;RG&#8217;) then<br />
      select nome<br />
         into v_nome_pessoa<br />
        from pessoas<br />
      where rg = pcodigo;<br />
   elsif(pfiltro = &#8216;CPF&#8217;) then<br />
      select nome<br />
         into v_nome_pessoa<br />
        from pessoas<br />
      where cpf = pcodigo;<br />
   elsif(pfiltro = &#8216;CNH&#8217;) then<br />
      select nome<br />
         into v_nome_pessoa<br />
        from pessoas<br />
      where cnh = pcodigo;<br />
   end if;</p>
<p>   return v_nome_pessoa;<br />
end;</p>
<p>Notemos que o SQL é o mesmo sempre (select nome into v_nome_pessoa from pessoas where &#8230; = pcodigo ), o que muda é apenas o nome do campo que será utilizado para filtrar a pessoa, portanto, podemos utilizar o recurso de SQL Dinâmico para otimizar este código, e como ele ficaria? Assim:</p>
<p>create or replace function pesquisa_pessoa(pcodigo number, pfiltro varchar2) return varchar2 is<br />
v_nome_pessoa pessoas.nome%type;<br />
v_where varchar2(50);<br />
begin<br />
if(pfiltro = &#8216;RG&#8217;) then<br />
v_where := &#8216;rg&#8217;;<br />
elsif(pfiltro = &#8216;CPF&#8217;) then<br />
v_where := &#8216;cpf&#8217;;<br />
elsif(pfiltro = &#8216;CNH&#8217;) then<br />
v_where := &#8216;cnh&#8217;;<br />
end if;</p>
<p>dbms_output.put_line(&#8216;select nome into v_nome_pessoa from pessoas where &#8216;||v_where||&#8217; = &#8216;||pcodigo||&#8217;;');</p>
<p>execute immediate &#8216;select nome from pessoas where &#8216;||v_where||&#8217; = &#8216;||pcodigo<br />
into v_nome_pessoa;</p>
<p>return v_nome_pessoa;<br />
end;</p>
<p>Bem mais simples, e não precisamos ficar repetindo o mesmo comando várias vezes.</p>
<p>Bom, isso é só um exemplo bem simples, mas&#8230; o Execute Immediate pode ser usado de diversas outras maneiras.</p>
<p>Achei um site bem interessante, que mostra as diversas usabilidades deste recurso com exemplos que podem ser utilizados para um melhor entendimento. O site é o DBA Support.</p>
<p>É isso aí, espero que este recurso seja útil e bem utilizado nas suas aplicações.</p>
<p>Atc.</p>
<p>Gerson Júnior</p>
<p>(gerson.vasconcelos@gmail.com)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2009/04/28/oracle-execute-immediate-sql-dinamico/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Union x Union ALL &#8212; Select&#8217;s no Oracle</title>
		<link>http://www.diaadiaoracle.com.br/2009/04/16/union-x-union-all-selects-no-oracle/</link>
		<comments>http://www.diaadiaoracle.com.br/2009/04/16/union-x-union-all-selects-no-oracle/#comments</comments>
		<pubDate>Thu, 16 Apr 2009 16:46:00 +0000</pubDate>
		<dc:creator>oracle</dc:creator>
				<category><![CDATA[distinct]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[select]]></category>
		<category><![CDATA[union]]></category>
		<category><![CDATA[union all]]></category>

		<guid isPermaLink="false">http://www.diaadiaoracle.com.br/?p=7</guid>
		<description><![CDATA[Fala PessoAll, Vamos com mais uma dica interessante sobre Oracle. Vamos analisar desta vez, os comandos UNION e UNION ALL. Estes comandos servem para que possamos unir mais de uma query (select) em um mesmo comando, trazendo os resultados de ambas as query&#8217;s. Que? Entendeu nada!? Vamos lá: Existe no Oracle a possibilidade de unirmos [...]]]></description>
			<content:encoded><![CDATA[<p>Fala PessoAll,</p>
<p>Vamos com mais uma dica interessante sobre Oracle.<br />
Vamos analisar desta vez, os comandos <code>UNION</code> e <code>UNION ALL</code>. Estes comandos servem para que possamos unir mais de uma query (select) em um mesmo comando, trazendo os resultados de ambas as query&#8217;s. Que? Entendeu nada!? Vamos lá:</p>
<p>Existe no Oracle a possibilidade de unirmos mais de um comando select de forma que possamos obter o resultados de todos eles unidos (claro!) em um único resultado, como se fosse um comando só, como assim?</p>
<p>Suponha que você possui uma tabela de clientes e uma tabela de funcionários, e você quer trazer todos os códigos e nomes de clientes e funcionários para exibir em um relatório? Como fazer isso? Assim:</p>
<p><code><br />
Select codcli,<br />
nom_cli,<br />
'C' tipo<br />
from clientes<br />
union<br />
Select cod_func,<br />
nom_func,<br />
'F'<br />
from funcionarios;<br />
</code></p>
<p>Se vocês executarem este comando, teremos todos os clientes e todos os funcionários listados em um mesmo resultado, mas&#8230; temos algumas coisas a considerar.</p>
<p>1 &#8211; Vocês devem ter notado que os nomes das colunas das tabelas são diferentes, quando eu rodar que nome minha coluna vai ter? O nome das colunas da primeira query da lista de comandos, a primeira query vai mandar em tudo e as colunas do resultado vão receber o nome das colunas da primeira query.</p>
<p>2 &#8211; Quando usamos o comando <code>UNION</code>, temos obrigatóriamente que ter a mesma quantidade de colunas e o mesmo tipo de dados das colunas em todas as query&#8217;s. Como assim? Suponha que na tabela <code>clientes</code> a coluna <code>cod_cli</code> tenha tipo de dados <code>number</code> e na tabela <code>funcionarios</code> a coluna <code>cod_func</code> tenha tipo de dados <code>varchar2</code>, não pode! Ao executar este comando o banco vai retornar um erro dizendo que as colunas das query&#8217;s não estão corretamente relacionadas. Como em ambos os comandos elas são a primeira coluna da query e estarão relacionadas, ambas tem que ter o mesmo tipo.</p>
<p>3 &#8211; Não podemos utilizar <code>ORDER BY</code> nas query&#8217;s envolvidas, apenas na última query, que ordernará os registros de todas as query&#8217;s. Neste caso acima, por exemplo, se na ultima query colocássemos um <code>ORDER BY 1</code> por exemplo, ele ordenaria o resultado das duas query&#8217;s juntas, como se fosse um comando só. Se tiver códigos iguais nas duas query&#8217;s, serão trazidos juntos, pois os resultados serão considerados juntos na hora de ordenar.</p>
<p>Outra coisa que comentei no início foi o <code>UNION ALL</code>, qual a diferença dele pro <code>UNION</code>? O <code>UNION</code> utilizado sozinho faz um <code>distinct</code> no resultado da query, ou seja, se tiverem resultados repitidos eles não serão exibidos, será exibida apenas uma ocorrência. Suponha que por coincidência tenhamos um cliente com código 1 e nome CICERO e tenhamos um funcionario com código 1 e nome CICERO também, caso não tivéssemos essa coluna tipo para diferenciar os registros de clientes e funcionários teríamos a ocorrência 1 CICERO apenas uma vez em nosso resultado. Já usando o <code>UNION ALL</code>, independente da quantidade de registros repetidos que sejam retornados, todos serão exibidos.</p>
<p>Como usa? Assim:</p>
<p><code><br />
Select codcli,<br />
nom_cli,<br />
'C' tipo<br />
from clientes<br />
union all<br />
Select cod_func,<br />
nom_func,<br />
'F'<br />
from funcionarios;<br />
</code></p>
<p>Qual a diferença? Só o <code>all</code> depois do <code>union</code>, depois disso o resto o Oracle resolve. Espero esse tal de Oracle!!</p>
<p>Momento DBA: Para o banco, por não precisar se preocupar em verificar se existem resultados iguais para que exiba apenas um deles, o <code>UNION ALL</code> tem bem menos custo para ser executado, portanto, se você tiver query&#8217;s em que você tem certeza que não serão retornados valores repetidos (como essa do exemplo, em que temos uma coluna <code>tipo</code> para diferenciar) use sempre <code>UNION ALL</code>, seu DBA e seu Banco de Dados agradecem!</p>
<p>É isso pessoal, espero que tenham entendido e que gostem.<br />
Qualquer dúvida, sugestão, reclamação etc não deixem de entrar em contato.</p>
<p>Atc.<br />
Gerson Júnior<br />
gerson.vasconcelos@gmail.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.diaadiaoracle.com.br/2009/04/16/union-x-union-all-selects-no-oracle/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

