<?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/"
	xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>CarlosAL &#187; Oracle</title>
	<atom:link href="http://carlosal.wordpress.com/category/oracle/feed/" rel="self" type="application/rss+xml" />
	<link>http://carlosal.wordpress.com</link>
	<description>Reflexiones sobre TERADATA, Oracle, Linux y todo lo que ocurre en la vida de un profesional de IT.</description>
	<lastBuildDate>Mon, 09 Nov 2009 10:35:41 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>es</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='carlosal.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/88d6f83190eacbf706b5945802b90cba?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>CarlosAL &#187; Oracle</title>
		<link>http://carlosal.wordpress.com</link>
	</image>
			<item>
		<title>Sun ORACLE DATABASE MACHINE</title>
		<link>http://carlosal.wordpress.com/2009/10/05/sun-oracle-database-machine/</link>
		<comments>http://carlosal.wordpress.com/2009/10/05/sun-oracle-database-machine/#comments</comments>
		<pubDate>Mon, 05 Oct 2009 16:49:34 +0000</pubDate>
		<dc:creator>carlosal</dc:creator>
				<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://carlosal.wordpress.com/?p=489</guid>
		<description><![CDATA[La primera de las consecuencias visibles de la adquisición de Sun por Oracle: Sun ORACLE DATABASE MACHINE.
Oracle ha reconstruído su HP ORACLE DATABASE MACHINE con tecnología (léase servidores) Sun: pasa de los servidores Exadata (con los HP Proliant) a los Exadata II
Hay varias cosas sorprendentes en este movimiento que le dejan a uno un tanto [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=489&subd=carlosal&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>La primera de las consecuencias visibles de la <a href="http://carlosal.wordpress.com/2009/04/20/%c2%a1%c2%a1oracle-compra-sun/">adquisición de Sun por Oracle</a>: <a href="http://www.oracle.com/database/database-machine.html">Sun ORACLE DATABASE MACHINE</a>.</p>
<p>Oracle ha reconstruído su <a href="http://carlosal.wordpress.com/2008/09/29/hp-oracle-database-machine-tras-las-huellas-de-teradata/">HP ORACLE DATABASE MACHINE</a> con tecnología (léase servidores) Sun: pasa de los servidores Exadata (con los HP Proliant) a los Exadata II</p>
<p>Hay varias cosas sorprendentes en este movimiento que le dejan a uno un tanto perplejo:</p>
<ol>
<li>Oracle lo anuncia como &#8216;<em>World’s First OLTP Database Machine</em>&#8216; (lá primera máquina de bases de datos OLTP)<strong> ¡OLTP! </strong>Originariamente, con la <a href="../2008/09/29/hp-oracle-database-machine-tras-las-huellas-de-teradata/">HP ORACLE DATABASE MACHINE</a> se pretendía asentar la posición de Oracle en el mercado del &#8216;<em>Data Warehousing</em>&#8216;, no de OLTP.</li>
<li>Oracle ha dejado de vender las <a href="../2008/09/29/hp-oracle-database-machine-tras-las-huellas-de-teradata/">HP ORACLE DATABASE MACHINE</a> &#8216;<em>ipso facto</em>&#8216;. Si yo fuera un cliente al que un avispado comercial de Oracle le ha &#8216;colocado&#8217; una de esas <a href="../2008/09/29/hp-oracle-database-machine-tras-las-huellas-de-teradata/">HP ORACLE DATABASE MACHINE</a> este último año, creo que iría a buscarle a su casa con un bate de béisbol en cada mano.</li>
<li>En vez de usar los Sun Sparc, la arquitectura de los nuevos servidores Exadata II está basada en procesadores Intel. Más específicamente en los <a href="http://www.intel.com/cd/products/services/emea/spa/server/processors/344489.htm">Intel Xeon 5500</a></li>
<li>El sistema operativo es <a href="http://www.oracle.com/us/technologies/linux/index.htm">Oracle Enterprise Linux</a>, en vez de Solaris.</li>
</ol>
<p>Y todo rebozado con gran cantidad de palabrejas, eslóganes, y demás parafernalia publicitaria. Y es que Larry es siempre Larry.</p>
<p>Saludos.</p>
<p>Carlos.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/carlosal.wordpress.com/489/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/carlosal.wordpress.com/489/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/carlosal.wordpress.com/489/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/carlosal.wordpress.com/489/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/carlosal.wordpress.com/489/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/carlosal.wordpress.com/489/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/carlosal.wordpress.com/489/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/carlosal.wordpress.com/489/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/carlosal.wordpress.com/489/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/carlosal.wordpress.com/489/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=489&subd=carlosal&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://carlosal.wordpress.com/2009/10/05/sun-oracle-database-machine/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d45c1082325971d1aaa6a1ad13d2620?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">carlosal</media:title>
		</media:content>
	</item>
		<item>
		<title>Business as usual&#8230;</title>
		<link>http://carlosal.wordpress.com/2009/09/15/business-as-usual/</link>
		<comments>http://carlosal.wordpress.com/2009/09/15/business-as-usual/#comments</comments>
		<pubDate>Tue, 15 Sep 2009 16:12:42 +0000</pubDate>
		<dc:creator>carlosal</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://carlosal.wordpress.com/?p=462</guid>
		<description><![CDATA[Aquí estamos otra vez, después de unas semanas de (merecidas) vacaciones. Tiempo para descansar, leer, dormir, nadar, correr&#8230; y sin tocar un ordernador.
Lecturas: La &#8216;Autobiografía&#8217; sin censurar de Charles Darwin, &#8216;Cinco Semanas En Globo&#8217; de Julio Verne y &#8216;Asesinos Sin Rostro&#8217; de Henning Mankell (Wallander le da más de mil vueltas a Salander).
Coche: Fiat Punto. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=462&subd=carlosal&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Aquí estamos otra vez, después de unas semanas de (merecidas) vacaciones. Tiempo para descansar, leer, dormir, nadar, correr&#8230; y sin tocar un ordernador.</p>
<p>Lecturas: La &#8216;Autobiografía&#8217; sin censurar de <a href="http://en.wikipedia.org/wiki/Charles_Darwin">Charles Darwin</a>, &#8216;Cinco Semanas En Globo&#8217; de <a href="http://es.wikipedia.org/wiki/Julio_Verne">Julio Verne</a> y &#8216;Asesinos Sin Rostro&#8217; de <a href="http://es.wikipedia.org/wiki/Henning_Mankell">Henning Mankell</a> (<a href="http://es.wikipedia.org/wiki/Kurt_Wallander">Wallander</a> le da más de mil vueltas a <a href="http://es.wikipedia.org/wiki/Lisbeth_Salander">Salander</a>).</p>
<p>Coche: Fiat Punto. Tranquilo, familiar, espartano.</p>
<p>He aquí unas cuantas reflexiones que se me han ocurrido mientras mi mente divagaba bajo el sol entre cervecita y cervecita:</p>
<p><strong>·La Gran Clavada</strong>: El precio del alquiler del mismo coche, por el mismo tiempo, en las mismas fechas entre 2008 y 2009 ha subido como un 120%. Y luego dicen que el IPC está bajando. Según parece, la escasez de créditos de los bancos hacen que las compañías no tengan liquidez para comprar coches con los que renovar las flotas. Esto disminuye la oferta para una (casi) igual demanda, con lo que los precios suben desmesuradamente (a esto creo que técnicamente se le llama &#8216;economía de mercado&#8217;. A mí me parece simplemente un atraco en el que alguien está haciendo su agosto -nunca mejor dicho-)</p>
<p><strong>·La Gran Cagada:</strong> Encontré una oferta muy buena para unas <a href="http://www.joesnewbalanceoutlet.com/larger_view.asp?style=M767WR">New Balance 767</a>. Llevado por la emoción del momento, me las probé demasiado deprisa con el resultado de que las compré medio número pequeñas. He intentado correr con ellas para ver si podía &#8216;domarlas&#8217;, pero me hacen daño en la parte externa de los dedos gordos de los pies.</p>
<p><strong>·La Gran Putada:</strong> El entusiasmo de las vacaciones me llevó a hacer burradas: tirar niños a la piscina, subirlos a los hombros, hacer el bestia&#8230; con el resultado de una lumbalgia que traté primero con pomada de ibuprofeno -sin resultado- y con calmantes, antiinflamatorios y relajantes musculares después. Total: cuatro o cinco días jodido de verdad.</p>
<p><strong>·La Gran Guarrada:</strong> Los fumadores deben de pensar que la playa es una especie de cenicero gigante en el que apagar y dejar las colillas de sus cigarrillos. Es asqueroso intentar hacer un castillo de arena con <em>el Bicho nº1</em> y el <em>Bicho nº2</em> y encontrar colillas y más colillas. ¿Acaso hacen lo mismo en sus casas? ¿Dejan tiradas las colillas por el suelo?</p>
<p><strong>·La Gran &#8216;Bacalada&#8217;: </strong>Mi <a href="http://www.timex.com/gp/product/B00093DSIY/sr=1-3/qid=1253085119/ref=sr_1_3/190-0691684-1006061?ie=UTF8&amp;m=A1S5XB33AHYRMX&amp;n=APS&amp;timexBrand=core">Timex Ironman Triathlon 100-Lap</a> dice que aguanta 100 metros de profundidad. Pues después de un chapuzón en la playa apareció una burbuja bajo el cristal principal, que se convirtió en una pequeña multitud de gotitas de agua. Más tarde, dejaron de funcionar varias barras de los dígitos de la pantalla haciendo casi imposible leer la hora. Tampoco funciona la iluminación &#8216;indiglo&#8217;. Quizá abriéndolo y limpiándolo vuelva a funcionar correctamente, pero eso de &#8216;WR 100 M&#8217; es una &#8216;bacalá&#8217; de mucho cuidado.</p>
<p><strong>·La Gran Gozada:</strong> Cómo se lo han pasado<em> el Bicho nº1</em> y <em>el Bicho nº2</em>. La felicidad que ves en los niños felices es la felicidad más absoluta.</p>
<p>¡Ah! Y mientras tanto <a href="http://www.oracle.com/technology/products/database/oracle11g/index.html">Oracle ha sacado la versión 11gR2</a> (&#8216;R2&#8242;: esa sí la instalaría yo).</p>
<p>Saludos.</p>
<p>Carlos.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/carlosal.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/carlosal.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/carlosal.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/carlosal.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/carlosal.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/carlosal.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/carlosal.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/carlosal.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/carlosal.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/carlosal.wordpress.com/462/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=462&subd=carlosal&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://carlosal.wordpress.com/2009/09/15/business-as-usual/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d45c1082325971d1aaa6a1ad13d2620?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">carlosal</media:title>
		</media:content>
	</item>
		<item>
		<title>Creando Vistas Materializadas en otros esquemas: ORA-01031 (II)</title>
		<link>http://carlosal.wordpress.com/2009/08/18/creando-vistas-materializadas-en-otros-esquemas-ora-01031-ii/</link>
		<comments>http://carlosal.wordpress.com/2009/08/18/creando-vistas-materializadas-en-otros-esquemas-ora-01031-ii/#comments</comments>
		<pubDate>Tue, 18 Aug 2009 17:14:23 +0000</pubDate>
		<dc:creator>carlosal</dc:creator>
				<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://carlosal.wordpress.com/?p=448</guid>
		<description><![CDATA[Recientemente me ha llegado a mi &#8216;mail&#8217; una duda sobre el mismo error (ORA-01031: privilegios insuficientes) al crear una vista materializada en otro esquema.
Tras remitirle aquí, el remitente me decía que persistía el error. Al ver el DDL de la creación de la vista materializada caí en la cuenta de que el problema era otro:era [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=448&subd=carlosal&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Recientemente me ha llegado a mi &#8216;mail&#8217; una duda sobre el mismo error (ORA-01031: privilegios insuficientes) al <a href="http://carlosal.wordpress.com/2008/02/20/creando-vistas-materializadas-en-otros-esquemas-ora-01031/">crear una vista materializada en otro esquema</a>.</p>
<p>Tras remitirle <a href="http://carlosal.wordpress.com/2008/02/20/creando-vistas-materializadas-en-otros-esquemas-ora-01031/">aquí</a>, el remitente me decía que persistía el error. Al ver el DDL de la creación de la vista materializada caí en la cuenta de que el problema era otro:<strong>era una vista materializada &#8216;REFRESH ON COMMIT&#8217;</strong>. Pues bien, para este tipo de vistas se necesita un privilegio específico:</p>
<blockquote><p><kbd><strong>ON COMMIT REFRESH</strong></kbd> create a refresh-on-commit materialized view on any table in the database</p></blockquote>
<p>Y lo vemos aquí:</p>
<pre>
CARLOS@XE.localhost&gt; CREATE MATERIALIZED VIEW MY_MV
  2    NOCACHE
  3    LOGGING
  4    NOPARALLEL
  5    BUILD IMMEDIATE
  6    REFRESH ON COMMIT
  7    AS
  8    SELECT * FROM OTHERUSER.THE_TABLE;
  SELECT * FROM OTHERUSER.THE_TABLE
                           *
ERROR en línea 8:
ORA-01031: privilegios insuficientes

CARLOS@XE.localhost&gt; CREATE MATERIALIZED VIEW MY_MV
  2    NOCACHE
  3    LOGGING
  4    NOPARALLEL
  5    BUILD IMMEDIATE
  6  --  REFRESH ON COMMIT
  7    AS
  8    SELECT * FROM OTHERUSER.THE_TABLE;

Vista materializada creada.

CARLOS@XE.localhost&gt; DROP MATERIALIZED VIEW MY_MV;

Vista materializada borrada.

CARLOS@XE.localhost&gt; GRANT ON COMMIT REFRESH TO CARLOS;

Concesión terminada correctamente.

CARLOS@XE.localhost&gt; CREATE MATERIALIZED VIEW MY_MV
  2    NOCACHE
  3    LOGGING
  4    NOPARALLEL
  5    BUILD IMMEDIATE
  6    REFRESH ON COMMIT
  7    AS
  8    SELECT * FROM OTHERUSER.THE_TABLE;

Vista materializada creada.

CARLOS@XE.localhost&gt;
</pre>
<p>Saludos.</p>
<p>Carlos.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/carlosal.wordpress.com/448/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/carlosal.wordpress.com/448/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/carlosal.wordpress.com/448/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/carlosal.wordpress.com/448/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/carlosal.wordpress.com/448/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/carlosal.wordpress.com/448/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/carlosal.wordpress.com/448/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/carlosal.wordpress.com/448/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/carlosal.wordpress.com/448/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/carlosal.wordpress.com/448/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=448&subd=carlosal&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://carlosal.wordpress.com/2009/08/18/creando-vistas-materializadas-en-otros-esquemas-ora-01031-ii/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d45c1082325971d1aaa6a1ad13d2620?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">carlosal</media:title>
		</media:content>
	</item>
		<item>
		<title>Importando fechas julianas a Teradata.</title>
		<link>http://carlosal.wordpress.com/2009/07/14/importando-fechas-julianas-a-teradata/</link>
		<comments>http://carlosal.wordpress.com/2009/07/14/importando-fechas-julianas-a-teradata/#comments</comments>
		<pubDate>Tue, 14 Jul 2009 16:39:18 +0000</pubDate>
		<dc:creator>carlosal</dc:creator>
				<category><![CDATA[Desarrollo Software]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Teradata]]></category>

		<guid isPermaLink="false">http://carlosal.wordpress.com/?p=425</guid>
		<description><![CDATA[Actualmente estoy trabajando en un proceso de incorporación de datos de una Base de datos OLTP Oracle a un Data Warehouse Teradata. La cosa no parecía muy complicada hasta que nos hemos dado cuenta que dicha base de datos Oracle es a su vez resultado de una migración -y no muy bien hecha- de un [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=425&subd=carlosal&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Actualmente estoy trabajando en un proceso de incorporación de datos de una Base de datos OLTP Oracle a un Data Warehouse Teradata. La cosa no parecía muy complicada hasta que nos hemos dado cuenta que dicha base de datos Oracle es a su vez resultado de una migración -y no muy bien hecha- de un DB2. Entre otras particularidades nos hemos encontrado con que hay tablas sin &#8216;<em>primary key</em>&#8216; y que las tablas y columnas tienen nombres restringidos a 8 dígitos (herencia DB2, suponemos). También que las tablas presentan cláusulas de almacenamiento (&#8216;STORAGE&#8217;) con &#8216;INITIAL&#8217; 1K, 2K, 3K,&#8230; (¡Hey! ¡Estamos en 2009! ¿alguien ha oído hablar de los LMT&#8217;s?) lo que para un <em>&#8216;datablock&#8217;</em> de 8K (suponemos) resulta ser un tanto &#8217;surrealista&#8217;.</p>
<p>Pero lo mejor es que todas las fechas aparecen como NUMBER(7). Al preguntar, nos dicen que son fechas &#8216;en juliano&#8217; (&#8216;<a href="http://en.wikipedia.org/wiki/Julian_date">julian date</a>&#8216;).</p>
<p>El calendario juliano es un calendario en el que se cuentan los días desde el 1 de enero del 4713 antes de Cristo a mediodía. Así el 14/07/2009 será el 2455027.</p>
<p>Oracle maneja las fechas julianas sin problemas mediante el formato &#8216;J&#8217; de las funciones TO_CHAR y TO_DATE:</p>
<pre>CARLOS@XE.localhost&gt; SELECT TO_CHAR(SYSDATE, 'J') FROM DUAL;

TO_CHAR
-------
2455027

CARLOS@XE.localhost&gt; SELECT TO_DATE('2455027', 'J') FROM DUAL;

TO_DATE(
--------
14/07/09</pre>
<p>Con lo que la incorporación de enteros (NUMBER(7)) como fechas julianas a Oracle no presentaría mayor problema que el uso de un TO_DATE().</p>
<p>Pero Teradata es otra cuestión. Teradata no presenta algo análogo al formato &#8216;J&#8217; de Oracle y hay que pensar cómo convertir esos NUMBER(7) a fechas.</p>
<p>El primer intento es obvio, pero fallido:</p>
<pre>SELECT CAST('-4713/01/01' AS DATE FORMAT 'YYYY/MM/DD') + 2455027;
 *** Failure 2665 Invalid date.
                Statement# 1, Info =0
 *** Total elapsed time was 1 second.</pre>
<p>De hecho, Teradata no soporta fechas anteriores  al 1 de enero de 01 (al menos directamente):</p>
<blockquote><p>Internally, Teradata Database stores each DATE value as a four-byte signed integer using the following formula:</p>
<p>(YEAR &#8211; 1900) * 10000 + (MONTH * 100) + DAY</p>
<p>where the YEAR, MONTH, and DAY components, defined appropriately for the Gregorian calendar, have the following range of values:</p>
<p>Range of values<br />
Component    Minimum            Maximum<br />
YEAR       1                        9999<br />
MONTH       1                           12<br />
DAY       1        28, 29, 30, or 31 (depending on the month and year)</p></blockquote>
<p>En efecto:</p>
<pre> BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT CAST((1 - 1900) * 10000 + (1 * 100) + 1 AS DATE);

SELECT CAST((1 - 1900) * 10000 + (1 * 100) + 1 AS DATE);

 *** Query completed. One row found. One column returned.
 *** Total elapsed time was 1 second.

((((1-1900)*10000)+(1*100))+1)
------------------------------
                      01/01/01

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT CAST((1 - 1900) * 10000 + (1 * 100) + 1 AS DATE) - 1;

SELECT CAST((1 - 1900) * 10000 + (1 * 100) + 1 AS DATE) - 1;
 *** Failure 2665 Invalid date.
                Statement# 1, Info =0
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT CAST('0001/01/01' AS DATE FORMAT 'YYYY/MM/DD');

SELECT CAST('0001/01/01' AS DATE FORMAT 'YYYY/MM/DD');

 *** Query completed. One row found. One column returned.
 *** Total elapsed time was 1 second.

'0001/01/01'
------------
  0001/01/01

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT CAST('0001/01/01' AS DATE FORMAT 'YYYY/MM/DD') - 1;

SELECT CAST('0001/01/01' AS DATE FORMAT 'YYYY/MM/DD') - 1;
 *** Failure 2665 Invalid date.
                Statement# 1, Info =0
 *** Total elapsed time was 1 second.</pre>
<p>Entonces ¿cómo nos las ingeniamos? La respuesta está en algo llamado <a href="http://en.wikipedia.org/wiki/Translation_%28geometry%29">traslación</a>. En vez de irnos al 1 de enero de 4713 antes de Cristo como origen de la aritmética de fechas, podemos hacer una traslación a -digamos- el <strong>1 de enero de 1900</strong>: tomamos la fecha juliana de ese día, que resulta ser el número <strong>2415021</strong>, y sacamos la diferencia con la fecha juliana recibida sabiendo la fecha base tomada. (También es bueno recordar que Teradata guarda este 1 de enero de 1900 como <strong>101</strong>).</p>
<p>Así para nuestro 14/07/2009 (<strong>2455027</strong> en juliano) tendremos que:</p>
<pre> BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT CAST(101 AS DATE) + (CAST(2455027 AS INTEGER) - 2415021) (FORMAT 'DD/MM/YYYY');

SELECT CAST(101 AS DATE) + (CAST(2455027 AS INTEGER) - 2415021) (FORMAT 'DD/MM/YYYY');

 *** Query completed. One row found. One column returned.
 *** Total elapsed time was 1 second.

(101+(2455027-2415021))
-----------------------
             14/07/2009</pre>
<p>Y con esta técnica podemos incorporar las enrevesadas fechas julianas NUMBER(7) de origen a simples fechas DATE que todo el mundo entiende.</p>
<p>Saludos.</p>
<p>Carlos.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/carlosal.wordpress.com/425/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/carlosal.wordpress.com/425/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/carlosal.wordpress.com/425/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/carlosal.wordpress.com/425/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/carlosal.wordpress.com/425/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/carlosal.wordpress.com/425/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/carlosal.wordpress.com/425/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/carlosal.wordpress.com/425/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/carlosal.wordpress.com/425/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/carlosal.wordpress.com/425/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=425&subd=carlosal&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://carlosal.wordpress.com/2009/07/14/importando-fechas-julianas-a-teradata/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d45c1082325971d1aaa6a1ad13d2620?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">carlosal</media:title>
		</media:content>
	</item>
		<item>
		<title>Heterogeneous Services: SQL a Teradata desde Oracle.</title>
		<link>http://carlosal.wordpress.com/2009/06/18/heterogeneous-services-sql-a-teradata-desde-oracle/</link>
		<comments>http://carlosal.wordpress.com/2009/06/18/heterogeneous-services-sql-a-teradata-desde-oracle/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 17:36:57 +0000</pubDate>
		<dc:creator>carlosal</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Teradata]]></category>

		<guid isPermaLink="false">http://carlosal.wordpress.com/?p=396</guid>
		<description><![CDATA[Oracle presenta unos productos de acceso a bases de datos no-Oracle que básicamente se pueden clasificar en dos grupos: Transparent Gateways y Heterogeneous Services.
Transparent Gateways son módulos de acceso a determinadas bases de datos (SQLServer, Sybase, Teradata, DB2&#8230;) Estos módulos están optimizados y ofrecen un mayor rendimiento, por lo que consisten en licencias que se [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=396&subd=carlosal&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Oracle presenta unos productos de acceso a bases de datos no-Oracle que básicamente se pueden clasificar en dos grupos: Transparent Gateways y Heterogeneous Services.</p>
<p>Transparent Gateways son módulos de acceso a determinadas bases de datos (SQLServer, Sybase, Teradata, DB2&#8230;) Estos módulos están optimizados y ofrecen un mayor rendimiento, por lo que consisten en licencias que se compran por separado.</p>
<p>Por otra parte, los Heterogeneous Services (o Generic Connectivity) están basados en accesos por ODBC/OLEDB y son gratis, aunque el rendimiento es menor.</p>
<p>Ambos persiguen un mismo objetivo: acceder desde Oracle a bases de datos no-Oracle y que sea el propio Oracle el que se encargue de los aspectos de mapeo de tipos, transferencias, etc, etc&#8230;</p>
<p>Vamos a ver como podemos hacer para que desde una ventana sqlplus conectada a una instancia Oracle veamos los datos de tablas de una base de datos Teradata con simples &#8216;SELECTS&#8217;. Por supuesto, utilizaremos la segunda solucion (ODBC/OLEDB y GRATIS).</p>
<p>Vamos a ello.</p>
<p>¿Que vamos a necesitar?</p>
<p>Lo primero, que la infraestructura de los Heterogeneous Services (Tablas, &#8216;packages&#8217;, sinónimos, etc&#8230;) esté en la base de datos Oracle. Para ello ejecutamos <strong>como SYS</strong> el &#8217;script&#8217; caths.sql:</p>
<pre>SQL*Plus: Release 10.2.0.1.0 - Production on Jue Jun 18 13:22:55 2009

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

Introduzca el nombre de usuario: sys@XE.localhost as sysdba
Introduzca la contraseña:

Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

SYS@XE.localhost&gt; @C:\bla\bla\...\10.2.0\server\RDBMS\ADMIN\caths.sql
create role hs_admin_role

...

Cuerpo del paquete creado.

Procedimiento PL/SQL terminado correctamente.

Confirmación terminada.</pre>
<p>Lo siguiente en configurar es un origen de datos ODBC. Es muy importante que configuremos el origen de datos como <strong>DE SISTEMA</strong> (no de usuario).</p>
<p>El nuestro se va a llamar TD_HS:</p>
<p><img class="alignleft size-full wp-image-403" title="TD_DS_1" src="http://carlosal.files.wordpress.com/2009/06/td_ds_1.jpg?w=425&#038;h=369" alt="TD_DS_1" width="425" height="369" /></p>
<p><img class="alignleft size-full wp-image-404" title="TD_DS_2" src="http://carlosal.files.wordpress.com/2009/06/td_ds_2.jpg?w=425&#038;h=458" alt="TD_DS_2" width="425" height="458" /></p>
<p>Una vez con el origen de datos ODBC listo comenzamos con la configuración de Oracle:</p>
<p>Para que se entere el &#8216;listener&#8217; de la conexión debemos informarle. Así en el listener.ora añadiremos una entrada bajo SID_LIST_LISTENER:</p>
<pre>SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = C:\bla\bla\...\server)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (SID_NAME = CLRExtProc)
      (ORACLE_HOME = C:\bla\bla\...\server)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (ORACLE_HOME = C:\bla\bla\...\server)
      (SID_NAME = TD_HS)
      (PROGRAM = hsodbc)
    )
  )</pre>
<p>SID_NAME debe corresponder con nuestro orígen de datos ODBC. PROGRAM es el nombre del módulo de Heterogeneous Services para ODBC (hsodbc.exe)</p>
<p>También necesitaremos una entrada en el tnsnames.ora:</p>
<pre>teradata.remote=
   (DESCRIPTION =
     (ADDRESS = (PROTOCOL = TCP)
              (HOST = XXX.XXX.XXX.XXX)
              (PORT = 1521)
     )
     (CONNECT_DATA =
         (SERVICE_NAME = TD_HS)
         (SID = TD_HS)
     )
     (HS = OK)
)</pre>
<p>Como bien de ve en la configuración será el propio &#8216;listener&#8217; de Oracle el que se encargue de gestionar las conexiones al ODBC.<br />
HS = OK identifica que será un origen Heterogeneous Services. El SID / SERVICE_NAME debe ser una vez más el nombre del origen de datos ODBC. El HOST y el PORT son los del equipo local (donde está Oracle).</p>
<p>Por último, necesitamos un fichero para la configuración de Heterogeneous Services para el origen de datos. Este fichero se llamará<strong> init&lt;SID name&gt;.ora</strong> y estará en el directorio \hs\admin de la instalación: C:\bla\bla\&#8230;\server\hs\admin\<strong>initTD_HS.ora</strong></p>
<pre>#
# HS init parameters
#

HS_FDS_CONNECT_INFO = TD_HS
HS_FDS_TRACE_LEVEL = 1
HS_FDS_TRACE_FILE_NAME = C:\bla\bla\...\server\hs\admin\initTD_HS.trc</pre>
<p>Lo importante aquí es la línea HS_FDS_CONNECT_INFO = TD_HS (una vez más el SID). Los otros son para establecer el nivel de las trazas y su fichero.</p>
<p>Si hemos llegado hasta aquí, podemos probar cómo están las cosas con un simple &#8216;tnsping&#8217;:</p>
<pre>C:\&gt;tnsping teradata.remote

TNS Ping Utility for 32-bit Windows: Version 10.2.0.1.0 - Production on 18-JUN-2009 13:46:53

Copyright (c) 1997, 2005, Oracle.  All rights reserved.

Archivos de parámetros utilizados:
C:\bla\bla\...\server\network\admin\sqlnet.ora

Adaptador TNSNAMES utilizado para resolver el alias
Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP) (HOST = XXX.XXX.XXX.XXX) (PORT = 1521))
(CONNECT_DATA = (SERVICE_NAME = TD_HS) (SID = TD_HS)) (HS = OK))
Realizado correctamente (10 mseg)

C:\&gt;</pre>
<p>El &#8216;<em>listener</em>&#8216; escucha para nuestro TD_HS.</p>
<p>Lo más duro ya está hecho. Ahora sólo nos queda crear un simple dblink en Oracle:</p>
<pre>CARLOS@XE.localhost&gt; CREATE DATABASE LINK teradata.remote
CONNECT TO carlos IDENTIFIED BY xxxxxxxx
USING 'teradata.remote';

Enlace con la base de datos creado.</pre>
<p>Si hemos hecho todo bien (y parece que sí), podríamos acceder a la base de datos Teradata con SQL Oracle desde sqlplus:</p>
<pre>CARLOS@XE.localhost&gt; SELECT COD_PROVINCIA,
  2                         DESC_PROVINCIA
  3                    FROM MY_DB.PROVINCIA@teradata.remote
  4                ORDER BY COD_PROVINCIA;

COD_PROVINCIA DESC_PROVINCIA
------------- --------------------
            1 Álava
            2 Albacete
            3 Alicante/Alacant
            4 Almería
            5 Ávila
            6 Badajoz
            7 Balears (Illes)
            8 Barcelona
            9 Burgos
           10 Cáceres
           11 Cádiz
           12 Castellón/Castelló
           13 Ciudad Real
           14 Córdoba
           15 Coruña (A)
           16 Cuenca
           17 Girona
           18 Granada
           19 Guadalajara
           20 Guipúzcoa
           21 Huelva
           22 Huesca
           23 Jaén
           24 León
           25 Lleida
           26 Rioja (La)
           27 Lugo
           28 Madrid
           29 Málaga
           30 Murcia
           31 Navarra
           32 Ourense
           33 Asturias
           34 Palencia
           35 Palmas (Las)
           36 Pontevedra
           37 Salamanca
           38 Santa Cruz de Tenerife
           39 Cantabria
           40 Segovia
           41 Sevilla
           42 Soria
           43 Tarragona
           44 Teruel
           45 Toledo
           46 Valencia/València
           47 Valladolid
           48 Vizcaya
           49 Zamora
           50 Zaragoza
           51 Ceuta
           52 Melilla
           99 Extranjero
          100 Desconocido

54 filas seleccionadas.

Plan de Ejecución
----------------------------------------------------------
Plan hash value: 3717373614

----------------------------------------------------------------------------------------------------------
| Id  | Operation        | Name          | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     | Inst   |IN-OUT|
----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |               |  2000 |   126K|       |    87   (3)| 00:00:02 |        |   |
|   1 |  SORT ORDER BY   |               |  2000 |   126K|   312K|    87   (3)| 00:00:02 |        |   |
|   2 |   REMOTE         | PROVINCIA     |  2000 |   126K|       |    52   (0)| 00:00:01 | TERAD~ | R-&gt;S |
----------------------------------------------------------------------------------------------------------

Remote SQL Information (identified by operation id):
----------------------------------------------------

   2 - SELECT "COD_PROVINCIA","DESC_PROVINCIA" FROM "MY_DB"."PROVINCIA" (accessing
       'TERADATA.REMOTE' )

Estadísticas
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          0  consistent gets
          0  physical reads
          0  redo size
       1600  bytes sent via SQL*Net to client
        413  bytes received via SQL*Net from client
          5  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         54  rows processed

CARLOS@XE.localhost&gt;</pre>
<p>¡Sí señor! Y el autotrace muestra que la ejecución ha sido &#8216;REMOTE&#8217;, como era de esperar.</p>
<p>Y lo que es mejor: podemos utilizar funciones nativas Oracle en el &#8216;SELECT&#8217; a los datos Teradata:</p>
<pre>CARLOS@XE.localhost&gt; SELECT REPLACE(DESC_PROVINCIA,'M','#')
  2    FROM MY_DB.PROVINCIA@teradata.remote
  3   WHERE COD_PROVINCIA = 28;

REPLACE(DESC_PROVINCIA,'M','#')
---------------------------------------------------------------------------------------------------
#adrid

Plan de Ejecución
----------------------------------------------------------
Plan hash value: 1788691278

--------------------------------------------------------------------------------------------------
| Id  | Operation        | Name          | Rows  | Bytes | Cost (%CPU)| Time     | Inst   |IN-OUT|
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |               |    20 |  1300 |    52   (0)| 00:00:01 |        |      |
|   1 |  REMOTE          | PROVINCIA     |    20 |  1300 |    52   (0)| 00:00:01 | ALMAC~ | R-&gt;S |
--------------------------------------------------------------------------------------------------

Remote SQL Information (identified by operation id):
----------------------------------------------------

   1 - SELECT "COD_PROVINCIA","DESC_PROVINCIA" FROM "MY_DB"."PROVINCIA" WHERE
       "COD_PROVINCIA"=28 (accessing 'TERADATA.REMOTE' )

Estadísticas
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          0  consistent gets
          0  physical reads
          0  redo size
        456  bytes sent via SQL*Net to client
        380  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

CARLOS@XE.localhost&gt;</pre>
<p>Y por supuesto, con los &#8216;GRANTS&#8217; necesarios, no tenemos por qué limitarnos a &#8216;SELECTS&#8217;&#8230;</p>
<p>Saludos.</p>
<p>Carlos.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/carlosal.wordpress.com/396/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/carlosal.wordpress.com/396/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/carlosal.wordpress.com/396/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/carlosal.wordpress.com/396/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/carlosal.wordpress.com/396/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/carlosal.wordpress.com/396/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/carlosal.wordpress.com/396/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/carlosal.wordpress.com/396/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/carlosal.wordpress.com/396/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/carlosal.wordpress.com/396/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=396&subd=carlosal&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://carlosal.wordpress.com/2009/06/18/heterogeneous-services-sql-a-teradata-desde-oracle/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d45c1082325971d1aaa6a1ad13d2620?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">carlosal</media:title>
		</media:content>

		<media:content url="http://carlosal.files.wordpress.com/2009/06/td_ds_1.jpg" medium="image">
			<media:title type="html">TD_DS_1</media:title>
		</media:content>

		<media:content url="http://carlosal.files.wordpress.com/2009/06/td_ds_2.jpg" medium="image">
			<media:title type="html">TD_DS_2</media:title>
		</media:content>
	</item>
		<item>
		<title>De recursividad e iteradores.</title>
		<link>http://carlosal.wordpress.com/2009/06/10/de-recursividad-e-iteradores/</link>
		<comments>http://carlosal.wordpress.com/2009/06/10/de-recursividad-e-iteradores/#comments</comments>
		<pubDate>Wed, 10 Jun 2009 16:59:09 +0000</pubDate>
		<dc:creator>carlosal</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Teradata]]></category>

		<guid isPermaLink="false">http://carlosal.wordpress.com/?p=375</guid>
		<description><![CDATA[Muchas veces tenemos la necesidad de construir &#8216;resulsets&#8216; sobre la marcha con el fin de generar iteradores, o vistas &#8216;inline&#8216; especficas para combinar (&#8216;join&#8216;) con tablas dentro de queries.
Esto se hace fácilmente en Oracle mediante una &#8216;query&#8216; recursiva con &#8216;CONNECT BY&#8217; desde una &#8216;SELECT&#8217; a &#8216;DUAL&#8217;. Pero en Teradata las cosas funcionan de otro modo.
Hemos [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=375&subd=carlosal&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Muchas veces tenemos la necesidad de construir &#8216;<em>resulsets</em>&#8216; sobre la marcha con el fin de generar iteradores, o vistas &#8216;<em>inline</em>&#8216; especficas para combinar (&#8216;<em>join</em>&#8216;) con tablas dentro de queries.</p>
<p>Esto se hace fácilmente en Oracle mediante una &#8216;<em>query</em>&#8216; recursiva con &#8216;CONNECT BY&#8217; desde una &#8216;SELECT&#8217; a &#8216;DUAL&#8217;. Pero en Teradata las cosas funcionan de otro modo.</p>
<p>Hemos hablado a menudo de que la gran fortaleza de Teradata (su concepción &#8216;<em>share nothing</em>&#8216; y su paralelismo &#8216;natural&#8217;) puede también ser su debilidad en ocasiones. Con esto en mente vamos a hacer un pequeño ejercicio comparativo:</p>
<p>Vamos primero con Oracle. Un iterador secursivo se construye fácilmente:</p>
<pre>CARLOS@XE.localhost&gt; WITH ITERADOR
  2  AS(
  3     SELECT LEVEL
  4       FROM DUAL
  5       CONNECT BY LEVEL &lt; 11
  6  )
  7  SELECT *
  8    FROM ITERADOR
  9  ;

     LEVEL
----------
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10

10 filas seleccionadas.</pre>
<p>En Teradata podemos hacer algo muy parecido (con una tabla MY_DUAL construida al efecto y análoga a la ubícua &#8216;DUAL&#8217; de Oracle)</p>
<pre> BTEQ -- Enter your DBC/SQL request or BTEQ command:
WITH RECURSIVE ITERADOR (ORDEN)
AS(
   SELECT 1 ORDEN
     FROM MY_DB.MY_DUAL a
UNION ALL
   SELECT b.ORDEN + 1
     FROM MY_DB.MY_DUAL a,
          ITERADOR b
    WHERE b.ORDEN &lt; 10
)
SELECT *
  FROM ITERADOR
;

WITH RECURSIVE ITERADOR (ORDEN)
AS(
   SELECT 1 ORDEN
     FROM MY_DB.MY_DUAL a
UNION ALL
   SELECT b.ORDEN + 1
     FROM MY_DB.MY_DUAL a,
          ITERADOR b
    WHERE b.ORDEN &lt; 10
)
SELECT *
  FROM ITERADOR
;

 *** Query completed. 10 rows found. One column returned.
 *** Total elapsed time was 1 second.

ORDEN
-----
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10</pre>
<p>Todo parece funcionar razonablemente bien. El problema comienza cuando necesitamos un iterador un poco más grande:</p>
<pre> BTEQ -- Enter your DBC/SQL request or BTEQ command:
WITH RECURSIVE ITERADOR (ORDEN)
AS(
   SELECT 1 ORDEN
     FROM MY_DB.MY_DUAL a
UNION ALL
   SELECT b.ORDEN + 1
     FROM MY_DB.MY_DUAL a,
          ITERADOR b
    WHERE b.ORDEN &lt; 100
)
SELECT *
  FROM ITERADOR
;

WITH RECURSIVE ITERADOR (ORDEN)
AS(
   SELECT 1 ORDEN
     FROM MY_DB.MY_DUAL a
UNION ALL
   SELECT b.ORDEN + 1
     FROM MY_DB.MY_DUAL a,
          ITERADOR b
    WHERE b.ORDEN &lt; 100
)
SELECT *
  FROM ITERADOR
;

 *** Query completed. 100 rows found. One column returned.
 *** Total elapsed time was 2 seconds.

ORDEN
-----
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   .
   .
   .
   97
   98
   99
  100

 BTEQ -- Enter your DBC/SQL request or BTEQ command:</pre>
<p>Dos segundos para 100 filas no parece muy &#8216;óptimo&#8217;. Sobre todo si Oracle hace:</p>
<pre>CARLOS@XE.localhost&gt; set timing on
CARLOS@XE.localhost&gt; WITH ITERADOR
  2  AS(
  3     SELECT LEVEL
  4       FROM DUAL
  5       CONNECT BY LEVEL
 5       CONNECT BY LEVEL &lt; 101
  6  )
  7  SELECT *
  8    FROM ITERADOR
  9  ;

     LEVEL
----------
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        .
        .
        .
        97
        98
        99
       100

100 filas seleccionadas.

Transcurrido: 00:00:00.23
CARLOS@XE.localhost&gt;</pre>
<p>Si seguimos aumentando las filas del iterador las diferencias aumentan exponencialmente. (Vamos a cambiar la query un poco y poner un COUNT() para que podamos ver los resultados con más facilidad):</p>
<p>Oracle:</p>
<pre>CARLOS@XE.localhost&gt; WITH ITERADOR
  2  AS(
  3     SELECT LEVEL
  4       FROM DUAL
  5       CONNECT BY LEVEL &lt; 1001
  6  )
  7  SELECT count(1)
  8    FROM ITERADOR
  9  ;

  COUNT(1)
----------
      1000

Transcurrido: 00:00:00.04</pre>
<p>Y Teradata:</p>
<pre> BTEQ -- Enter your DBC/SQL request or BTEQ command:
WITH RECURSIVE ITERADOR (ORDEN)
AS(
   SELECT 1(SMALLINT) ORDEN
     FROM MY_DB.MY_DUAL a
UNION ALL
   SELECT b.ORDEN + 1
     FROM MY_DB.MY_DUAL a,
          ITERADOR b
    WHERE b.ORDEN &lt; 1000
)
SELECT count(1)
  FROM ITERADOR
;

WITH RECURSIVE ITERADOR (ORDEN)
AS(
   SELECT 1(SMALLINT) ORDEN
     FROM MY_DB.MY_DUAL a
UNION ALL
   SELECT b.ORDEN + 1
     FROM MY_DB.MY_DUAL a,
          ITERADOR b
    WHERE b.ORDEN &lt; 1000
)
SELECT count(1)
  FROM ITERADOR
;

 *** Query completed. One row found. One column returned.
 *** Total elapsed time was one minute and 18 seconds.

   Count(1)
-----------
       1000

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
WITH RECURSIVE ITERADOR (ORDEN)
AS(
   SELECT 1(SMALLINT) ORDEN
     FROM MY_DB.MY_DUAL a
UNION ALL
   SELECT b.ORDEN + 1
     FROM MY_DB.MY_DUAL a,
          ITERADOR b
    WHERE b.ORDEN &lt; 10000
)
SELECT count(1)
  FROM ITERADOR
;

WITH RECURSIVE ITERADOR (ORDEN)
AS(
   SELECT 1(SMALLINT) ORDEN
     FROM MY_DB.MY_DUAL a
UNION ALL
   SELECT b.ORDEN + 1
     FROM MY_DB.MY_DUAL a,
          ITERADOR b
    WHERE b.ORDEN &lt; 10000
)
SELECT count(1)
  FROM ITERADOR
;

 *** Query completed. One row found. One column returned.
 *** Total elapsed time was <strong>11 minutes and 4 seconds</strong>.

   Count(1)
-----------
      10000</pre>
<p>Mientras que a Oracle no le afecta casi nada el aumento del iterador:</p>
<pre> CARLOS@XE.localhost&gt; WITH ITERADOR
  2  AS(
  3     SELECT LEVEL
  4       FROM DUAL
  5       CONNECT BY LEVEL &lt; 10001
  6  )
  7  SELECT count(1)
  8    FROM ITERADOR
  9  ;

  COUNT(1)
----------
     10000

Transcurrido: 00:00:00.14</pre>
<p>Como se dijo al principio, a veces el paralelismo en sí puede ser una desventaja. <a href="http://asktom.oracle.com">Tom Kyte</a> ponía un ejemplo: si voy a escribir un libro de cientos de páginas, hacerlo en paralelo (varios autores escribiendo capítulos por separado y juntando el resultado final) será más efectivo (más rápido) que que lo escriba una sola persona. Pero si voy a escribir un pequeño documento de diez páginas juntar varios autores para hacerlo (ponerse en contacto con ellos, coordinar y sincronizar el trabajo, etc&#8230;) puede llevar mucho más tiempo que lo que le llevaría a una sola persona.</p>
<p>Para ver el jaleo que se forma en Teradata vemos el &#8216;EXPLAIN&#8217;:</p>
<pre>
 BTEQ -- Enter your DBC/SQL request or BTEQ command:
EXPLAIN
WITH RECURSIVE ITERADOR (ORDEN)
AS(
   SELECT 1(SMALLINT) ORDEN
     FROM MY_DB.MY_DUAL a
UNION ALL
   SELECT b.ORDEN + 1
     FROM MY_DB.MY_DUAL a,
          ITERADOR b
    WHERE b.ORDEN &lt; 10000
)
SELECT *
  FROM ITERADOR
;

EXPLAIN
WITH RECURSIVE ITERADOR (ORDEN)
AS(
   SELECT 1(SMALLINT) ORDEN
     FROM MY_DB.MY_DUAL a
UNION ALL
   SELECT b.ORDEN + 1
     FROM MY_DB.MY_DUAL a,
          ITERADOR b
    WHERE b.ORDEN &lt; 10000
)
SELECT *
  FROM ITERADOR
;

 *** Help information returned. 38 rows.
 *** Total elapsed time was 1 second.

Explanation
-----------------------------------------------------------------------
  1) First, we lock a distinct DW_USUARIO."pseudo table" for read on a
     RowHash to prevent global deadlock for MY_DB.MY_DUAL.
  2) Next, we lock MY_DB.MY_DUAL for read.
  3) We do an all-AMPs RETRIEVE step from MY_DB.MY_DUAL by way of
     an all-rows scan with no residual conditions into Spool 3
     (all_amps), which is built locally on the AMPs.  The size of Spool
     3 is estimated with high confidence to be 1 row.  The estimated
     time for this step is 0.01 seconds.
  4) We do an all-AMPs RETRIEVE step from Spool 3 by way of an all-rows
     scan into Spool 2 (all_amps), which is built locally on the AMPs.
     The size of Spool 2 is estimated with no confidence to be 1 row.
     The estimated time for this step is 0.01 seconds.
  5) We do an all-AMPs RETRIEVE step from MY_DB.MY_DUAL by way of
     an all-rows scan with no residual conditions into Spool 4
     (all_amps), which is duplicated on all AMPs.  The size of Spool 4
     is estimated with high confidence to be 20 rows.  The estimated
     time for this step is 0.01 seconds.
  6) We do an all-AMPs JOIN step from Spool 4 (Last Use) by way of an
     all-rows scan, which is joined to Spool 3 (Last Use) by way of an
     all-rows scan with a condition of ("ORDEN &lt; 10000").  Spool 4 and
     Spool 3 are joined using a product join, with a join condition of
     ("(1=1)").  The result goes into Spool 5 (all_amps), which is
     built locally on the AMPs.  The size of Spool 5 is estimated with
     no confidence to be 1 row.  The estimated time for this step is
     0.01 seconds.
  7) We do an all-AMPs RETRIEVE step from Spool 5 (Last Use) by way of
     an all-rows scan into Spool 3 (all_amps), which is built locally
     on the AMPs.  The size of Spool 3 is estimated with no confidence
     to be 2 rows.  The estimated time for this step is 0.01 seconds.
     If one or more rows are inserted into spool 3, then go to step 4.
  <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> We do an all-AMPs RETRIEVE step from Spool 2 (Last Use) by way of
     an all-rows scan into Spool 6 (all_amps), which is built locally
     on the AMPs.  The size of Spool 6 is estimated with no confidence
     to be 51 rows.  The estimated time for this step is 0.01 seconds.
  9) Finally, we send out an END TRANSACTION step to all AMPs involved
     in processing the request.
  -&gt; The contents of Spool 6 are sent back to the user as the result of
     statement 1.  The total estimated time is 0.03 seconds.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
</pre>
<p>Y aquí la sencillez en Oracle:</p>
<pre>
CARLOS@XE.localhost&gt; SET AUTOTRACE TRACEONLY;
CARLOS@XE.localhost&gt; WITH ITERADOR
  2  AS(
  3     SELECT LEVEL
  4       FROM DUAL
  5       CONNECT BY LEVEL &lt; 10001
  6  )
  7  SELECT *
  8    FROM ITERADOR
  9  ;

10000 filas seleccionadas.

Transcurrido: 00:00:00.12

Plan de Ejecución
----------------------------------------------------------
Plan hash value: 2403765415

--------------------------------------------------------------------------------------
| Id  | Operation                     | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |      |     1 |    13 |     2   (0)| 00:00:01 |
|   1 |  VIEW                         |      |     1 |    13 |     2   (0)| 00:00:01 |
|   2 |   CONNECT BY WITHOUT FILTERING|      |       |       |            |          |
|   3 |    FAST DUAL                  |      |     1 |       |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Estadísticas
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          0  consistent gets
          0  physical reads
          0  redo size
     136894  bytes sent via SQL*Net to client
       7706  bytes received via SQL*Net from client
        668  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
      10000  rows processed

CARLOS@XE.localhost&gt;
</pre>
<p>Y todo esto teniendo en cuenta que las &#8216;queries&#8217; de Teradata se han ejecutado en un &#8217;server&#8217; de 20 AMPs y las de Oracle en un XE local en un PC.</p>
<p>Saludos.</p>
<p>Carlos.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/carlosal.wordpress.com/375/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/carlosal.wordpress.com/375/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/carlosal.wordpress.com/375/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/carlosal.wordpress.com/375/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/carlosal.wordpress.com/375/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/carlosal.wordpress.com/375/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/carlosal.wordpress.com/375/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/carlosal.wordpress.com/375/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/carlosal.wordpress.com/375/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/carlosal.wordpress.com/375/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=375&subd=carlosal&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://carlosal.wordpress.com/2009/06/10/de-recursividad-e-iteradores/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d45c1082325971d1aaa6a1ad13d2620?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">carlosal</media:title>
		</media:content>
	</item>
		<item>
		<title>ANSI OUTER JOINS: parecido no es igual.</title>
		<link>http://carlosal.wordpress.com/2009/06/03/ansi-outer-joins-parecido-no-es-igual/</link>
		<comments>http://carlosal.wordpress.com/2009/06/03/ansi-outer-joins-parecido-no-es-igual/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 16:52:11 +0000</pubDate>
		<dc:creator>carlosal</dc:creator>
				<category><![CDATA[Desarrollo Software]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Teradata]]></category>

		<guid isPermaLink="false">http://carlosal.wordpress.com/?p=357</guid>
		<description><![CDATA[¿Qué es un &#8216;outer join&#8216;? Si estáis leyendo esto, seguramente ya lo sabeis. Un &#8216;outer join&#8217; es un &#8216;join&#8217; en el que las filas de la tabla principal son mantenidas en el resultado aunque no existan filas que les correspondan en la tabla con la que se combina.
La sintaxis ANSI es:
SELECT &#8230;
FROM Tabla1
(LEFT) OUTER JOIN [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=357&subd=carlosal&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>¿Qué es un <em>&#8216;outer join</em>&#8216;? Si estáis leyendo esto, seguramente ya lo sabeis. Un <em>&#8216;outer join&#8217; </em>es un<em> &#8216;join&#8217;</em> en el que las filas de la tabla principal son mantenidas en el resultado aunque no existan filas que les correspondan en la tabla con la que se combina.</p>
<p>La sintaxis ANSI es:</p>
<p>SELECT &#8230;<br />
FROM Tabla1<br />
(LEFT) OUTER JOIN Tabla2 ON Tabla1.Col1 = Tabla2.Col1<br />
[AND Tabla1.Col2 = Tabla2.Col2 ...]</p>
<p>La teoría es fácil y la sintaxis también, pero a veces sentencias &#8216;muy parecidas&#8217; que en un primer vistazo asumimos como idénticas pueden no serlo tanto y meternos en problemas al devolver resultados inesperados.</p>
<p>Vamos a verlo en Teradata, pero primero las tablas de rigor:</p>
<pre> BTEQ -- Enter your DBC/SQL request or BTEQ command:
CREATE SET TABLE MY_DB.PRUEBA01 ,
     NO FALLBACK ,
     NO BEFORE JOURNAL,
     NO AFTER JOURNAL,
     CHECKSUM = DEFAULT
     (
      ID    INTEGER     NOT NULL,
      CTXT  VARCHAR(10) NOT NULL )
PRIMARY INDEX ( ID );

CREATE SET TABLE MY_DB.PRUEBA01 ,
     NO FALLBACK ,
     NO BEFORE JOURNAL,
     NO AFTER JOURNAL,
     CHECKSUM = DEFAULT
     (
      ID    INTEGER     NOT NULL,
      CTXT  VARCHAR(10) NOT NULL )
PRIMARY INDEX ( ID );

 *** Table has been created.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:

CREATE SET TABLE MY_DB.PRUEBA02 ,
     NO FALLBACK ,
     NO BEFORE JOURNAL,
     NO AFTER JOURNAL,
     CHECKSUM = DEFAULT
     (
      ID    INTEGER     NOT NULL,
      CTXT  VARCHAR(10) NOT NULL )
PRIMARY INDEX ( ID );

CREATE SET TABLE MY_DB.PRUEBA02 ,
     NO FALLBACK ,
     NO BEFORE JOURNAL,
     NO AFTER JOURNAL,
     CHECKSUM = DEFAULT
     (
      ID    INTEGER     NOT NULL,
      CTXT  VARCHAR(10) NOT NULL )
PRIMARY INDEX ( ID );

 *** Table has been created.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:

INSERT INTO MY_DB.PRUEBA01 (ID, CTXT) VALUES (1, 'UNO');

INSERT INTO MY_DB.PRUEBA01 (ID, CTXT) VALUES (1, 'UNO');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
INSERT INTO MY_DB.PRUEBA01 (ID, CTXT) VALUES (2, 'DOS');

INSERT INTO MY_DB.PRUEBA01 (ID, CTXT) VALUES (2, 'DOS');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
INSERT INTO MY_DB.PRUEBA01 (ID, CTXT) VALUES (3, 'TRES');

INSERT INTO MY_DB.PRUEBA01 (ID, CTXT) VALUES (3, 'TRES');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:

INSERT INTO MY_DB.PRUEBA02 (ID, CTXT) VALUES (1, 'ONE');

INSERT INTO MY_DB.PRUEBA02 (ID, CTXT) VALUES (1, 'ONE');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
INSERT INTO MY_DB.PRUEBA02 (ID, CTXT) VALUES (2, 'TWO');

INSERT INTO MY_DB.PRUEBA02 (ID, CTXT) VALUES (2, 'TWO');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
INSERT INTO MY_DB.PRUEBA02 (ID, CTXT) VALUES (3, 'THREE');

INSERT INTO MY_DB.PRUEBA02 (ID, CTXT) VALUES (3, 'THREE');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:</pre>
<p>Las tablas quedan tal que así:</p>
<pre> BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT *
  FROM MY_DB.PRUEBA01;

SELECT *
  FROM MY_DB.PRUEBA01;

 *** Query completed. 3 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

         ID  CTXT
-----------  ----------
          2  DOS
          3  TRES
          1  UNO

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT *
  FROM MY_DB.PRUEBA02;

SELECT *
  FROM MY_DB.PRUEBA02;

 *** Query completed. 3 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

         ID  CTXT
-----------  ----------
          2  TWO
          3  THREE
          1  ONE

 BTEQ -- Enter your DBC/SQL request or BTEQ command:</pre>
<p>Ahora vamos con la query: un &#8216;OUTER JOIN&#8217; ANSI con una condición &#8216;WHERE&#8217;:</p>
<pre> BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT a.ID,
       a.CTXT,
       b.CTXT
  FROM MY_DB.PRUEBA01 a
  LEFT OUTER JOIN MY_DB.PRUEBA02 b
             ON a.ID = b.ID
 WHERE a.ID &gt; 1;

SELECT a.ID,
       a.CTXT,
       b.CTXT
  FROM MY_DB.PRUEBA01 a
  LEFT OUTER JOIN MY_DB.PRUEBA02 b
             ON a.ID = b.ID
 WHERE a.ID &gt; 1;

 *** Query completed. 2 rows found. 3 columns returned.
 *** Total elapsed time was 1 second.

         ID  CTXT        CTXT
-----------  ----------  ----------
          2  DOS         TWO
          3  TRES        THREE</pre>
<p>OK. Ahora vamos a escribir la misma<em> &#8216;query&#8217;</em> de otra manera para obtener los mismos resultados:</p>
<pre> BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT a.ID,
       a.CTXT,
       b.CTXT
  FROM MY_DB.PRUEBA01 a
  LEFT OUTER JOIN MY_DB.PRUEBA02 b
             ON a.ID = b.ID
   AND a.ID &gt; 1;

SELECT a.ID,
       a.CTXT,
       b.CTXT
  FROM MY_DB.PRUEBA01 a
  LEFT OUTER JOIN MY_DB.PRUEBA02 b
             ON a.ID = b.ID
   AND a.ID &gt; 1;

 *** Query completed. 3 rows found. 3 columns returned.
 *** Total elapsed time was 1 second.

         ID  CTXT        CTXT
-----------  ----------  ----------
          2  DOS         TWO
          3  TRES        THREE
          1  UNO         (null)

 BTEQ -- Enter your DBC/SQL request or BTEQ command:</pre>
<p>¿Cómo? ¡Aparece una última línea que no debería aparecer! ¿Qué es esto? ¿Acaso un &#8216;bug&#8217; de Teradata? No. No hay nada errónero en el resultado, lo erróneo está en nuestra cabeza y lo que esperamos ver. Quizá apereca más claro si lo escribimos así:</p>
<pre> BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT a.ID,
       a.CTXT,
       b.CTXT
  FROM MY_DB.PRUEBA01 a
  LEFT OUTER JOIN MY_DB.PRUEBA02 b
             ON ( a.ID = b.ID
                  AND
                  a.ID &gt; 1 )
;

SELECT a.ID,
       a.CTXT,
       b.CTXT
  FROM MY_DB.PRUEBA01 a
  LEFT OUTER JOIN MY_DB.PRUEBA02 b
             ON ( a.ID = b.ID
                  AND
                  a.ID &gt; 1 )
;

 *** Query completed. 3 rows found. 3 columns returned.
 *** Total elapsed time was 1 second.

         ID  CTXT        CTXT
-----------  ----------  ----------
          2  DOS         TWO
          3  TRES        THREE
          1  UNO         (null)</pre>
<p>Ahora se ilumina una lucecilla y empezamos a ver qué es lo que está pasando: Teradata tiene razón y está simplemente siguiendo las reglas y mecanismos de los <em>&#8216;outer joins&#8217;</em>. En el primer ejemplo efectúa un<em> &#8216;outer join&#8217;</em> con la condición &#8216;ON a.ID = b.ID&#8217; y a este resultado le aplica el filtro del<em> &#8216;where&#8217;</em>: &#8216;WHERE a.ID &gt; 1&#8242;, donde se elimina la fila correspondiente a a.ID = 1.</p>
<p>En el segundo ejemplo combina <strong>todas las filas</strong> de la tabla MY_DB.PRUEBA01 a con las de la tabla MY_DB.PRUEBA02 b <strong>y las que no cumplen la condición</strong> (aquí es donde está la trampa) &#8216;AND a.ID &gt; 1&#8242; <strong>les asigna filas &#8216;nulas&#8217;</strong> de MY_DB.PRUEBA02 b. De ahí que aparezca la fila &#8220;1, &#8216;UNO&#8217;, (null)&#8221;: No hay filtro que elimine luego esa fila.</p>
<p>Así que las partículas &#8216;WHERE a.ID &gt; 1&#8242; y &#8216;AND a.ID &gt; 1&#8242; aunque parezcan iguales, no lo son.</p>
<p>Esto no es algo propio de Teradata. Oracle funciona de la misma manera:</p>
<pre>SQL*Plus: Release 10.2.0.1.0 - Production on Mié Jun 3 11:33:20 2009

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

Introduzca el nombre de usuario: carlos@XE.localhost
Introduzca la contraseña:

Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

CARLOS@XE.localhost&gt; CREATE TABLE PRUEBA01(IDN INTEGER NOT NULL,
  2                        CTXT  VARCHAR2(10) NOT NULL,
  3                        CONSTRAINT PRUEBA01_PK PRIMARY KEY(IDN)
  4                        )
  5  ;

Tabla creada.

CARLOS@XE.localhost&gt; CREATE TABLE PRUEBA02(IDN INTEGER NOT NULL,
  2                        CTXT  VARCHAR2(10) NOT NULL,
  3                        CONSTRAINT PRUEBA02_PK PRIMARY KEY(IDN)
  4                        )
  5  ;

Tabla creada.

CARLOS@XE.localhost&gt; INSERT INTO PRUEBA01(IDN, CTXT) VALUES (1,'UNO');

1 fila creada.

CARLOS@XE.localhost&gt; INSERT INTO PRUEBA01(IDN, CTXT) VALUES (2,'DOS');

1 fila creada.

CARLOS@XE.localhost&gt; INSERT INTO PRUEBA01(IDN, CTXT) VALUES (3,'TRES');

1 fila creada.

CARLOS@XE.localhost&gt;
CARLOS@XE.localhost&gt; INSERT INTO PRUEBA02(IDN, CTXT) VALUES (1,'ONE');

1 fila creada.

CARLOS@XE.localhost&gt; INSERT INTO PRUEBA02(IDN, CTXT) VALUES (2,'TWO');

1 fila creada.

CARLOS@XE.localhost&gt; INSERT INTO PRUEBA02(IDN, CTXT) VALUES (3,'THREE');

1 fila creada.

CARLOS@XE.localhost&gt; commit;

Confirmación terminada.

CARLOS@XE.localhost&gt; SELECT a.IDN,
  2         a.CTXT,
  3         b.CTXT
  4    FROM PRUEBA01 a
  5    LEFT OUTER JOIN PRUEBA02 b
  6               ON a.IDN = b.IDN
  7   WHERE a.IDN &gt; 1;

       IDN CTXT       CTXT
---------- ---------- ----------
         2 DOS        TWO
         3 TRES       THREE

CARLOS@XE.localhost&gt; SELECT a.IDN,
  2         a.CTXT,
  3         b.CTXT
  4    FROM PRUEBA01 a
  5    LEFT OUTER JOIN PRUEBA02 b
  6               ON a.IDN = b.IDN
  7     AND a.IDN &gt; 1;

       IDN CTXT       CTXT
---------- ---------- ----------
         1 UNO
         2 DOS        TWO
         3 TRES       THREE</pre>
<p>Por último, los &#8216;oracleros&#8217; pueden ver a cual de las dos sintaxis ANSI corresponde su sintaxis nativa:</p>
<pre>CARLOS@XE.localhost&gt; SELECT a.IDN,
  2         a.CTXT,
  3         b.CTXT
  4    FROM PRUEBA01 a,
  5         PRUEBA02 b
  6   WHERE a.IDN = b.IDN(+)
  7     AND a.IDN &gt; 1;

       IDN CTXT       CTXT
---------- ---------- ----------
         2 DOS        TWO
         3 TRES       THREE

CARLOS@XE.localhost&gt;</pre>
<p>En efecto: con la &#8216;buena&#8217;: aquí el &#8216;AND&#8217; se considera en el &#8216;WHERE&#8217;.</p>
<p>Saludos.</p>
<p>Carlos.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/carlosal.wordpress.com/357/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/carlosal.wordpress.com/357/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/carlosal.wordpress.com/357/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/carlosal.wordpress.com/357/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/carlosal.wordpress.com/357/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/carlosal.wordpress.com/357/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/carlosal.wordpress.com/357/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/carlosal.wordpress.com/357/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/carlosal.wordpress.com/357/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/carlosal.wordpress.com/357/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=357&subd=carlosal&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://carlosal.wordpress.com/2009/06/03/ansi-outer-joins-parecido-no-es-igual/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d45c1082325971d1aaa6a1ad13d2620?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">carlosal</media:title>
		</media:content>
	</item>
		<item>
		<title>Oracle compra Sun (II)</title>
		<link>http://carlosal.wordpress.com/2009/04/21/oracle-compra-sun-ii/</link>
		<comments>http://carlosal.wordpress.com/2009/04/21/oracle-compra-sun-ii/#comments</comments>
		<pubDate>Tue, 21 Apr 2009 18:22:56 +0000</pubDate>
		<dc:creator>carlosal</dc:creator>
				<category><![CDATA[Desarrollo Software]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://carlosal.wordpress.com/?p=338</guid>
		<description><![CDATA[La nota oficial aquí.
Me temo que corren malos tiempos para MySQL&#8230;
Saludos.
Carlos.
       <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=338&subd=carlosal&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>La nota oficial <a href="http://www.oracle.com/sun/index.html">aquí.</a></p>
<p>Me temo que corren malos tiempos para MySQL&#8230;</p>
<p>Saludos.</p>
<p>Carlos.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/carlosal.wordpress.com/338/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/carlosal.wordpress.com/338/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/carlosal.wordpress.com/338/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/carlosal.wordpress.com/338/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/carlosal.wordpress.com/338/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/carlosal.wordpress.com/338/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/carlosal.wordpress.com/338/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/carlosal.wordpress.com/338/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/carlosal.wordpress.com/338/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/carlosal.wordpress.com/338/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=338&subd=carlosal&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://carlosal.wordpress.com/2009/04/21/oracle-compra-sun-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d45c1082325971d1aaa6a1ad13d2620?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">carlosal</media:title>
		</media:content>
	</item>
		<item>
		<title>¡¡Oracle compra Sun!!</title>
		<link>http://carlosal.wordpress.com/2009/04/20/%c2%a1%c2%a1oracle-compra-sun/</link>
		<comments>http://carlosal.wordpress.com/2009/04/20/%c2%a1%c2%a1oracle-compra-sun/#comments</comments>
		<pubDate>Mon, 20 Apr 2009 16:02:23 +0000</pubDate>
		<dc:creator>carlosal</dc:creator>
				<category><![CDATA[Desarrollo Software]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://carlosal.wordpress.com/?p=335</guid>
		<description><![CDATA[¡Oracle compra Sun microsystems por 7.400 Millones de dólares!
Más información: aquí, aquí, aquí y aquí.
¿Qué será lo próximo? ¿unbreakable solaris?
Saludos.
Carlos.
       <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=335&subd=carlosal&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>¡Oracle compra Sun microsystems por 7.400 Millones de dólares!</p>
<p>Más información: <a href="http://www.theregister.co.uk/2009/04/20/oracle_buys_sun/">aquí</a>, <a href="http://www.eleconomista.es/telecomunicaciones-tecnologia/noticias/1179833/04/09/Oracle-to-buy-Sun-Micro-for-74-billion.html">aquí</a>, <a href="http://www.forbes.com/2009/04/20/oracle-sun-microsystems-markets-equity-takeover.html">aquí</a> y <a href="http://news.yahoo.com/s/ap/20090420/ap_on_bi_ge/oracle_sun">aquí</a>.</p>
<p>¿Qué será lo próximo? ¿unbreakable solaris?</p>
<p>Saludos.</p>
<p>Carlos.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/carlosal.wordpress.com/335/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/carlosal.wordpress.com/335/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/carlosal.wordpress.com/335/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/carlosal.wordpress.com/335/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/carlosal.wordpress.com/335/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/carlosal.wordpress.com/335/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/carlosal.wordpress.com/335/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/carlosal.wordpress.com/335/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/carlosal.wordpress.com/335/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/carlosal.wordpress.com/335/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=335&subd=carlosal&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://carlosal.wordpress.com/2009/04/20/%c2%a1%c2%a1oracle-compra-sun/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d45c1082325971d1aaa6a1ad13d2620?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">carlosal</media:title>
		</media:content>
	</item>
		<item>
		<title>LPAD() en Teradata</title>
		<link>http://carlosal.wordpress.com/2009/04/07/lpad-en-teradata/</link>
		<comments>http://carlosal.wordpress.com/2009/04/07/lpad-en-teradata/#comments</comments>
		<pubDate>Tue, 07 Apr 2009 16:49:34 +0000</pubDate>
		<dc:creator>carlosal</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Teradata]]></category>

		<guid isPermaLink="false">http://carlosal.wordpress.com/?p=331</guid>
		<description><![CDATA[Siguiendo con lo que vimos en RPAD() en Teradata, para conseguir los resultados del LPAD() de Oracle en Teradata basta con concatenar la cadena sobre la que queremos el &#8216;LPAD()&#8217; con una cadena con el caracter de relleno de la longitud deseada en el LPAD() y tomando un &#8216;substring&#8216; desde la posición de la longitud [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=331&subd=carlosal&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Siguiendo con lo que vimos en <a href="http://carlosal.wordpress.com/2009/03/31/rpad-en-teradata/">RPAD() en Teradata</a>, para conseguir los resultados del LPAD() de Oracle en Teradata basta con concatenar la cadena sobre la que queremos el &#8216;LPAD()&#8217; con una cadena con el caracter de relleno de la longitud deseada en el LPAD() y tomando un &#8216;<em>substring</em>&#8216; desde la posición de la longitud de la cadena (para ello usaremos la función &#8216;CHARACTERS()&#8217; de Teradata) más uno .</p>
<p>Ejemplo: LPAD() para rellenar a ceros por la izquierda hasta cinco posiciones.</p>
<pre>
 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT SUBSTR('00000'||'19',CHARACTERS('19')+1) "LPAD('19',5,'0')";

SELECT SUBSTR('00000'||'19',CHARACTERS('19')+1) "LPAD('19',5,'0')";

 *** Query completed. One row found. One column returned.
 *** Total elapsed time was 1 second.

LPAD('19',5,'0')
----------------
00019

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT SUBSTR('00000'||'2119',CHARACTERS('2119')+1) "LPAD('2119',5,'0')";

SELECT SUBSTR('00000'||'2119',CHARACTERS('2119')+1) "LPAD('2119',5,'0')";

 *** Query completed. One row found. One column returned.
 *** Total elapsed time was 1 second.

LPAD('2119',5,'0')
------------------
02119

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT SUBSTR('00000'||'319',CHARACTERS('319')+1) "LPAD('319',5,'0')";

SELECT SUBSTR('00000'||'319',CHARACTERS('319')+1) "LPAD('319',5,'0')";

 *** Query completed. One row found. One column returned.
 *** Total elapsed time was 1 second.

LPAD('319',5,'0')
-----------------
00319
</pre>
<p>Saludos.</p>
<p>Carlos.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/carlosal.wordpress.com/331/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/carlosal.wordpress.com/331/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/carlosal.wordpress.com/331/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/carlosal.wordpress.com/331/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/carlosal.wordpress.com/331/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/carlosal.wordpress.com/331/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/carlosal.wordpress.com/331/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/carlosal.wordpress.com/331/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/carlosal.wordpress.com/331/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/carlosal.wordpress.com/331/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=carlosal.wordpress.com&blog=235816&post=331&subd=carlosal&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://carlosal.wordpress.com/2009/04/07/lpad-en-teradata/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d45c1082325971d1aaa6a1ad13d2620?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">carlosal</media:title>
		</media:content>
	</item>
	</channel>
</rss>