<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-22727713</id><updated>2011-07-29T06:33:21.736+03:00</updated><category term='statistics oracle'/><category term='oracle training'/><category term='gplivna.eu'/><category term='Oracle SQL Server Express Edition'/><category term='Development process'/><category term='drop source code flashback'/><title type='text'>Gints Plivna blog</title><subtitle type='html'>These are my thoughts... Mostly about &lt;a href = "http://www.oracle.com"&gt;Oracle&lt;/a&gt; and related things.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>36</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-22727713.post-6372983445920774152</id><published>2011-03-12T02:21:00.005+02:00</published><updated>2011-03-12T04:53:45.019+02:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Indexes cannot be used for inequalities?&lt;/h3&gt;&lt;br /&gt;For years and years I thought it was true. Now I'd say it's only partially true. OK &lt;b&gt;it is&lt;/b&gt; true for b-tree indexes (at least there isn't any reasonable effect of using an index for "not eaquals to"), but for bitmaps it's a different answer though. And I mean generally YES, they can be used :)&lt;br /&gt;&lt;br /&gt;OK let's look at examples. I'll create a table and populate with almost all the same values but one. That's to make things more attractive for CBO to get the one and only value.&lt;br /&gt;&lt;pre&gt;SQL&gt; CREATE TABLE test (&lt;br /&gt;2    id NUMBER PRIMARY KEY,&lt;br /&gt;3    txt VARCHAR2(10) NOT NULL);&lt;br /&gt;&lt;br /&gt;Table created.&lt;br /&gt;&lt;br /&gt;SQL&gt; INSERT INTO test&lt;br /&gt;2  SELECT rownum, 'AAA'&lt;br /&gt;3  FROM DUAL CONNECT BY LEVEL &lt; 10000;&lt;br /&gt;&lt;br /&gt;9999 rows created.&lt;br /&gt;&lt;br /&gt;SQL&gt; INSERT INTO test&lt;br /&gt;2  VALUES (10000, 'BBB');&lt;br /&gt;&lt;br /&gt;1 row created.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So now I have 9999 of "AAA" and only one "BBB".&lt;br /&gt;I won't explain with examples what one can get with b-tree indexes, the best is INDEX FULL SCAN and &lt;a href="http://richardfoote.wordpress.com/2008/08/13/indexes-and-not-equal-not-now-john/"&gt;the example by Richard Foote is here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;OK but what if we try bitmap index? Let's create it:&lt;br /&gt;&lt;pre&gt;SQL&gt; CREATE BITMAP INDEX txt_idx ON test (txt) COMPUTE STATISTICS;&lt;br /&gt;&lt;br /&gt;Index created.&lt;/pre&gt;&lt;br /&gt;Now let's see what we get for the query we know should get only 1 row:&lt;br /&gt;&lt;pre&gt;SQL&gt; SELECT * FROM test&lt;br /&gt; 2  WHERE txt &lt;&gt; 'AAA';&lt;br /&gt;&lt;br /&gt;       ID TXT&lt;br /&gt;---------- ----------&lt;br /&gt;    10000 BBB&lt;br /&gt;&lt;br /&gt;--------------------------------------------------------------------------&lt;br /&gt;| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;--------------------------------------------------------------------------&lt;br /&gt;|   0 | SELECT STATEMENT  |      |     1 |     7 |     7   (0)| 00:00:01 |&lt;br /&gt;|*  1 |  TABLE ACCESS FULL| TEST |     1 |     7 |     7   (0)| 00:00:01 |&lt;br /&gt;--------------------------------------------------------------------------&lt;br /&gt;Predicate Information (identified by operation id):&lt;br /&gt;---------------------------------------------------&lt;br /&gt;&lt;br /&gt;  1 - filter("TXT"&lt;&gt;'AAA')&lt;br /&gt;&lt;br /&gt;Statistics&lt;br /&gt;----------------------------------------------------------&lt;br /&gt;        23  consistent gets&lt;br /&gt;         1  rows processed&lt;/pre&gt;&lt;br /&gt;Bang! Full scan. Not very promising. OK what if we try to hint the query?&lt;br /&gt;At first let's give a soft hint - how about using an index?&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; SELECT /*+ index(test) */ * FROM test&lt;br /&gt;  2  WHERE txt &lt;&gt; 'AAA';&lt;br /&gt;&lt;br /&gt;        ID TXT&lt;br /&gt;---------- ----------&lt;br /&gt;     10000 BBB&lt;br /&gt;&lt;br /&gt;--------------------------------------------------------------------------------&lt;br /&gt;| Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|&lt;br /&gt;--------------------------------------------------------------------------------&lt;br /&gt;|   0 | SELECT STATEMENT            |             |     1 |     7 |   826   (0)|&lt;br /&gt;|*  1 |  TABLE ACCESS BY INDEX ROWID| TEST        |     1 |     7 |   826   (0)|&lt;br /&gt;|   2 |   INDEX FULL SCAN           | SYS_C009499 | 10000 |       |    26   (0)|&lt;br /&gt;--------------------------------------------------------------------------------&lt;br /&gt;Predicate Information (identified by operation id):&lt;br /&gt;---------------------------------------------------&lt;br /&gt;   1 - filter("TXT"&lt;&gt;'AAA')&lt;br /&gt;Statistics&lt;br /&gt;----------------------------------------------------------&lt;br /&gt;         39  consistent gets&lt;br /&gt;          1  rows processed&lt;/pre&gt;&lt;br /&gt;WoW! That's actually annoying. Bad plan, many consistent gets. Oracle is using primary key index, but not my brand new bitmap index! I'm disappointed.&lt;br /&gt;OK now let's hammer it with the precise hint!&lt;br /&gt;&lt;pre&gt;SQL&gt; SELECT /*+ index(test txt_idx) */ * FROM test&lt;br /&gt;  2  WHERE txt &lt;&gt; 'AAA';&lt;br /&gt;&lt;br /&gt;        ID TXT&lt;br /&gt;---------- ----------&lt;br /&gt;     10000 BBB&lt;br /&gt;&lt;br /&gt;-----------------------------------------------------------------------------&lt;br /&gt;| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)|&lt;br /&gt;-----------------------------------------------------------------------------&lt;br /&gt;|   0 | SELECT STATEMENT             |         |     1 |     7 |    36   (0)|&lt;br /&gt;|   1 |  TABLE ACCESS BY INDEX ROWID | TEST    |     1 |     7 |    36   (0)|&lt;br /&gt;|   2 |   BITMAP CONVERSION TO ROWIDS|         |       |       |            |&lt;br /&gt;|*  3 |    BITMAP INDEX FULL SCAN    | TXT_IDX |       |       |            |&lt;br /&gt;-----------------------------------------------------------------------------&lt;br /&gt;Predicate Information (identified by operation id):&lt;br /&gt;---------------------------------------------------&lt;br /&gt;   3 - filter("TXT"&lt;&gt;'AAA')&lt;br /&gt;&lt;br /&gt;Statistics&lt;br /&gt;----------------------------------------------------------&lt;br /&gt;          2  consistent gets&lt;br /&gt;          1  rows processed&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So that's it!! At last we get it! Only 2 consistent gets. And the cost is much less than using that stupid primary key index full scan. So that means Oracle even didn't consider using this plan at least for the query with just index hint. I looked at 10053 trace and found following for the query with just hint "index(test)":&lt;br /&gt;The beginning looks promising:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Table Stats::&lt;br /&gt;  Table: TEST  Alias:  A&lt;br /&gt;    #Rows: 10000  #Blks:  20  AvgRowLen:  7.00&lt;br /&gt;Index Stats::&lt;br /&gt;  Index: SYS_C009499  Col#: 1    (NOT ANALYZED)&lt;br /&gt;    LVLS: 1  #LB: 25  #DK: 100  LB/K: 1.00  DB/K: 1.00  CLUF: 800.00&lt;br /&gt;    &lt;b&gt;User hint to use this index&lt;/b&gt;&lt;br /&gt;  Index: TXT_IDX  Col#: 2&lt;br /&gt;    LVLS: 0  #LB: 1  #DK: 2  LB/K: 1.00  DB/K: 1.00  CLUF: 2.00&lt;br /&gt;    &lt;b&gt;User hint to use this index&lt;/b&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;However in access path analysis Oracle simply doesn't even consider my bitmap index.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SINGLE TABLE ACCESS PATH&lt;br /&gt;  Single Table Cardinality Estimation for TEST[A]&lt;br /&gt;  Table: TEST  Alias: A&lt;br /&gt;    Card: Original: 10000.000000  Rounded: 1  Computed: 1.00  Non Adjusted: 1.00&lt;br /&gt;  Access Path: index (FullScan)&lt;br /&gt;    Index: SYS_C009499&lt;br /&gt;    resc_io: 826.00  resc_cpu: 6932309&lt;br /&gt;    ix_sel: 1.000000  ix_sel_with_filters: 1.000000&lt;br /&gt;    Cost: 826.39  Resp: 826.39  Degree: 1&lt;br /&gt;  Best:: AccessPath: IndexRange&lt;br /&gt;  Index: SYS_C009499&lt;br /&gt;         Cost: 826.39  Degree: 1  Resp: 826.39  Card: 1.00  Bytes: 0&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Things however get brighter if we are just counting rows, then we don't need hint or anything, just run the select:&lt;br /&gt;&lt;pre&gt;SQL&gt; SELECT count(*) FROM test&lt;br /&gt;  2  WHERE txt &lt;&gt; 'AAA';&lt;br /&gt;&lt;br /&gt;  COUNT(*)&lt;br /&gt;----------&lt;br /&gt;         1&lt;br /&gt;&lt;br /&gt;------------------------------------------------------------------------------&lt;br /&gt;| Id  | Operation                     | Name    | Rows  | Bytes | Cost (%CPU)|&lt;br /&gt;------------------------------------------------------------------------------&lt;br /&gt;|   0 | SELECT STATEMENT              |         |     1 |     4 |     1   (0)|&lt;br /&gt;|   1 |  SORT AGGREGATE               |         |     1 |     4 |            |&lt;br /&gt;|   2 |   BITMAP CONVERSION COUNT     |         |     1 |     4 |     1   (0)|&lt;br /&gt;|*  3 |    BITMAP INDEX FAST FULL SCAN| TXT_IDX |       |       |            |&lt;br /&gt;------------------------------------------------------------------------------&lt;br /&gt;Statistics&lt;br /&gt;----------------------------------------------------------&lt;br /&gt;          3  consistent gets&lt;br /&gt;          1  rows processed&lt;/pre&gt;&lt;br /&gt;So it is more or less OK that table full scan is better (i.e. cost less than) bitmap index full scan and then bitmap conversion to rowids and then access table by calculated rowids. However it is quite strange that for simple index hint Oracle doesn't even consider this access path however as we can see from CBO trace understands that bitmap index is one of the hinted ones.&lt;br /&gt;Of course the usual problems with bitmap indexes remains - locking, concurrency issues etc.&lt;br /&gt;And yea I just arrived from &lt;a href="http://richardfoote.wordpress.com/oracle-index-internals-seminar/"&gt;Richard's seminar&lt;/a&gt; in Tallinn. Many new things, fluent story, cool!! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-6372983445920774152?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/6372983445920774152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=6372983445920774152' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/6372983445920774152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/6372983445920774152'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2011/03/indexes-cannot-be-used-for-inequalities.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-4357062829056702195</id><published>2010-02-17T16:58:00.002+02:00</published><updated>2010-02-17T17:44:53.716+02:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Unbreakable Oracle documentation&lt;/h3&gt;&lt;br /&gt;Yes, that's the fact - everyone knowing the real situation will start Homeric laughter. It is down, down, down and down again. To be true sometimes it is also up and running. Unfortunately "sometimes" seems to be more and more rarely. Just now the popular entry point &lt;a href="http://tahiti.oracle.com/"&gt;tahiti.oracle.com&lt;/a&gt; shows following:&lt;br /&gt;&lt;br /&gt;Access Denied&lt;br /&gt;You don't have permission to access "http://www-portal-stage.oracle.com/splash/www/index.html" on this server.&lt;br /&gt;Reference #18.3c55293e.1266419217.19d36a&lt;br /&gt;&lt;br /&gt;Interesting - is tooooo much to ask Oracle to provide just static htmls (OK there is advanced thing - search feature, however I could also easily use Google instead, at least it is less unbreakable ;) for its users continuously without interruptions more than not?&lt;br /&gt;Or after the &lt;a href="http://www.informationweek.com/news/global-cio/security/showArticle.jhtml?articleID=222002898&amp;amp;cid=nl_IW_btl_2010-01-05_t"&gt;grand results of maintenance income&lt;/a&gt; there isn't any single $ left for an admin to monitor the resource? Or probably the last reliable box has gone to super functional and alike working &lt;a href="https://support.oracle.com/CSP/ui/flash.html"&gt;MOS&lt;/a&gt;?&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Chris Warticki &lt;a href="http://blogs.oracle.com/Support/"&gt;in his blog&lt;/a&gt; wrote what to do if MOS is down then what? Unfortunately the blog now is (seems to be censored and) closed and for a little while &lt;a href="http://209.85.135.132/search?q=cache:Tbd0DOljVmkJ:blogs.oracle.com/Support/2010/02/if_mos_is_down_then_what.html+site:blogs.oracle.com+my+oracle+support+blog&amp;amp;cd=8&amp;amp;hl=lv&amp;amp;ct=clnk&amp;amp;gl=lv"&gt;pages are only accessible from google's cache&lt;/a&gt;. Most of the people in oracle-l list say &lt;a href="http://www.freelists.org/post/oracle-l/Oracle-documentation,6"&gt;they have downloaded oracle documentation locally&lt;/a&gt; in a &lt;a href="http://www.freelists.org/post/oracle-l/Oracle-documentation,3"&gt;recent discussion about oracle documentation&lt;/a&gt;. However it is bit odd for a company providing leading database of the world having income with nine zeroes being unable to provide simple html files without continued interruptions... &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Probably that's the reason I more and more have to do something with SQL Server :)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-4357062829056702195?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/4357062829056702195/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=4357062829056702195' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/4357062829056702195'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/4357062829056702195'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2010/02/unbreakable-oracle-documentation-yes.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-6612460016606283960</id><published>2009-02-07T19:32:00.010+02:00</published><updated>2009-02-08T16:19:01.114+02:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Woodwork&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Time after time I'm doing something different than databases and Oracle :) One of these things is woodwork. So around the New Year I finished the most recent one - a shelf. &lt;em&gt;Requirements, design and implementation&lt;/em&gt; fully by me. Here it is just attached to the wall.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_8yYAHvkcUVA/SY3Mws7vehI/AAAAAAAAAHc/2nwYJp77NVI/s1600-h/shelf_1.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5300117473552464402" style="WIDTH: 400px; HEIGHT: 300px" alt="wood shelf" src="http://1.bp.blogspot.com/_8yYAHvkcUVA/SY3Mws7vehI/AAAAAAAAAHc/2nwYJp77NVI/s400/shelf_1.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;And now full with stuff. Most of pottery in this shelf is produced by my cousin and her husband.&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_8yYAHvkcUVA/SY3P5TXm7LI/AAAAAAAAAHk/-pkj9JEjfew/s1600-h/shelf_2.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5300120919843728562" style="WIDTH: 400px; HEIGHT: 300px" alt="wood shelf" src="http://3.bp.blogspot.com/_8yYAHvkcUVA/SY3P5TXm7LI/AAAAAAAAAHk/-pkj9JEjfew/s400/shelf_2.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The hobby started already in school years when we had special woodwork lessons and this probably is one of the best results from these times - a turned wood vessel with amber decor on the top.&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_8yYAHvkcUVA/SY3X190cBFI/AAAAAAAAAHs/oSUhtiQjRzg/s1600-h/wood_vessel.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5300129658612483154" style="WIDTH: 400px; CURSOR: hand; HEIGHT: 300px" alt="turned wood vessel" src="http://3.bp.blogspot.com/_8yYAHvkcUVA/SY3X190cBFI/AAAAAAAAAHs/oSUhtiQjRzg/s400/wood_vessel.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Nowadays there are fantastic possibilities to make something from wood on his own compared to Soviet and early post-Soviet times. Tools, paints, lacquers, various components and semi-finished products in shops are far and away more. For example the shelf above also was created using ground glued board, so actually the creation process is not complicated. &lt;br /&gt;One of the most interesting tasks was to restore a few Soviet style chairs as old as myself (i.e ~30 years). Here is a photo with one old chair and one already restored.&lt;/p&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_8yYAHvkcUVA/SY7nFuxjuAI/AAAAAAAAAH0/-CZy0HzYiFY/s1600-h/chairs.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5300427897102907394" style="WIDTH: 400px; CURSOR: hand; HEIGHT: 268px" alt="Chairs" src="http://2.bp.blogspot.com/_8yYAHvkcUVA/SY7nFuxjuAI/AAAAAAAAAH0/-CZy0HzYiFY/s400/chairs.jpg" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-6612460016606283960?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/6612460016606283960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=6612460016606283960' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/6612460016606283960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/6612460016606283960'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2009/02/woodwork-time-after-time-im-doing.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_8yYAHvkcUVA/SY3Mws7vehI/AAAAAAAAAHc/2nwYJp77NVI/s72-c/shelf_1.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-5245488827331529484</id><published>2009-01-31T22:46:00.002+02:00</published><updated>2009-02-01T00:21:59.880+02:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Security through obscurity - object names&lt;/h3&gt;&lt;br /&gt;This post was inspired by question in one of Latvian forums - can we use only numbers in column names. Of course we can do it using quotes but that's starting point into dangerous path of &lt;a href="http://www.web-hits.org/txt/codingunmaintainable.html"&gt;how to write unmaintainable code&lt;/a&gt;. But why stop only with tables like C34 and columns 1, 2, 3? There are ways beyond that!&lt;br /&gt;So let's start with the same table names differing only in upper/lower case.&lt;br /&gt;&lt;pre&gt;SQL&amp;gt; create table A (big number);&lt;br /&gt;Table created.&lt;br /&gt;SQL&amp;gt; create table "a" (small number);&lt;br /&gt;Table created.&lt;/pre&gt;&lt;br /&gt;So what are our tables A and a:&lt;br /&gt;&lt;pre&gt;SQL&amp;gt; desc A&lt;br /&gt; Name                    Null?    Type&lt;br /&gt; ----------------------- -------- -------&lt;br /&gt; BIG                              NUMBER&lt;br /&gt;SQL&amp;gt; desc a&lt;br /&gt; Name                    Null?    Type&lt;br /&gt; ----------------------- -------- -------&lt;br /&gt; BIG                              NUMBER&lt;/pre&gt;&lt;br /&gt;A bit strange, isn't it? But that is because all nonquoted identifiers are converted to uppercase so we have to be precise:&lt;br /&gt;&lt;pre&gt;SQL&amp;gt; desc "a"&lt;br /&gt; Name                    Null?    Type&lt;br /&gt; ----------------------- -------- ------&lt;br /&gt; SMALL                            NUMBER&lt;/pre&gt;&lt;br /&gt;But we can make things even more obscure! For example how about table and/or column name as space?&lt;br /&gt;&lt;pre&gt;SQL&gt; create table " " (A number, "a" number);&lt;br /&gt;Table created.&lt;br /&gt;SQL&amp;gt; select table_name from user_tables;&lt;br /&gt;TABLE_NAME&lt;br /&gt;------------------------------&lt;br /&gt;a&lt;br /&gt;&lt;br /&gt;A&lt;br /&gt;3 rows selected.&lt;/pre&gt;&lt;br /&gt;Previous example with &lt;i&gt;2 rows instead&lt;/i&gt; of reported three and next with lost columns definitely could make some nervous people start searching for Oracle bugs.&lt;br /&gt;&lt;pre&gt;SQL&amp;gt; create table b (" " number, "  " date);&lt;br /&gt;Table created.&lt;br /&gt;SQL&amp;gt; desc b&lt;br /&gt; Name                    Null?    Type&lt;br /&gt; ----------------------- -------- ------&lt;br /&gt;                                  NUMBER&lt;br /&gt;                                  DATE&lt;/pre&gt;&lt;br /&gt;But we can make things better. Why should we use only symbols on keybord? Remember the nice possibility of ALT key and numeric keypad keys. ALT + these keys gives us symbols according to their ASCII values, so just use your imagination. For example ALT+223 gives me this:&lt;br /&gt;&lt;pre&gt;SQL&amp;gt; create table abnormal ("▀" number);&lt;br /&gt;Table created.&lt;br /&gt;SQL&amp;gt; desc abnormal&lt;br /&gt; Name                    Null?    Type&lt;br /&gt; ----------------------- -------- -------&lt;br /&gt; ▀                                NUMBER&lt;/pre&gt;&lt;br /&gt;Nice little black square.&lt;br /&gt;Next level might be making some columns a bit like &lt;em&gt;hidden&lt;/em&gt;.&lt;br /&gt;&lt;pre&gt;SQL&amp;gt; create table persons (name varchar2(10), "SYSDATE" date);&lt;br /&gt;Table created.&lt;br /&gt;SQL&amp;gt; insert into persons values ('John', sysdate-1);&lt;br /&gt;1 row created.&lt;br /&gt;SQL&amp;gt; select sysdate from dual;&lt;br /&gt;SYSDATE&lt;br /&gt;---------&lt;br /&gt;31-JAN-09&lt;br /&gt;SQL&amp;gt; select name, sysdate from persons;&lt;br /&gt;NAME       SYSDATE&lt;br /&gt;---------- ---------&lt;br /&gt;John       31-JAN-09&lt;/pre&gt;&lt;br /&gt;So where our column sysdate was gone? We inserted value sysdate-1 and got back the same sysdate? Although our column was in upper case, so our query column should be used? Naah, we should enclose it in quotes.&lt;br /&gt;&lt;pre&gt;SQL&amp;gt; select name, "SYSDATE" from persons;&lt;br /&gt;NAME       SYSDATE&lt;br /&gt;---------- ---------&lt;br /&gt;John       30-JAN-09&lt;/pre&gt;&lt;br /&gt;So next time when you are starting to think about table name like C12, numeric column names, column names in quotes or something like that, don't be shy! Use the complete power of obscurity, so making your db more secure. If you'd try hard enough, you'd reach perfection when obscurity is so great that nobody, even you, won't be able to understand anything ;)&lt;br /&gt;And I wasn't even suggesting to replace DUAL in your schema ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-5245488827331529484?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/5245488827331529484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=5245488827331529484' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/5245488827331529484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/5245488827331529484'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2009/01/security-through-obscurity-object-names.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-896887052296696889</id><published>2009-01-09T00:52:00.002+02:00</published><updated>2009-01-09T02:01:46.488+02:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;About experience&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Just a few days ago &lt;a href="http://watsonldsbc.blogspot.com/"&gt;Ryan Watson&lt;/a&gt; mentioned &lt;a href="http://www.gplivna.eu/papers/choose_database.htm"&gt;one of my articles&lt;/a&gt; in &lt;a href="http://watsonldsbc.blogspot.com/2009/01/what-to-consider-when-choosing-database.html"&gt;his blog post&lt;/a&gt;. It really wouldn't be anything important to write about but the first comment by &lt;a href="http://www.blogger.com/profile/01136664173076859679"&gt;Kevin&lt;/a&gt; really amused me and the comment was "Who is this guy and why is he qualified to comment on databases."&lt;br /&gt;&lt;br /&gt;Blahhh... My answer was "[..] why does it matter and isn't better just to make reasonable pros and/or cons about the subject?" and Kevin answered with "Experts carry more weight than a novice; a senior Oracle admin with 20 years of experience has more experience to draw on. This is why a senior DBA will make $100 k and novice $20 k."&lt;br /&gt;&lt;br /&gt;This was something so immediate and direct statement that let me started to think more about this subject. How much experience means to me? How much it means to other people (virtually) around me? Probably we all know one of the brightest stars in this area good old Don with &lt;a href="http://forums.oracle.com/forums/message.jspa?messageID=3197529#3197529"&gt;one of his latest performances here&lt;/a&gt;, but undoubtely for all of us - if we don't know other people and they say something, their experience somehow matters. So how much does it matter for me?&lt;br /&gt;&lt;br /&gt;1. I definitely have positive experience with some people and know their knowledge and writing style. They have credit in my eyes and I read each their article/statement/whatever else with more caution than on average. Even if the beginning of the message is somehow blurry or overall quality is not that perfect this time. They have to "apply efforts" to their articles to make me angry and sceptic.&lt;br /&gt;2. I definitely have negative experience with a few people and know their usually blurry and washy posts without any resultant technical value. They have really minus credits in my eyes and even if this time they have written something technically sound I'm quite suspect about that. They have to write something really, really good to attract my attention other than sigh "usual crap".&lt;br /&gt;3. I definitely have neutral experience with quite a lot of people. Let's say "nothing special" :) I read their articles only when they are directly related to my particular current needs.&lt;br /&gt;4. People whom I've met the first time or haven't made any particular impression. These are the most complex part. What is my attitude to them? Analyzing my usual behaviour the conclusion is - I start reading the article with some interest and few starting paragraphs should attract my attention. They must be interesting or suitable for my needs otherwise I jump to next article. BUT. I've never (OK almost never :) read the author's CV, last rows about the author how cool he is or whatever else describing his experience. The content of the article is what matters for me.&lt;br /&gt;&lt;br /&gt;So people I don't know win over people with negative credit (whose articles I usually even don't read), but lose to people with positive credit (whose articles I usually try to read until the and to find out something valuable).&lt;br /&gt;&lt;br /&gt;And returning to the initial comments - what does 20 years of experience mean to me? Most probably nothing. At least initially. 20 years ago there was Oracle 6, how does it help for today's work? Most probably in almost no way. I'd say that a few years for an inquiring and smart mind is enough to deserve more than a person with 20 years experience stalled in Oracle 8. Actually he wins without any doubt at all.&lt;br /&gt;&lt;br /&gt;The (quality of) content is what matters - this is the conclusion. &lt;em&gt;At least for people I don't know&lt;/em&gt; :)&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-896887052296696889?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/896887052296696889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=896887052296696889' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/896887052296696889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/896887052296696889'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2009/01/about-experience-just-few-days-ago-ryan.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-2174332616802934673</id><published>2008-11-23T15:00:00.003+02:00</published><updated>2008-11-23T16:33:10.283+02:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Advanced Oracle Troubleshooting by Tanel Poder..&lt;/h3&gt;&lt;p&gt;.. is over. &lt;a href="http://blog.tanelpoder.com/seminar/"&gt;His seminar&lt;/a&gt; in Riga was real fun for two days. It was different from the &lt;em&gt;big guys'&lt;/em&gt; seminars I've attended before (for example, &lt;a href="http://asktom.oracle.com/"&gt;Thomas Kyte&lt;/a&gt; and &lt;a href="http://jonathanlewis.wordpress.com/"&gt;Jonathan Lewis&lt;/a&gt;). Not in the way that it was or wasn't somehow better or not, but in the way that Tanel spoke more about:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;internal memory structures (x$ tables), process stacks, Oracle kernel functions and their mapping to SQL statement execution plan steps;&lt;/li&gt;&lt;li&gt;understanding structure of library cache, process state objects, buffer cache;&lt;/li&gt;&lt;li&gt;dumping cursors, trace buffers, process stack;&lt;/li&gt;&lt;li&gt;systematic troubleshooting a session and finding the root cause of slowness and what it is doing now;&lt;/li&gt;&lt;li&gt;and many more subjects.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Lots of live demos, nothing like an Oracle documentation rephrase, narrative explanation of quite advanced technical things - these were the main characteristics of this seminar. &lt;/p&gt;&lt;p&gt;Some previous understanding of Operating systems basic functions, commands and Oracle architecture however is a must, otherwise you simply will be overwhelmed by new information and won't be able to follow the main idea. On the other hand I'm absolutely not a sysadmin and/or &lt;em&gt;true&lt;/em&gt; DBA, but I understood let's say 95% of the material provided ;)&lt;/p&gt;&lt;p&gt;So the conclusion is - I definitely recommend it for the people interested in these topics.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-2174332616802934673?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/2174332616802934673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=2174332616802934673' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/2174332616802934673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/2174332616802934673'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/11/advanced-oracle-troubleshooting-by.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-89211105908667821</id><published>2008-11-20T22:34:00.003+02:00</published><updated>2008-11-21T00:11:16.371+02:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Data modeling&lt;/h3&gt;&lt;p&gt;Time after time it is worth to remember (or learn) basic theory. One of them, which is very important when creating new systems, is data modeling. I'm quite sure most of the DBMS people have seen one or another data model with tables, columns, primary and foreign keys. However the &lt;a href="http://en.wikipedia.org/wiki/Data_modeling"&gt;theory of data modeling&lt;/a&gt; says that this is only &lt;strong&gt;one&lt;/strong&gt; level out of &lt;strong&gt;three&lt;/strong&gt;. Unfortunately I've seen quite many cases when people have forgotten two another levels. So let's remember what they are.&lt;/p&gt;&lt;h4&gt;Conceptual data model&lt;/h4&gt;&lt;p&gt;Conceptual data model contains entities, relationships and attributes. One can draw them using different notations for example ER modeling or UML, but the idea remains the same - this model &lt;strong&gt;doesn't know anything&lt;/strong&gt; about the underlying DBMS. This model &lt;strong&gt;is the same&lt;/strong&gt; for Oracle, SQL Server, DB2, MySQL, whatever else. So why is it important? &lt;/p&gt;&lt;ul&gt;&lt;li&gt;It speaks in business language and uses terms only from business users, not any programmer's or IT person's hacks.&lt;/li&gt;&lt;li&gt;It is normalized, every piece of information is stored only once.&lt;/li&gt;&lt;li&gt;It displays common structures and tries to aggregate them, it is easier to find them in such model.&lt;/li&gt;&lt;li&gt;It is readable (after a short introduction probably) by every sensible customer.&lt;/li&gt;&lt;li&gt;It doesn't contain any reference to any particular DBMS, so one can easily reuse it for ultimately any DBMS.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So the question - have you used it? If not - why? Are you aware of &lt;a href="http://www.gplivna.eu/papers/data_waste_or_data_base.htm"&gt;possible data waste dangers&lt;/a&gt;?&lt;/p&gt;&lt;h4&gt;Logical data model&lt;/h4&gt;&lt;p&gt;This is the model people usually use. It contains tables, columns, primary keys, foreign keys, unique keys. Some characteristics of it are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;It is created on the basis of conceptual data model, but it might not correspond 1:1 to it. For example some entities might be split, some unioned.&lt;/li&gt;&lt;li&gt;It may contain some programmer's hacks for example different flag columns for easier data selection.&lt;/li&gt;&lt;li&gt;It is aware of used DBMS. For example data types for columns &lt;strong&gt;are&lt;/strong&gt; DBMS specific.&lt;/li&gt;&lt;li&gt;It may have denormalized columns (i.e. the same facts stored in more than one column) for performance reasons.&lt;/li&gt;&lt;li&gt;Table and column names might not exactly mimic business terms i.e. they might be abbreviated, changed to conform &lt;a href="http://www.gplivna.eu/papers/naming_conventions.htm"&gt;some naming rules&lt;/a&gt; and/or DBMS restrictions, although for easier readability it is worth to retain some dependency.&lt;/li&gt;&lt;li&gt;It is based on conceptual data model but created &lt;strong&gt;keeping performance and most common possible SQL statements&lt;/strong&gt; in mind.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I'm quite sure you have used it, so the only question is - have you created it keeping performance and business critical SQL in mind?&lt;/p&gt;&lt;h4&gt;Physical data model&lt;/h4&gt;&lt;p&gt;What's that? Is there anything remaining to model at all? Yes it is. Heap table (i.e. table type which is used by default) is not the only available table type in Oracle. Partitioning is not the only option, which can be used in Oracle. So what is modeled here?&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/statements_7002.htm"&gt;Table type&lt;/a&gt; - heap, index organized, clustered, sorted hash cluster, single table hash cluster there are many possible options.&lt;/li&gt;&lt;li&gt;Partitioning, compression, encryption - do you need it, can you afford it?&lt;/li&gt;&lt;li&gt;Indexes - will you use only &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/statements_5011.htm"&gt;b-tree or something more&lt;/a&gt;?&lt;/li&gt;&lt;li&gt;Will you use object tables?&lt;/li&gt;&lt;li&gt;What tablespaces will be created and on what devices/files?&lt;/li&gt;&lt;li&gt;Here comes the real strength (or weakness) of your chosen DBMS - if it offers all these features - why not at least consider them?&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If you are DBA you have definitely used some of the features mentioned above, but have you thought about non-default ones? Have you systematically gone through at least the most business critical tables and considered what kind of table type to use, what kind of indexes create?&lt;/p&gt;&lt;p&gt;Not that I'm suggesting to enforce anything just for the sake of completeness ;) but I'm sure I've read something like that somewhere "If you have only heap tables and b-tree indexes, most probably your schema is not optimal".&lt;/p&gt;&lt;h4&gt;Conclusion&lt;/h4&gt;&lt;p&gt;Sometimes conceptual modeling is called logical and logical physical and then of course question remains how should be called the real "physical modeling", but it is not so important. The important thing is - whatever DBMS you choose for a new application it is worth to go through all the data model steps. Go through the conceptual modeling to better understand your requirements, to better confirm them with your customer, to better find out common patterns. Of course logical modeling cannot be avoided if we'd like to get at least one table, however quite many people forget about referential integrity constraints and rely only on application enforcing it. Sighhhh... And at last don't forget about physical modeling because when your table will contain (hundreds) millions of rows in production it would be much harder to change it's type, move it somewhere else etc. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-89211105908667821?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/89211105908667821/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=89211105908667821' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/89211105908667821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/89211105908667821'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/11/data-modeling-time-after-time-it-is.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-4355778202627530744</id><published>2008-10-14T18:32:00.018+03:00</published><updated>2008-10-19T21:41:03.553+03:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Mortgage calculator using SQL Model clause&lt;/h3&gt;&lt;br /&gt;Recently we had &lt;a href="http://datubazes.wordpress.com/2008/10/17/oracle-diena-2008-pagajusi/"&gt;local Latvian Oracle day conference&lt;/a&gt;. This year it was quite big event with 5 parallel sessions and more than 400 participants. I also was one of the presenters telling about analytic functions and SQL Model clause. During the process of understanding deeper and better Oracle SQL Model clause I've tried make also some a bit complex examples myself. Nowadays the actual problem is mortgage and of course the possibility to pay monthly payments (fortunately not for me :) ) on the background of world wide financial crisis.&lt;br /&gt;So here is fully functional mortgage calculator using SQL Model clause. There are two variants:&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Adjustable_rate_mortgage"&gt;Adjustable rate mortgage&lt;/a&gt; with variable payment each month and&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Fixed_rate_mortgage"&gt;Fixed rate mortgage&lt;/a&gt; with fixed monthly payment.&lt;/li&gt;&lt;/ul&gt;I've used &lt;a href="http://www.mtgprofessor.com/formulas.htm"&gt;this site&lt;/a&gt; to get formula for fixed monthly payment required to fully amortize a loan over a term of fixed months at a fixed monthly interest rate.&lt;br /&gt;OK and now the scripts.&lt;pre&gt;&lt;span style="background-color: silver; font-family:courier new;"&gt;&lt;br /&gt;set ver off                                                     &lt;br /&gt;set lines 120                                                   &lt;br /&gt;undefine rem_loan year_int_rate term                            &lt;br /&gt;SELECT m+1 month,                                               &lt;br /&gt;            to_char(rem_loan, '99999999.00') rem_loan,          &lt;br /&gt;            to_char(loan_paid_tot, '99999999.00') loan_paid_tot,&lt;br /&gt;            to_char(mon_int, '999999.00') mon_int,              &lt;br /&gt;            to_char(tot_int, '99999999.00') tot_int,            &lt;br /&gt;            to_char(mon_paym, '99999999.00') mon_paym,          &lt;br /&gt;            to_char(mon_paym_tot, '99999999.00') mon_paym_tot,  &lt;br /&gt;            to_char(grand_tot, '99999999.00') grand_tot         &lt;br /&gt;FROM dual&lt;br /&gt;MODEL    &lt;br /&gt;DIMENSION BY (-1 m)                                                                         &lt;br /&gt;MEASURES (&amp;amp;&amp;amp;rem_loan rem_loan,                                                              &lt;br /&gt;  round(&amp;amp;&amp;amp;rem_loan*&amp;amp;&amp;amp;year_int_rate/100/12,2) mon_int,                                       &lt;br /&gt;  ceil(&amp;amp;&amp;amp;rem_loan/&amp;amp;&amp;amp;term*100)/100 mon_paym,                                                 &lt;br /&gt;  (&amp;amp;&amp;amp;rem_loan/&amp;amp;&amp;amp;term*100)/100 loan_paid_tot,                                                &lt;br /&gt;  round(&amp;amp;&amp;amp;rem_loan*&amp;amp;&amp;amp;year_int_rate/12/100,2) tot_int,                                       &lt;br /&gt;  ceil(&amp;amp;&amp;amp;rem_loan/&amp;amp;&amp;amp;term*100)/100 + round(&amp;amp;&amp;amp;rem_loan*&amp;amp;&amp;amp;year_int_rate/100/12,2) mon_paym_tot,&lt;br /&gt;  ceil(&amp;amp;&amp;amp;rem_loan/&amp;amp;&amp;amp;term*100)/100 + round(&amp;amp;&amp;amp;rem_loan*&amp;amp;&amp;amp;year_int_rate/100/12,2) grand_tot    &lt;br /&gt;)&lt;br /&gt;RULES ITERATE (&amp;amp;&amp;amp;term) UNTIL (round(loan_paid_tot[iteration_number], 2) = &amp;amp;&amp;amp;rem_loan) (&lt;br /&gt;  rem_loan[iteration_number] = rem_loan[iteration_number -1] - mon_paym[iteration_number - 1],       &lt;br /&gt;  mon_int[iteration_number] = round(rem_loan[iteration_number]*&amp;amp;&amp;amp;year_int_rate/100/12,2),            &lt;br /&gt;  mon_paym[iteration_number] = least(ceil(&amp;amp;&amp;amp;rem_loan/&amp;amp;&amp;amp;term*100)/100, rem_loan[iteration_number]),   &lt;br /&gt;  loan_paid_tot[iteration_number] = loan_paid_tot[iteration_number - 1] + mon_paym[iteration_number],&lt;br /&gt;  tot_int[iteration_number] = tot_int[iteration_number - 1] + mon_int[iteration_number],             &lt;br /&gt;  mon_paym_tot[iteration_number] = mon_paym[iteration_number] + mon_int[iteration_number],           &lt;br /&gt;  grand_tot[iteration_number] = grand_tot[iteration_number - 1] + mon_paym_tot[iteration_number]);   &lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Result for loan of 1000 money units (lats, euros, dollars, pounds whatever) for 10 % year rate with term of 7 months looks as follows:&lt;pre&gt;&lt;span style="background-color: silver; font-family:courier new;"&gt;&lt;br /&gt;Enter value for rem_loan: 1000&lt;br /&gt;Enter value for year_int_rate: 10&lt;br /&gt;Enter value for term: 7&lt;br /&gt;&lt;br /&gt;     MONTH REM_LOAN     LOAN_PAID_TO MON_INT    TOT_INT      MON_PAYM     MON_PAYM_TOT GRAND_TOT&lt;br /&gt;---------- ------------ ------------ ---------- ------------ ------------ ------------ ------------&lt;br /&gt;         0      1000.00       142.86       8.33         8.33       142.86       151.19       151.19&lt;br /&gt;         1       857.14       285.72       7.14        15.47       142.86       150.00       301.19&lt;br /&gt;         2       714.28       428.58       5.95        21.42       142.86       148.81       450.00&lt;br /&gt;         3       571.42       571.44       4.76        26.18       142.86       147.62       597.62&lt;br /&gt;         4       428.56       714.30       3.57        29.75       142.86       146.43       744.05&lt;br /&gt;         5       285.70       857.16       2.38        32.13       142.86       145.24       889.29&lt;br /&gt;         6       142.84      1000.00       1.19        33.32       142.84       144.03      1033.32&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;For fixed payment each month the script is as follows:&lt;pre&gt;&lt;span style="background-color: silver; font-family:courier new;"&gt;&lt;br /&gt;SELECT m+1 month,                                               &lt;br /&gt;            to_char(rem_loan, '99999999.00') rem_loan,          &lt;br /&gt;            to_char(loan_paid_tot, '99999999.00') loan_paid_tot,&lt;br /&gt;            to_char(mon_int, '999999.00') mon_int,              &lt;br /&gt;            to_char(tot_int, '99999999.00') tot_int,            &lt;br /&gt;            to_char(mon_paym, '99999999.00') mon_paym,          &lt;br /&gt;            to_char(mon_paym_tot, '99999999.00') mon_paym_tot,  &lt;br /&gt;            to_char(grand_tot, '99999999.00') grand_tot         &lt;br /&gt;FROM dual&lt;br /&gt;MODEL    &lt;br /&gt;DIMENSION BY (-1 m)                                                                 &lt;br /&gt;MEASURES (&amp;&amp;rem_loan rem_loan,                                                      &lt;br /&gt;  round(&amp;&amp;rem_loan*&amp;&amp;year_int_rate/100/12,2) mon_int,                               &lt;br /&gt;  ceil(&amp;&amp;rem_loan*(&amp;&amp;year_int_rate/100/12*POWER((1+&amp;&amp;year_int_rate/100/12),&amp;&amp;term))/&lt;br /&gt;    (POWER((1+&amp;&amp;year_int_rate/100/12),&amp;&amp;term)-1)*100)/100 -                         &lt;br /&gt;    round(&amp;&amp;rem_loan*&amp;&amp;year_int_rate/100/12,2) mon_paym,                            &lt;br /&gt;  ceil(&amp;&amp;rem_loan*(&amp;&amp;year_int_rate/100/12*POWER((1+&amp;&amp;year_int_rate/100/12),&amp;&amp;term))/&lt;br /&gt;    (POWER((1+&amp;&amp;year_int_rate/100/12),&amp;&amp;term)-1)*100)/100 -                         &lt;br /&gt;    round(&amp;&amp;rem_loan*&amp;&amp;year_int_rate/100/12,2) loan_paid_tot,                       &lt;br /&gt;  round(&amp;&amp;rem_loan*&amp;&amp;year_int_rate/12/100,2) tot_int,                               &lt;br /&gt;  ceil(&amp;&amp;rem_loan*(&amp;&amp;year_int_rate/100/12*POWER((1+&amp;&amp;year_int_rate/100/12),&amp;&amp;term))/&lt;br /&gt;    (POWER((1+&amp;&amp;year_int_rate/100/12),&amp;&amp;term)-1)*100)/100 mon_paym_tot,             &lt;br /&gt;  ceil(&amp;&amp;rem_loan*(&amp;&amp;year_int_rate/100/12*POWER((1+&amp;&amp;year_int_rate/100/12),&amp;&amp;term))/&lt;br /&gt;    (POWER((1+&amp;&amp;year_int_rate/100/12),&amp;&amp;term)-1)*100)/100 grand_tot                 &lt;br /&gt;)&lt;br /&gt;RULES ITERATE (&amp;&amp;term) UNTIL (round(loan_paid_tot[iteration_number], 2) = &amp;&amp;rem_loan) (              &lt;br /&gt;  rem_loan[iteration_number] = rem_loan[iteration_number -1] - mon_paym[iteration_number - 1],       &lt;br /&gt;  mon_int[iteration_number] = round(rem_loan[iteration_number]*&amp;&amp;year_int_rate/100/12,2),            &lt;br /&gt;  mon_paym_tot[iteration_number] = least(                                                            &lt;br /&gt;    ceil(&amp;&amp;rem_loan*(&amp;&amp;year_int_rate/100/12*POWER((1+&amp;&amp;year_int_rate/100/12),&amp;&amp;term))/               &lt;br /&gt;      (POWER((1+&amp;&amp;year_int_rate/100/12),&amp;&amp;term)-1)*100)/100,                                         &lt;br /&gt;    rem_loan[iteration_number] + mon_int[iteration_number]),                                         &lt;br /&gt;  mon_paym[iteration_number] = mon_paym_tot[iteration_number] - mon_int[iteration_number],           &lt;br /&gt;  loan_paid_tot[iteration_number] = loan_paid_tot[iteration_number - 1] + mon_paym[iteration_number],&lt;br /&gt;  tot_int[iteration_number] = tot_int[iteration_number - 1] + mon_int[iteration_number],             &lt;br /&gt;  grand_tot[iteration_number] = grand_tot[iteration_number - 1] + mon_paym_tot[iteration_number]);   &lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;Result for the same loan of 1000 money units (lats, euros, dollars, pounds whatever) for 10 % year rate with term of 7 months looks as follows:&lt;pre&gt;&lt;span style="background-color: silver; font-family:courier new;"&gt;&lt;br /&gt;     MONTH REM_LOAN     LOAN_PAID_TO MON_INT    TOT_INT      MON_PAYM     MON_PAYM_TOT GRAND_TOT&lt;br /&gt;---------- ------------ ------------ ---------- ------------ ------------ ------------ ------------&lt;br /&gt;         0      1000.00       139.33       8.33         8.33       139.33       147.66       147.66&lt;br /&gt;         1       860.67       279.82       7.17        15.50       140.49       147.66       295.32&lt;br /&gt;         2       720.18       421.48       6.00        21.50       141.66       147.66       442.98&lt;br /&gt;         3       578.52       564.32       4.82        26.32       142.84       147.66       590.64&lt;br /&gt;         4       435.68       708.35       3.63        29.95       144.03       147.66       738.30&lt;br /&gt;         5       291.65       853.58       2.43        32.38       145.23       147.66       885.96&lt;br /&gt;         6       146.42      1000.00       1.22        33.60       146.42       147.64      1033.60&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;During my research I've found invaluable these resources:&lt;ul&gt;&lt;li&gt;&lt;a href="http://download.oracle.com/docs/cd/B19306_01/server.102/b14223/sqlmodel.htm"&gt;Oracle official documentation&lt;/a&gt;;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://rwijk.blogspot.com/"&gt;Rob van Wijk blog&lt;/a&gt;;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://volder-notes.blogspot.com/"&gt;Volder blog&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-4355778202627530744?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/4355778202627530744/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=4355778202627530744' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/4355778202627530744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/4355778202627530744'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/10/mortgage-calculator-using-sql-model.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-1695825812149846215</id><published>2008-07-14T23:42:00.002+03:00</published><updated>2008-07-15T00:02:11.546+03:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;One of 364 000 articles&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;According to google I've written another one of ~364 000 articles about &lt;a href="http://www.gplivna.eu/papers/sql_join_types.htm"&gt;SQL join types&lt;/a&gt;. So the question is why anyone should read it?&lt;br /&gt;Here are a few reasons:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;It is 25 pages long;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It contains join types metamodel or at least my attempt to create one;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It tries to describe what are different join types and how they relate to each other;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It contains visual pictures of cross, inner, and left, right, full outer joins and this time &lt;a href="http://www.codinghorror.com/blog/archives/000976.html"&gt;not with Venn diagramms&lt;/a&gt;, which I personally think are suitable for absolutely different operations (set operations);&lt;/li&gt;&lt;br /&gt;&lt;li&gt;To describe theory it contains 44 examples, which are tested on Oracle, SQL Server and MySQL;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It contains several links to other resources.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Because it is 25 pages I've decided not to put it here but &lt;a href="http://www.gplivna.eu/papers/sql_join_types.htm"&gt;it is on my website&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I have one wish though - if You are reading this article and have access to another DBMS (than already mentioned in article i.e. Oracle, SQL Server, MySQL) and have a bit free time, please run examples on your DBMS and post results either here or send me to mail &lt;a href="mailto:gints.plivna@gmail.com"&gt;gints.plivna@gmail.com&lt;/a&gt;. Then I will put them in original article along with contributor's name.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-1695825812149846215?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/1695825812149846215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=1695825812149846215' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/1695825812149846215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/1695825812149846215'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/07/one-of-364-000-articles-according-to.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-6646527580257657711</id><published>2008-07-05T16:28:00.008+03:00</published><updated>2008-07-05T20:40:27.448+03:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Latvian Nationwide Song and Dance Celebration in Riga&lt;/h3&gt;Today is the beginning of 24th song festival - unique celebration of choral songs, which started 135 years ago with the first song festival. In these times under the rule of Russian Czar, later they continued during the short freedom period as well as even in Soviet times. This year about 35 000 singers and dancers will come to Riga to sing and dance in various concerts. This means more than 2% of all Latvians are coming together to sing and dance and many many more are coming to see them on the concerts or via TV.&lt;br /&gt;&lt;h4&gt;Brief history&lt;/h4&gt;The first All Latvian Song Festival took place in Riga, year 1873. There were 1003 singers in these times. Under the Russian Czar there were 5 festivals. During the Latvian independence there were 4 festivals and participant count raised to more than 14 000 people. During the Soviet times these festivals partially become the weapon of Soviet propaganda, however these were like two-edged sword, for example, the 100th anniversary of song festival in 1973 was some kind of emotional uprising against Soviet regime. Since 1990 song festivals are held in independent state again and the participant count has raised to impressive more than 2% of all Latvians. The learning process of songs and dances is continued all the time and it is worth to mention that noone pays a single santīms (centime) to participants both for preparation process lasting a few years and also the very festival, although of course there is governmental material support for the organizational purposes of the festival.&lt;br /&gt;&lt;h4&gt;Events&lt;/h4&gt;&lt;p&gt;During the festival there are many concerts and other kind of events. I'll mention a few of them. The first is participant parade. In the picture below one can look at one of the best choirs in the world "Kamēr", which has won many international awards and also takes part in this festival.&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_8yYAHvkcUVA/SG9_XbBRXLI/AAAAAAAAAFM/NEPn7a_t2-w/s1600-h/043.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5219530533512502450" style="CURSOR: hand" alt="Latvian Song Festival choir Kamēr" src="http://4.bp.blogspot.com/_8yYAHvkcUVA/SG9_XbBRXLI/AAAAAAAAAFM/NEPn7a_t2-w/s400/043.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The second one is main dance concert. In recent times more than 10 000 dancers are taking part in it.&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_8yYAHvkcUVA/SG-A5mwKMrI/AAAAAAAAAFU/nIvmM_SgXfk/s1600-h/083.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5219532220289135282" style="CURSOR: hand" alt="Latvian Song and Dance Festival" src="http://2.bp.blogspot.com/_8yYAHvkcUVA/SG-A5mwKMrI/AAAAAAAAAFU/nIvmM_SgXfk/s400/083.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The last and biggest event is the final concert with all the singers in one big choir. It is very impressive moment.&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_8yYAHvkcUVA/SG-CE8ffFwI/AAAAAAAAAFc/SM1wzzQrnhc/s1600-h/027.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5219533514614970114" style="CURSOR: hand" alt="Latvian Song and Dance Festival" src="http://4.bp.blogspot.com/_8yYAHvkcUVA/SG-CE8ffFwI/AAAAAAAAAFc/SM1wzzQrnhc/s400/027.jpg" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;&lt;h4&gt;Some links&lt;/h4&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=WDhbvfvMd34"&gt;Gaismas pils (&lt;em&gt;Castle of Light&lt;/em&gt;)&lt;/a&gt; - one of the favourite Song Festival songs of all time, one of the symbols of resistance against oppressors&lt;/li&gt;&lt;li&gt;The official website of &lt;a href="http://www.dziesmusvetki2008.lv/index.php?&amp;amp;99"&gt;Latvian Nationwide Song and Dance Celebration in Riga, July 5-12, 2008&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://flickr.com/photos/28241716@N04/sets/"&gt;Photo gallery of the current festival&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://www.dziesmusvetki2008.lv/index.php?&amp;amp;85"&gt;History of Song Festivals&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-6646527580257657711?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/6646527580257657711/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=6646527580257657711' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/6646527580257657711'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/6646527580257657711'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/07/latvian-nationwide-song-and-dance.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_8yYAHvkcUVA/SG9_XbBRXLI/AAAAAAAAAFM/NEPn7a_t2-w/s72-c/043.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-4304331403087932224</id><published>2008-06-27T15:55:00.054+03:00</published><updated>2008-07-02T01:10:49.689+03:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Trip to Estonia&lt;/h3&gt;&lt;br /&gt;During my holidays I've been in a 4 days trip to Estonia. For Oracle adepts this is the country where &lt;a href="http://blog.tanelpoder.com/"&gt;Tanel Poder&lt;/a&gt; comes from ;)&lt;br /&gt;The trip was made up by myself and my wife, during it we drove ~1700 km. The general idea was to drive around all Estonia (it is not very big country) and look at some (hopefully) most interesting places. Here are 26 most interesting photos:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGjvAD08pFI/AAAAAAAAABs/GYKLs9beTBo/s1600-h/01_munamagi.jpg" target="_blank"&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;" alt="A view from Munamagi hill" src="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGjvAD08pFI/AAAAAAAAABs/GYKLs9beTBo/s400/01_munamagi.jpg" width="300" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;A view from Munamagi hill, the highest point in Baltics&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGjw-5mLizI/AAAAAAAAACE/K8zo3BvmFzY/s1600-h/02_tartu_cathedral.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Tartu Dom Cathedral" src="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGjw-5mLizI/AAAAAAAAACE/K8zo3BvmFzY/s400/02_tartu_cathedral.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Tartu Dom Cathedral, it is being rebuilt now&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_8yYAHvkcUVA/SGj0PtyLdiI/AAAAAAAAACM/UOnI2OBgLR0/s1600-h/03_tartu_monument.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Tartu monument" src="http://4.bp.blogspot.com/_8yYAHvkcUVA/SGj0PtyLdiI/AAAAAAAAACM/UOnI2OBgLR0/s400/03_tartu_monument.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Interesting fountain in Tartu, second largest Estonian city&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_8yYAHvkcUVA/SGj0rrVhoBI/AAAAAAAAACU/W7ZaHQ5RnBo/s1600-h/04_rainbow_over_peipsi.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Rainbow over Peipsi lake" src="http://2.bp.blogspot.com/_8yYAHvkcUVA/SGj0rrVhoBI/AAAAAAAAACU/W7ZaHQ5RnBo/s400/04_rainbow_over_peipsi.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Rainbow over Peipsi lake&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGj1DVS7T1I/AAAAAAAAACc/UEMfWmXC5Sc/s1600-h/05_street_at_peipsi.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Street at Peipsi" src="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGj1DVS7T1I/AAAAAAAAACc/UEMfWmXC5Sc/s400/05_street_at_peipsi.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;There is 8 km long street through the old villages along the Peipsi lake. It looks like that all lengthways&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGj1masxPqI/AAAAAAAAACk/oRRJzcPFXn4/s1600-h/06_ivangorod_castle.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Ivangorod castle" src="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGj1masxPqI/AAAAAAAAACk/oRRJzcPFXn4/s400/06_ivangorod_castle.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Ivangorod castle over the river in Russia. This castle is just in the opposite side of Narva river from the Narva castle&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_8yYAHvkcUVA/SGj2AUK0PEI/AAAAAAAAACs/WZ8d8LFm1gk/s1600-h/07_narva_castle.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Narva castle" src="http://4.bp.blogspot.com/_8yYAHvkcUVA/SGj2AUK0PEI/AAAAAAAAACs/WZ8d8LFm1gk/s400/07_narva_castle.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Narva castle. This castle is just in the opposite side of Narva river from the Ivangorod castle&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGj2VQrJ9nI/AAAAAAAAAC0/WlRmyW4ASds/s1600-h/08_Aija_bells_in_narva_castle.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Bells in Narva castle" src="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGj2VQrJ9nI/AAAAAAAAAC0/WlRmyW4ASds/s400/08_Aija_bells_in_narva_castle.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Aija along with bells in Narva castle&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGj2wIasD-I/AAAAAAAAAC8/6D4n1nY3Sxg/s1600-h/09_estonia_northern_coast.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Estonia northern coast" src="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGj2wIasD-I/AAAAAAAAAC8/6D4n1nY3Sxg/s400/09_estonia_northern_coast.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Northern coast (Gulf of Finland) mostly consists of limestone rocks up to 56 metres high&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGj3HN5aCZI/AAAAAAAAADE/5T3Wx9g-U20/s1600-h/10_sunset_over_finnish_bay.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Sunset over Gulf of Finland" src="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGj3HN5aCZI/AAAAAAAAADE/5T3Wx9g-U20/s400/10_sunset_over_finnish_bay.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Sunset over Gulf of Finland&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_8yYAHvkcUVA/SGj3kErDflI/AAAAAAAAADM/PanzUgHN9vk/s1600-h/11_valaste_waterfall.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Valaste waterfall" src="http://2.bp.blogspot.com/_8yYAHvkcUVA/SGj3kErDflI/AAAAAAAAADM/PanzUgHN9vk/s400/11_valaste_waterfall.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Valaste waterfall is the highest waterfall of Estonia&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_8yYAHvkcUVA/SGj4JBaX40I/AAAAAAAAADU/ccX4YADZFMc/s1600-h/12_kivioli_hill.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Kivioli hills" src="http://2.bp.blogspot.com/_8yYAHvkcUVA/SGj4JBaX40I/AAAAAAAAADU/ccX4YADZFMc/s400/12_kivioli_hill.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Estonia has some kind of oil shale, this hill is man-made and consists of slag of oil shales. It is 116 metres high. The picture was taken from a bit lower hill of the same origin, just older one.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_8yYAHvkcUVA/SGj4jcPYvrI/AAAAAAAAADc/XL9moL4n3Yk/s1600-h/13_rakvere_symbol.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Symbol of Rakvere town" src="http://4.bp.blogspot.com/_8yYAHvkcUVA/SGj4jcPYvrI/AAAAAAAAADc/XL9moL4n3Yk/s400/13_rakvere_symbol.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Symbol of Rakvere town&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGj6IvhEL_I/AAAAAAAAADk/f5xo8rYvRi8/s1600-h/14_bikes_at_palmse_manor.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Bikes at Palmse manor" src="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGj6IvhEL_I/AAAAAAAAADk/f5xo8rYvRi8/s400/14_bikes_at_palmse_manor.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Bikes at Palmse manor, which is in the very centre of Lahemaa national park, a beautiful sightseeing place&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGj6r7tFw0I/AAAAAAAAADs/pJDPMEDc0UU/s1600-h/15_jagala_waterfall.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Jagala waterfall" src="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGj6r7tFw0I/AAAAAAAAADs/pJDPMEDc0UU/s400/15_jagala_waterfall.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Jagala waterfall near from Tallinn&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGj7aX5HBNI/AAAAAAAAAD0/JGuNq--XNbo/s1600-h/16_tallinn_old_town_towers.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Tallinn city wall" src="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGj7aX5HBNI/AAAAAAAAAD0/JGuNq--XNbo/s400/16_tallinn_old_town_towers.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Tallinn has more than 2km long old city wall with many towers and everything in very well preserved&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGj71acT4VI/AAAAAAAAAD8/wlA4XGsqHSY/s1600-h/17_tallinn_old_town.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Tallinn old town" src="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGj71acT4VI/AAAAAAAAAD8/wlA4XGsqHSY/s400/17_tallinn_old_town.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Tallinn old town&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_8yYAHvkcUVA/SGj81jfLtNI/AAAAAAAAAEE/fCkmFw2E2Rw/s1600-h/18_ferries_to_saaremaa.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Ferries to Saaremaa" src="http://4.bp.blogspot.com/_8yYAHvkcUVA/SGj81jfLtNI/AAAAAAAAAEE/fCkmFw2E2Rw/s400/18_ferries_to_saaremaa.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;There was a bit rainy when we crossed over to Saaremaa island (actually Muhu island, which is connected to Saaremaa by dam). The sail is very short just ~20 minutes.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGj939y5qAI/AAAAAAAAAEM/C6PYK12OsRQ/s1600-h/19_13th_century_paintings_in_liiva_church.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Liiva church" src="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGj939y5qAI/AAAAAAAAAEM/C6PYK12OsRQ/s400/19_13th_century_paintings_in_liiva_church.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;13th century painting in Liiva church, Muhu island&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_8yYAHvkcUVA/SGj-VNHP4MI/AAAAAAAAAEU/gjNsyyzkL8k/s1600-h/20_maasilinn_stronghold.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Maasilinn stronghold" src="http://2.bp.blogspot.com/_8yYAHvkcUVA/SGj-VNHP4MI/AAAAAAAAAEU/gjNsyyzkL8k/s400/20_maasilinn_stronghold.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Maasilinn stronghold in Saaremaa&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGj-w-a7gEI/AAAAAAAAAEc/lOP892d7Pi8/s1600-h/21_angla_windmill.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Angla windmills" src="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGj-w-a7gEI/AAAAAAAAAEc/lOP892d7Pi8/s400/21_angla_windmill.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Angla windmills. There were multitude of windmills in Saremaa (~800) these are just a few of forever gone old might.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_8yYAHvkcUVA/SGj_KSeOrdI/AAAAAAAAAEk/5VNLsRScdZU/s1600-h/22_kaali_meteoritic_lake.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Kaali meteoritic lake" src="http://2.bp.blogspot.com/_8yYAHvkcUVA/SGj_KSeOrdI/AAAAAAAAAEk/5VNLsRScdZU/s400/22_kaali_meteoritic_lake.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;It is very easy to get to this Kaali meteoritic lake, it is just 17 km from Kuressaare, centre of Saaremaa&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_8yYAHvkcUVA/SGj_h7WQqiI/AAAAAAAAAEs/S3fFfE4KK0U/s1600-h/23_passage_in_kurressaare_castle.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Kuressaare castle" src="http://2.bp.blogspot.com/_8yYAHvkcUVA/SGj_h7WQqiI/AAAAAAAAAEs/S3fFfE4KK0U/s400/23_passage_in_kurressaare_castle.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;A passage in Kuressaare castle, Saremaa&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_8yYAHvkcUVA/SGj_7uAnbzI/AAAAAAAAAE0/kRF645KnS14/s1600-h/24_middle_age_toilett.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Toilett of Middle Ages" src="http://4.bp.blogspot.com/_8yYAHvkcUVA/SGj_7uAnbzI/AAAAAAAAAE0/kRF645KnS14/s400/24_middle_age_toilett.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Toilett of Middle Ages in Kuressaare castle, Saremaa&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGkAMo_pneI/AAAAAAAAAE8/RPNVDJaF3uM/s1600-h/25_kihelkonna_church_inside.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Kihelkonna church" src="http://3.bp.blogspot.com/_8yYAHvkcUVA/SGkAMo_pneI/AAAAAAAAAE8/RPNVDJaF3uM/s400/25_kihelkonna_church_inside.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Organ of Kihelkonna church, Saremaa&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGkAshen2MI/AAAAAAAAAFE/GBI8GS4XLVI/s1600-h/26_kihelkonna_church_outside.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img style="float:left; margin:10px 10px 10px 10px;cursor:pointer; cursor:hand;"  alt="Kihelkonna church" src="http://1.bp.blogspot.com/_8yYAHvkcUVA/SGkAshen2MI/AAAAAAAAAFE/GBI8GS4XLVI/s400/26_kihelkonna_church_outside.jpg" width="300" align="middle" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Kihelkonna church, Saremaa. It was possible to climb up to the tower and look around through the windows&lt;br /&gt;&lt;table width=100%&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;If you enjoyed these you can look also at &lt;b&gt;&lt;a href="http://gplivna.blogspot.com/2008/01/some-photos-ive-been-tagged-by-apc.html"&gt;some of my photos from Latvia&lt;/a&gt;&lt;/b&gt;.&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-4304331403087932224?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/4304331403087932224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=4304331403087932224' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/4304331403087932224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/4304331403087932224'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/06/trip-to-estonia-during-my-holidays-ive.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_8yYAHvkcUVA/SGjvAD08pFI/AAAAAAAAABs/GYKLs9beTBo/s72-c/01_munamagi.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-7726663011513029253</id><published>2008-06-26T14:20:00.002+03:00</published><updated>2008-06-26T14:55:00.897+03:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;New improved price list&lt;/h3&gt;&lt;p&gt;Obviously fluctuations of $ is affecting also Oracle ;) and as a result we have new global price list. Changes have affected also all Oracle database editions except Express, which is for free. So now Standard Edition One license is for 5 800 (was 4 995), Standard Edition is for 17 500 (was 15 000) and Enterprise Edition 47 500 (was 40 000) per processor. Personal Edition named user plus licence now is 460 US dollars (was 400). All new prices &lt;a href="http://www.oracle.com/corporate/pricing/technology-price-list.pdf"&gt;are here&lt;/a&gt;. These are the bad news.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The good news are that Oracle has created very informative &lt;a href="http://www.oracle.com/partners/sell/dist_agre/global/auth/pricetools.html"&gt;Pricing and Licensing Rules, Tools&lt;/a&gt; page (at least I was not aware of that), which has many links to other valuable documents regarding Oracle pricing and licensing, for example, Oracle product &lt;a href="http://solutions.oracle.com/opn_esrc/PRICE/PRICING_ENGINE/LOCALIZABLE_PRICE_LIST/OPN_LOCAL/LOCALIZABLE_EPLO_TECH_OPN.XLS"&gt;prices in other currencies&lt;/a&gt; using Oracle exchange rates. &lt;/p&gt;&lt;p&gt;So get accustomed to new prices ;) and don't forget that there are other editions than Enterprise as well as there are such thing like term licensing (licenses for 1 till 5 years starting with 20% and ending with 70% of list price)!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-7726663011513029253?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/7726663011513029253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=7726663011513029253' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/7726663011513029253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/7726663011513029253'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/06/new-improved-price-list-obviously.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-9165014391627972588</id><published>2008-05-22T00:52:00.002+03:00</published><updated>2008-05-22T01:16:47.131+03:00</updated><title type='text'></title><content type='html'>SQL Merge and Sequence gaps&lt;br /&gt;&lt;br /&gt;I hope You my dear reader isn't one of the people cursed by &lt;a href="http://gplivna.eu/papers/gapless_sequences.htm"&gt;requirement for gapless sequences&lt;/a&gt; ;)&lt;br /&gt;Yesterday I just found another nail in the coffin for oracle sequence objects used as gapless sequence generators. Of course there are many causes not to do that, just like simple rollback, users changing their minds, network connection error, flushing cache etc. But I didn't know at least till yesterday, that MERGE statements generate gaps with quite big guarantee. It seems that Merge statement is generating the same number of calls for sequence next value as row count of source table or subquery.&lt;br /&gt;Let's look at example:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CREATE TABLE target (pk number, data varchar2(10));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CREATE TABLE source (pk_s number, data_s varchar2(10));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;INSERT INTO target VALUES (1, 'a');&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;INSERT INTO target VALUES (3, 'c');&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;INSERT INTO source VALUES (1, 'a');&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;INSERT INTO source VALUES (2, 'b');&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;INSERT INTO source VALUES (3, 'c');&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;INSERT INTO source VALUES (4, 'd');&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;COMMIT;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CREATE SEQUENCE seq START WITH 5;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So now we have 2 rows in target table, and 4 rows in source table. We'll compare them using data and data_s column. We'd insert only two rows, because another 2 already exists and even won't use WHEN MATCHED clause for update.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;MERGE INTO target&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;USING source&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ON (data = data_s)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;WHEN NOT MATCHED THEN &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;INSERT VALUES (seq.nextval, data_s);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; SELECT * FROM target;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        PK DATA&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;---------- ----------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         1 a&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         3 c&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         7 d&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         8 b&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Although the sequence should have started from 5 new pk values are 7 and 8. Let's add another row into source and look what happens:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;INSERT INTO source VALUES (5, 'e');&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;MERGE INTO target&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;USING source&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ON (data = data_s)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;WHEN NOT MATCHED THEN &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;INSERT VALUES (seq.nextval, data_s);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; SELECT * FROM target;&lt;br /&gt;        PK DATA&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;---------- ----------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         1 a&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         3 c&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         7 d&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         8 b&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        13 e&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So now the value is 13 i.e. 8 + count of rows from source table (5). Now let's add another row and delete all previous.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;INSERT INTO source VALUES (6, 'f');&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;DELETE source WHERE pk_s &lt;=5;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;MERGE INTO target&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;USING source&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ON (data = data_s)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;WHEN NOT MATCHED THEN &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;INSERT VALUES (seq.nextval, data_s);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; SELECT * FROM target;&lt;br /&gt;        PK DATA&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;---------- ----------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         1 a&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         3 c&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         7 d&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         8 b&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        13 e&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        14 f&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As we can see pk is incremented only by 1.&lt;br /&gt;After my experiments I found also metalink note "Merge Increments SEQUENCE.NEXTVAL for Both Insert and Update" (Note:554656.1), which also assures this as expected situation and not bug. So another reason not to worry about sequence values, just uniqueness of them ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-9165014391627972588?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/9165014391627972588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=9165014391627972588' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/9165014391627972588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/9165014391627972588'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/05/sql-merge-and-sequence-gaps-i-hope-you.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-3073892298299043234</id><published>2008-05-16T18:16:00.002+03:00</published><updated>2008-05-16T18:47:35.164+03:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;Minus All and Intersect All&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Today I rediscovered &lt;a href="https://mix.oracle.com/ideas"&gt;Oracle Mix ideas&lt;/a&gt; and remembered my surprise that there are also &lt;a href="http://gplivna.blogspot.com/2008/01/minus-all-and-intersect-all-in-oracle.html"&gt;Minus all and Intersect all operators in SQL standard&lt;/a&gt; just like Union and Union all. I'll briefly remind You what exactly they were. Let's imagine we have two sets:&lt;br /&gt;&lt;br /&gt;T1: 1, 2, 2, 2, 3, 4, 4&lt;br /&gt;T2: 2, 3, 4, 4, 4, 5&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Then T1 INTERSECT T2 is 2, 3, 4&lt;br /&gt;T1 INTERSECT ALL T2 would be 2, 3, 4, 4&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T1 MINUS T2 is 1&lt;br /&gt;T1 MINUS ALL T2 would be 1, 2, 2&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So by default Intersect and Minus have DISTINCT operator removing all non-unique values. But in case we add keyword ALL then all values and their cardinalities are counted as well. I think these operators could be quite handy in process of analysing two data sets and finding what exactly the difference is. So if You are thinking the same way then I kindly ask you to &lt;a href="https://mix.oracle.com/ideas/28856-add-except-minus-all-and-intersect-all-set-operators"&gt;support my idea about intersect all and minus all&lt;/a&gt; with your voice in Oracle Mix.&lt;br /&gt;&lt;br /&gt;Thank You in advance for any decision :) and I hope sooner or later (better sooner of course ;) to find that in New features guide.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-3073892298299043234?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/3073892298299043234/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=3073892298299043234' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/3073892298299043234'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/3073892298299043234'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/05/minus-all-and-intersect-all-today-i.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-3931742339791879168</id><published>2008-05-07T19:49:00.007+03:00</published><updated>2008-05-08T01:12:43.790+03:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;DBMSes are different...&lt;/h3&gt;Recently had to do some work with SQL Server. As my experience with it is quite limited I've got a few interesting impressions, which probably are absolutely trivial for SQL Server adepts :)&lt;br /&gt;&lt;h4&gt;Do you know that SELECT query can create new tables?&lt;/h4&gt;OK in SQL Server it can. So I had to create backup of a table and firstly was quite frustrated not finding anything like CTAS (CREATE TABLE ... AS SELECT). I was on a wrong track however. The right syntax is SELECT INTO as in following example:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CREATE TABLE persons (&lt;br /&gt;prs_id INT IDENTITY NOT NULL PRIMARY KEY,&lt;br /&gt;prs_name VARCHAR(30) NOT NULL) ;&lt;br /&gt;&lt;br /&gt;INSERT INTO persons (prs_name) VALUES ('GINTS');&lt;br /&gt;INSERT INTO persons (prs_name) VALUES ('JOE');&lt;br /&gt;&lt;br /&gt;SELECT *&lt;br /&gt;INTO persons_bkp&lt;br /&gt;FROM persons;&lt;br /&gt;&lt;br /&gt;SELECT * FROM persons_bkp;&lt;br /&gt;-------------------------&lt;br /&gt;1 GINTS&lt;br /&gt;2 JOE&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So till now I was under the impression that SELECT is DML statement however obviously that's not true at least for SQL Server.&lt;br /&gt;&lt;h4&gt;Do you know that SQL Server can handle recursive queries?&lt;/h4&gt;&lt;p&gt;At least since version 2005 it can. Long ago I have heard that SQL Server has nothing similar to START WITH CONNECT BY. This site &lt;a href="http://www.psoug.org/reference/sqlserver.html"&gt;comparing SQL Server and Oracle&lt;/a&gt; seemed to approve my thoughts. However DBMSes are different and one has to look for different ways accomplishing the same goals. And in SQL Server one can use Common table expressions (aka query factoring clause or with clause in Oracle world) to get hierarchical results. And BTW here SQL Server "outfunctions" Oracle because it allows to recursively reference the same common table in its definition, which is not allowed by Oracle. Here are two articles if you are interested in how exactly it is done: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms186243.aspx"&gt;Recursive Queries Using Common Table Expressions&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://www.sqlservercentral.com/articles/Development/recursivequeriesinsqlserver2005/1760/"&gt;Recursive Queries in SQL Server 2005&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So in conclusion these two features which are possible in both DBMSes, but are implemented in completely different ways supports my previous article that &lt;a href="http://gplivna.eu/papers/choose_database.htm#_Toc183880189"&gt;all databases are different&lt;/a&gt; :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-3931742339791879168?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/3931742339791879168/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=3931742339791879168' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/3931742339791879168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/3931742339791879168'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/05/dbmses-are-different.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-2443287729218326070</id><published>2008-01-30T23:39:00.000+02:00</published><updated>2008-01-31T01:37:50.131+02:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;The year has gone..&lt;/h3&gt;..since I started blogging. Actually I started it because of real anger against Oracle. The reason was one of the most famous problems in OTN history - &lt;a href="http://gplivna.blogspot.com/2007/01/five-million-and-counting-what_30.html"&gt;inability to change e-mails&lt;/a&gt; ;) However about a month or two later &lt;a href="http://gplivna.blogspot.com/2007/04/statistics-is-power.html"&gt;it was resolved&lt;/a&gt;.&lt;br /&gt;It seems the last year Oracle has made advances towards the community and:&lt;br /&gt;1) listened to it (above mentioned case) as well as for example &lt;a href="http://www.pythian.com/blogs/526/an-open-letter-to-larry-ellison-on-awr-and-ash-licensing"&gt;the case with AWR and ASH licensing&lt;/a&gt;. Probably all these steps were already on their way but I'm quite sure blog entries accelerated the result.&lt;br /&gt;2) created public resources (&lt;a href="http://wiki.oracle.com/"&gt;oracle wiki&lt;/a&gt;) probably not veeeeery actively used until now.&lt;br /&gt;3) &lt;a href="http://oracleappslab.com/2007/10/30/seriously-we-want-bloggers-at-openworld/"&gt;granted free access&lt;/a&gt; for active members of public community to Oracle open world.&lt;br /&gt;4) most probably made other positive steps I cannot remember or simply haven't heard about.&lt;br /&gt;&lt;br /&gt;Last year was also big improvement in so called Oracle blogosphere - &lt;a href="http://orana.info/"&gt;orana.info&lt;/a&gt; was founded along with some other aggregators, &lt;a href="http://wiki.oracle.com/page/Blogging"&gt;which can be found on oracle wiki&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;For me it was a year of realizing the fact that there are tremendous resources about databases and Oracle in English, but just few in my mother tongue Latvian. So as I don't think English is the only language in the world even for databases :) I started to &lt;a href="http://datubazes.wordpress.com/"&gt;blog about databases in Latvian&lt;/a&gt;. Quite a bit of free time goes there.&lt;br /&gt;&lt;br /&gt;So in my little anniversary I wish Oracle remember and support its community (probably sponsor a trip to Open world next year for bloggers khe khe :))) and myself to continue work about databases and Oracle resources especially in Latvian!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-2443287729218326070?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/2443287729218326070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=2443287729218326070' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/2443287729218326070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/2443287729218326070'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/01/year-has-gone.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-5393025030975688011</id><published>2008-01-25T12:12:00.006+02:00</published><updated>2008-07-14T23:41:56.590+03:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;SQL Join Types&lt;/h3&gt;&lt;br /&gt;&lt;b&gt;New enhanced 25 pages long article with 44 examples and visual pictures describing &lt;a href="http://www.gplivna.eu/papers/sql_join_types.htm"&gt;SQL join types&lt;/a&gt; can be found here.&lt;/b&gt;&lt;br /&gt;&lt;p&gt;I'm studying a bit SQL joins and trying to make clear at least for me what they are and what the relationships among them are. As I've always thought that picture is worth hundred words I've tried to create ER diagram describing metainfo about joins. So the question for everyone is - is this diagram OK? And aren't there obvious bugs? :)&lt;br /&gt;Probably from the strict viewpoint of Set theory and &lt;a href="http://en.wikipedia.org/wiki/Relational_algebra"&gt;relational algebra&lt;/a&gt; it is not OK, but I'm more concerned of practical SQL usage and understanding. In case you know similar diagramm or whatever else visual explanation of relationships among join types please leave comment with link.&lt;br /&gt;So the diagram is as follows (please click on it to get bigger):&lt;br /&gt;&lt;br /&gt;&lt;a title="SQL Join Types" href="http://datubazes.files.wordpress.com/2008/02/joins2.png"&gt;&lt;img alt="SQL Join Types" src="http://datubazes.wordpress.com/files/2008/02/joins31.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now for those that aren’t familiar with all these join types and terms in diagram above I'll try to give SQL examples (without data and results) for each one of them. If you'd like to have also examples with data cehck one of the links at the very end of this post.&lt;br /&gt;Assume we have 2 tables - TableA (id, title) and TableB (id, description).&lt;br /&gt;What the result are for each one of them you can find in other places for example: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Cross join:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;SELECT * FROM TableA CROSS JOIN TableB &lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Join with restriction:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;It is either natural join or qualified join. Each join with restriction has one cross join which is the degraded case of it. &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Natural join:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Natural joins can be Inner or one of Outer joins, but they always are equi joins. Without explicitly specified inner or outer it is inner join. More about natural joins in &lt;a href="http://gplivna.blogspot.com/2007/10/natural-joins-are-evil-motto-if-you.html"&gt;my previous blog post&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;SELECT * FROM TableA NATURAL JOIN TableB &lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Qualified join:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Qualified joins can be written either specifying join columns (named columns join) or explicitly writing join condition. &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Join type: &lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Could not find anything better to somehow unite inner and various outer joins under one roof. &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Inner join:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;SELECT * FROM TableA NATURAL INNER JOIN TableB&lt;br /&gt;SELECT * FROM TableA INNER JOIN TableB USING (id)&lt;br /&gt;SELECT * FROM TableA INNER JOIN TableB ON (tablea.id = tableb.id) &lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Outer join:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Outer join is one of left, right or full outer join. &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Left outer join:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;SELECT * FROM TableA NATURAL LEFT OUTER JOIN TableB&lt;br /&gt;SELECT * FROM TableA LEFT OUTER JOIN TableB USING (id)&lt;br /&gt;SELECT * FROM TableA LEFT OUTER JOIN TableB ON (tablea.id = tableb.id) &lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Right outer join and Full outer join:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Take the same examples as from left outer join and just replace left with right or outer. &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Qualified join expression:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;There are two ways how more explicitly write join condition either specifying join columns or explicitly writing join condition. &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Named columns join:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This join is written with "USING" clause. Named columns join always is equi join. &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;SELECT * FROM TableA INNER JOIN TableB USING (id) &lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Conditional join:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This join is the real one that I'd like to suggest using. With explicitly specifying what the join condition is. This also is the only join where one can use not only equi join but also another predicate operator than "=". &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;SELECT * FROM TableA INNER JOIN TableB ON (tablea.id = tableb.id) &lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Predicate operator type:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Based on predicate operator type joins can be classified as either equi or theta (nonequi) joins. &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Equi join:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Equi join is join where operator used in join condition is equivalence ("=").&lt;br /&gt;Both natural joins and Named columns joins are always equi joins. Examples: &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;SELECT * FROM TableA NATURAL LEFT OUTER JOIN TableB&lt;br /&gt;SELECT * FROM TableA FULL OUTER JOIN TableB USING (id)&lt;br /&gt;SELECT * FROM TableA INNER JOIN TableB ON (tablea.id = tableb.id) &lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Theta (Nonequi) join:&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Equi join is join where operator used in join condition is something other than equivalence ("="). &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;SELECT * FROM TableA INNER JOIN TableB ON (tablea.id &lt;&gt;&lt;/p&gt;&lt;p&gt;I've not showed here such beasts like UNION JOINS, SEMI JOINS and ANTI JOINS because the first one (UNION join) is neither in SQL standard nor in any database I worked with.&lt;br /&gt;SEMI JOINS and ANTI JOINS are somehow less interesting for me. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;Further reading: &lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://v.hdm-stuttgart.de/~riekert/lehre/db-kelz/chap7.htm"&gt;SQL und relationale Algebra&lt;/a&gt; (in German with for everyone understandable examples)&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Relational_algebra"&gt;Relational algebra, joins and join like operation from wikipedia&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Why I think &lt;a href="http://gplivna.blogspot.com/2007/10/natural-joins-are-evil-motto-if-you.html"&gt;natural joins are most unnatural joins ever&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-5393025030975688011?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/5393025030975688011/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=5393025030975688011' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/5393025030975688011'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/5393025030975688011'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/01/sql-join-types-im-studying-bit-sql.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-5201251717743590932</id><published>2008-01-13T14:26:00.000+02:00</published><updated>2008-01-14T08:43:43.427+02:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Some photos&lt;/h3&gt;&lt;br /&gt;I've been &lt;a href="http://radiofreetooting.blogspot.com/2008/01/all-about-me.html"&gt;tagged by APC&lt;/a&gt;. Usually I don't respond to &lt;a href="http://www.cs.rutgers.edu/~watrous/chain-letters.html"&gt;chain letters&lt;/a&gt; but this will be a bit of exception. However I won't tag anyone further. Looking at &lt;a href="http://forums.speedguide.net/showthread.php?t=44882"&gt;usual curses&lt;/a&gt; happening after NOT forwarding chain letters I hope all my Oracle installations won't silently transform to SQL Server ones ;)&lt;br /&gt;So I won't tell anything about me, I'll just publish some of my best photos taken in various places in Latvia.&lt;br /&gt;&lt;table&gt;&lt;br /&gt;&lt;tr valign=bottom&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/LilacsBig.jpg" target="_blank"&gt;&lt;img border="0" width=180 src="http://www.gplivna.eu/Blogspot/Lilacs.jpg" alt="Lilacs in Dobele" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/OperaSquareBig.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img border="0" width=180 align="middle" src="http://www.gplivna.eu/Blogspot/OperaSquare.jpg" alt="Opera square"/&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr valign=top&gt;&lt;td&gt;Lilacs in Dobele garden&lt;/td&gt;&lt;td&gt;Garden if front of National Opera&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;&lt;tr valign=bottom&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/LesserSpottedEagleNestBig.jpg" target="_blank"&gt;&lt;img border="0" width=180 src="http://www.gplivna.eu/Blogspot/LesserSpottedEagleNest.jpg" alt="Nest of Lesser Spotted Eagle" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/HeathBig.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img border="0" width=180 align="middle" src="http://www.gplivna.eu/Blogspot/Heath.jpg" alt="Heath" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr valign=top&gt;&lt;td&gt;Nest of Lesser Spotted Eagle&lt;/td&gt;&lt;td&gt;Airing trail in heath&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;&lt;tr valign=bottom&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/LakeInFogBig.jpg" target="_blank"&gt;&lt;img border="0" width=180 src="http://www.gplivna.eu/Blogspot/LakeInFog.jpg" alt="A lake in fog" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/SunSetBig.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img border="0" width=180 align="middle" src="http://www.gplivna.eu/Blogspot/SunSet.jpg" alt="Sun set" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr valign=top&gt;&lt;td&gt;A lake in fog&lt;/td&gt;&lt;td&gt;Sun set view over my country landed property&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;&lt;tr valign=bottom&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/AtteBig.jpg" target="_blank"&gt;&lt;img border="0" width=180 src="http://www.gplivna.eu/Blogspot/Atte.jpg" alt="Open air museum in Atte" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/EasterEggsBig.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img border="0" width=180 align="middle" src="http://www.gplivna.eu/Blogspot/EasterEggs.jpg" alt="Heath" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;tr valign=top&gt;&lt;td&gt;Open air museum in Atte&lt;/td&gt;&lt;td&gt;Easter eggs by my wife(colouring of course :)&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;&lt;tr valign=bottom&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/OperaHouseBig.jpg" target="_blank"&gt;&lt;img border="0" width=180 src="http://www.gplivna.eu/Blogspot/OperaHouse.jpg" alt="National Opera House in Riga" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/RundalePalaceBig.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img border="0" width=180 align="middle" src="http://www.gplivna.eu/Blogspot/RundalePalace.jpg" alt="Rundale Palace" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;tr valign=top&gt;&lt;td&gt;National Opera House in Riga&lt;/td&gt;&lt;td&gt;Rundale Palace&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;&lt;tr valign=bottom&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/RigaDomCathedralBig.jpg" target="_blank"&gt;&lt;img border="0" width=180 src="http://www.gplivna.eu/Blogspot/RigaDomCathedral.jpg" alt="Riga Dom Cathedral" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/HouseOfBlackHeadsAndStPeterChurchBig.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img border="0" width=180 align="middle" src="http://www.gplivna.eu/Blogspot/HouseOfBlackHeadsAndStPeterChurch.jpg" alt="House Of Blackheads and St.Peter church" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;tr valign=top&gt;&lt;td&gt;Riga Dom Cathedral - biggest church in Baltics&lt;/td&gt;&lt;td&gt;House Of Blackheads and St.Peter church&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;&lt;tr valign=bottom&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/RailRoadBridgeBig.jpg" target="_blank"&gt;&lt;img border="0" width=180 src="http://www.gplivna.eu/Blogspot/RailRoadBridge.jpg" alt="Railroad bridge at night" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;a href="http://www.gplivna.eu/Blogspot/ArtNoveauBig.jpg" target="_blank"&gt;&lt;br /&gt;&lt;img border="0" width=180 align="middle" src="http://www.gplivna.eu/Blogspot/ArtNoveau.jpg" alt="Art Noveau in Riga" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;tr valign=top&gt;&lt;td&gt;Railroad bridge at night&lt;/td&gt;&lt;td&gt;Art Noveau in Riga&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-5201251717743590932?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/5201251717743590932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=5201251717743590932' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/5201251717743590932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/5201251717743590932'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/01/some-photos-ive-been-tagged-by-apc.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-7706395229142950150</id><published>2008-01-10T22:08:00.001+02:00</published><updated>2008-01-13T17:25:01.594+02:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;MINUS ALL and INTERSECT ALL in Oracle Revisited&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Yesterday &lt;a href="http://gplivna.blogspot.com/2008/01/minus-all-and-intersect-all-in-oracle.html"&gt;I wrote an article&lt;/a&gt; explaining that MINUS ALL and INTERSECT ALL is not possible in Oracle.&lt;br /&gt;However today after a bit thinking I got insight - &lt;strong&gt;multiset operations! &lt;/strong&gt;Yes these should be the right thing!&lt;br /&gt;Since 10g Release 1 &lt;a href="http://download.oracle.com/docs/cd/B14117_01/server.101/b10759/operators006.htm#sthref780"&gt;Oracle supports&lt;/a&gt; MULTISET UNION/EXCEPT/INTERSECT for both ALL/DISTINCT. I have only to make some types, a bit type casting and everything should be ok!&lt;br /&gt;&lt;br /&gt;So I've started with the simple tables I've shown yesterday.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE TABLE t1 AS SELECT mod(rownum, 1000) rn&lt;br /&gt;FROM dba_source WHERE rownum &lt;=50000;&lt;br /&gt;CREATE TABLE t2 AS SELECT * FROM t1;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now I can query both tables and try to compare then. To use multiset operations I need to &lt;a href="http://download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions015.htm#SQLRF00613"&gt;cast subquery&lt;/a&gt; as nested table. To be able to use such type casting I have to create two additional types. The first one is simple Object type containing records I'd like to compare. Second one is object table type, to which I'll cast my subqueries. So they are as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE TYPE t1_type&lt;br /&gt;AS OBJECT ( rn NUMBER);&lt;br /&gt;/&lt;br /&gt;CREATE TYPE t1_tab_type&lt;br /&gt;AS TABLE OF t1_type;&lt;br /&gt;/&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So far so good. Let's start building queries step by step. The first one just builds nested table from subquery.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select cast(multiset(&lt;br /&gt;  2    select rn from t1 where rownum &lt;=3&lt;br /&gt;  3  ) as t1_tab_type)&lt;br /&gt;  4  from dual&lt;br /&gt;  5  /&lt;br /&gt;&lt;br /&gt;CAST(MULTISET(SELECTRNFROMT1WHEREROWNUM&lt;=3)AST1_TAB_TYPE)(RN)&lt;br /&gt;---------------------------------------------------------------&lt;br /&gt;T1_TAB_TYPE(T1_TYPE(1), T1_TYPE(2), T1_TYPE(3))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The second one already uses multiset intersect to get desired result.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select col1 multiset intersect distinct col2&lt;br /&gt;  2  from (&lt;br /&gt;  3    select cast(multiset(&lt;br /&gt;  4      select rn from t1 where rownum &lt;=3&lt;br /&gt;  5    ) as t1_tab_type) col1,&lt;br /&gt;  6    cast(multiset(&lt;br /&gt;  7      select rn from t2 where rownum &lt;=3&lt;br /&gt;  8    ) as t1_tab_type) col2&lt;br /&gt;  9    from dual&lt;br /&gt; 10  )&lt;br /&gt; 11  /&lt;br /&gt;&lt;br /&gt;COL1MULTISETINTERSECTDISTINCTCOL2(RN)&lt;br /&gt;---------------------------------------------------&lt;br /&gt;T1_TAB_TYPE(T1_TYPE(1), T1_TYPE(2), T1_TYPE(3))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now we just need to add one final step - cast nested table rows back to normal rows. Here us helps select from table construct:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select * from table (&lt;br /&gt;  2    select col1 multiset intersect distinct col2&lt;br /&gt;  3    from (&lt;br /&gt;  4      select cast(multiset(&lt;br /&gt;  5        select rn from t1 where rownum &lt;=3&lt;br /&gt;  6      ) as t1_tab_type) col1,&lt;br /&gt;  7      cast(multiset(&lt;br /&gt;  8        select rn from t2 where rownum &lt;=3&lt;br /&gt;  9      ) as t1_tab_type) col2&lt;br /&gt; 10      from dual&lt;br /&gt; 11    )&lt;br /&gt; 12  )&lt;br /&gt; 13  /&lt;br /&gt;&lt;br /&gt;        RN&lt;br /&gt;----------&lt;br /&gt;         1&lt;br /&gt;         2&lt;br /&gt;         3&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Voila! Everything works!&lt;br /&gt;However then I was torn with doubt - how it will work when not used as a toy but on real volumes? I created million rows worth table with wide column and got - yeahh I got following:&lt;br /&gt;&lt;br /&gt;ORA-22813: operand value exceeds system limits&lt;br /&gt;&lt;br /&gt;Not pleasing.&lt;br /&gt;&lt;br /&gt;Then I started to play with the tables defined above and got quite awful results. What is the performance of normal MINUS set operator?&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select * from t1&lt;br /&gt;   2 minus&lt;br /&gt;   3 select * from t2 where rn &lt;=998;&lt;br /&gt;        RN&lt;br /&gt;----------&lt;br /&gt;       999&lt;br /&gt;Elapsed: 00:00:00.10&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What is the equivalent for multiset except distinct? I was a bit unpleasantly surprised again:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select * from table (&lt;br /&gt;   2   select col1 multiset except distinct col2&lt;br /&gt;   3   from (&lt;br /&gt;   4     select cast(multiset(&lt;br /&gt;   5       select rn from t1&lt;br /&gt;   6     ) as t1_tab_type) col1,&lt;br /&gt;   7     cast(multiset(&lt;br /&gt;   8       select rn from t2 where rn &lt;= 998&lt;br /&gt;   9     ) as t1_tab_type) col2&lt;br /&gt;   10     from dual&lt;br /&gt;   11   )&lt;br /&gt;   12 )&lt;br /&gt;   13 /&lt;br /&gt;           RN&lt;br /&gt;   ----------&lt;br /&gt;          999&lt;br /&gt;   Elapsed: 00:01:17.98&lt;br /&gt;   &lt;/pre&gt;&lt;br /&gt;However for multiset except all I was simply shocked!&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select * from table (&lt;br /&gt;   2   select col1 multiset except all col2&lt;br /&gt;   3   from (&lt;br /&gt;   4     select cast(multiset(&lt;br /&gt;   5       select rn from t1&lt;br /&gt;   6     ) as t1_tab_type) col1,&lt;br /&gt;   7     cast(multiset(&lt;br /&gt;   8       select rn from t2 where rn &lt;= 998&lt;br /&gt;   9     ) as t1_tab_type) col2&lt;br /&gt;   10     from dual&lt;br /&gt;   11   )&lt;br /&gt;   12 )&lt;br /&gt;   13 /&lt;br /&gt;          RN&lt;br /&gt;  ----------&lt;br /&gt;         999&lt;br /&gt;         ...&lt;br /&gt;         999&lt;br /&gt;  50 rows selected.&lt;br /&gt;  Elapsed: 00:06:05.39&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;6 minutes for 2 * 50K rows!? Hmm is it implemented using bubble sort or what? :O&lt;br /&gt;&lt;br /&gt;So normal SQL minus needed 0.10 seconds, multiset minus distinct 1 minute 18 seconds, but multiset except all more than 6 minutes.&lt;br /&gt;&lt;br /&gt;Yeahh I got another strong argument &lt;strong&gt;NOT&lt;/strong&gt; to use nested tables and their operations ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-7706395229142950150?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/7706395229142950150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=7706395229142950150' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/7706395229142950150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/7706395229142950150'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/01/minus-all-and-intersect-all-in-oracle_10.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-2248861905034608988</id><published>2008-01-09T18:51:00.000+02:00</published><updated>2008-01-09T19:04:09.030+02:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;MINUS ALL and INTERSECT ALL in Oracle&lt;/h3&gt;&lt;p&gt;Recently I was a bit studying &lt;a href="http://www.wiscorp.com/SQLStandards.html"&gt;SQL standard&lt;/a&gt; and a lot to my surprise found that there exists not only UNION ALL set operator, but also INTERSECT ALL and EXCEPT ALL (in Oracle version it would be MINUS ALL).&lt;/p&gt;&lt;p&gt;So you'd say Oracle haven't them and it is also (although partially - somehow minus has been forgotten) documented in &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/ap_standard_sql004.htm#i7738"&gt;Oracle Support for Optional Features of SQL/Foundation:2003&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Hmm, yea but a while ago I was doing &lt;a href="http://www.gplivna.eu/papers/legacy_app_migration.htm"&gt;several data migrations&lt;/a&gt; and then such set operators would really helped me. Now a bit what these non-existant (at least for Oracle) set operators are doing?&lt;/p&gt;&lt;p&gt;Imagine we have tables T1 and T2 with data as follows:&lt;/p&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;T1: 1, 2, 2, 2, 3, 4, 4&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;T2: 2, 3, 4, 4, 4, 5&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;So what is the result for SELECT * FROM T1 MINUS SELECT * FROM T2?&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;1&lt;/span&gt;&lt;/p&gt;&lt;p&gt;What &lt;em&gt;would be&lt;/em&gt; the result for SELECT * FROM T1 &lt;strong&gt;MINUS ALL&lt;/strong&gt; SELECT * FROM T2?&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;1, 2, 2&lt;/span&gt;&lt;/p&gt;&lt;p&gt;What is the result for SELECT * FROM T1 INTERSECT SELECT * FROM T2?&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;2, 3, 4&lt;/span&gt;&lt;/p&gt;&lt;p&gt;What &lt;em&gt;would be&lt;/em&gt; the result for SELECT * FROM T1 &lt;strong&gt;INTERSECT ALL&lt;/strong&gt; SELECT * FROM T2?&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;2, 3, 4, 4&lt;/span&gt;&lt;/p&gt;&lt;p&gt;As you can see ALL for EXCEPT/MINUS and INTERSECT retains cardinality and doesn't keep only unique records. Let's hope Oracle someday will stop this gap and give us this functionality :)&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-2248861905034608988?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/2248861905034608988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=2248861905034608988' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/2248861905034608988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/2248861905034608988'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2008/01/minus-all-and-intersect-all-in-oracle.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-8391217777773586656</id><published>2007-12-08T22:29:00.000+02:00</published><updated>2007-12-08T22:45:36.065+02:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Oracle wiki&lt;/h3&gt;I've thought for a while about creating an article about the resources available in Oracle problem solving process. Meanwhile &lt;a href="http://wiki.oracle.com/"&gt;Oracle wiki&lt;/a&gt; was born and already exists for about two months. As it is supposed to be shared and editable resource by everyone in Oracle community I thought that it would be a perfect place for my eventual article for two reasons:&lt;br /&gt;1) more people hopefully will read it and probably get some help;&lt;br /&gt;2) more people can add their suggestions how they solve Oracle related problems.&lt;br /&gt;So my first contribution to Oracle wiki is &lt;a href="http://wiki.oracle.com/page/How+to+solve+Oracle+Database+related+problems"&gt;How to solve Oracle Database related problems&lt;/a&gt;. Everyone is invited to correct it and/or add some other resources. As well as for other Oracle wiki pages of course.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-8391217777773586656?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/8391217777773586656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=8391217777773586656' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/8391217777773586656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/8391217777773586656'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/12/oracle-wiki-ive-thought-for-while-about.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-6020764947390883079</id><published>2007-11-26T23:43:00.000+02:00</published><updated>2007-11-26T23:55:38.276+02:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;How to choose database&lt;/h3&gt;&lt;br /&gt;Most of us (I mean readers of Oracle related blogs) most probably have already decided which DBMS to use. However the world is changing and sooner or later either you'll have to choose a new DBMS or defend your favourite one.&lt;br /&gt;Quite often we hear such argument like DB X is cheaper than DB Y, therefore we have to take this one. And cheaper usually means only license cost. However license cost is only one &lt;strong&gt;part of&lt;/strong&gt; &lt;em&gt;direct expenses&lt;/em&gt; not to speak even about &lt;em&gt;indirect expenses&lt;/em&gt;.&lt;br /&gt;So &lt;a href="http://www.gplivna.eu/papers/choose_database.htm"&gt;i've written an article&lt;/a&gt; trying to explain more than 10 criteria which should be analyzed before final decision. Article contains also a list of more than 30 databases with links to their sites one can choose from.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-6020764947390883079?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/6020764947390883079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=6020764947390883079' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/6020764947390883079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/6020764947390883079'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/11/how-to-choose-database-most-of-us-i.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-7812472088654247032</id><published>2007-11-04T19:34:00.000+02:00</published><updated>2007-11-04T19:39:56.338+02:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;The curse of gapless sequences&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;Gapless sequences are one of the best examples of &lt;a href="http://gplivna.blogspot.com/2007/03/where-bad-performance-starts-my.html"&gt;bad requirements&lt;/a&gt;. Initially it was thought as an article for my blog but the result was too big and I've put it &lt;a href="http://www.gplivna.eu/papers/gapless_sequences.htm"&gt;on my site&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-7812472088654247032?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/7812472088654247032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=7812472088654247032' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/7812472088654247032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/7812472088654247032'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/11/curse-of-gapless-sequences-gapless.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-4925125758695468038</id><published>2007-10-25T15:12:00.000+03:00</published><updated>2007-10-25T15:28:03.068+03:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Hints "stronger" than db parameters?&lt;/h3&gt;&lt;p&gt;Actually I've tested only one parameter so the plural in title is questionable generalization :)&lt;/p&gt;&lt;p&gt;Recently battling with ORA-04030: out of process memory errors I found at least for me quite interesting fact.&lt;br /&gt;USE_HASH hint is more powerful than parameter _hash_join_enabled = false (for 10g) or hash_join_enabled = false (for 9i).&lt;br /&gt;I was quite suprised because without this test case I'd thought completely opposite. Of course neither hash_join_enabled nor _hash_join_enabled should be often altered to different value than default "true", but in case of "false" and your code having hints use_hash, you'll have hash joins regardless of above mentioned db parameter setting. It might be quite nasty surprise in case you have eliminated hash joins because of possible bugs, for example.&lt;br /&gt;I've tested this behaviour for 10.2.0.1.0 SE and 10.2.0.1.0 EE on Windows as well as 10.2.0.3.0 SE on AIX and 9.2.0.7.0 EE on windows, all had the same behaviour.&lt;br /&gt;Here is my test case and 10046 event trace execution plan results on 10.2.0.1.0 SE/Windows (all other tests were similar):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select * from v$version;&lt;br /&gt;BANNER&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;Oracle Database 10g Release 10.2.0.1.0 - Production&lt;br /&gt;PL/SQL Release 10.2.0.1.0 - Production&lt;br /&gt;CORE 10.2.0.1.0 Production&lt;br /&gt;TNS for 32-bit Windows: Version 10.2.0.1.0 - Production&lt;br /&gt;NLSRTL Version 10.2.0.1.0 - Production&lt;br /&gt;&lt;br /&gt;SQL&gt; create table a as select rownum rn, object_name&lt;br /&gt;  2  from all_objects;&lt;br /&gt;&lt;br /&gt;Table created.&lt;br /&gt;&lt;br /&gt;SQL&gt; alter session set events '10046 trace name context forever, level 1';&lt;br /&gt;&lt;br /&gt;Session altered.&lt;br /&gt;&lt;br /&gt;SQL&gt; select count(*) from (&lt;br /&gt;  2    select *&lt;br /&gt;  3    from a a1, a a2&lt;br /&gt;  4    where a1.rn = a2.rn);&lt;br /&gt;&lt;br /&gt;  COUNT(*)&lt;br /&gt;----------&lt;br /&gt;     60141&lt;br /&gt;&lt;br /&gt;Execution plan:&lt;br /&gt;STAT #24 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=556 pr=73 pw=0 time=212727 us)'&lt;br /&gt;STAT #24 id=2 cnt=60141 pid=1 pos=1 obj=0 op='HASH JOIN (cr=556 pr=73 pw=0 time=406508 us)'&lt;br /&gt;STAT #24 id=3 cnt=60141 pid=2 pos=1 obj=176936 op='TABLE ACCESS FULL A (cr=278 pr=73 pw=0 time=61652 us)'&lt;br /&gt;STAT #24 id=4 cnt=60141 pid=2 pos=2 obj=176936 op='TABLE ACCESS FULL A (cr=278 pr=0 pw=0 time=60192 us)'&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;SQL&gt; alter session set "_hash_join_enabled" = false;&lt;br /&gt;&lt;br /&gt;Session altered.&lt;br /&gt;&lt;br /&gt;SQL&gt; select count(*) cnt from (&lt;br /&gt;  2    select *&lt;br /&gt;  3    from a a1, a a2&lt;br /&gt;  4    where a1.rn = a2.rn);&lt;br /&gt;&lt;br /&gt;       CNT&lt;br /&gt;----------&lt;br /&gt;     60141&lt;br /&gt;&lt;br /&gt;Execution plan:&lt;br /&gt;STAT #12 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=556 pr=0 pw=0 time=374302 us)'&lt;br /&gt;STAT #12 id=2 cnt=60141 pid=1 pos=1 obj=0 op='MERGE JOIN (cr=556 pr=0 pw=0 time=470826 us)'&lt;br /&gt;STAT #12 id=3 cnt=60141 pid=2 pos=1 obj=0 op='SORT JOIN (cr=278 pr=0 pw=0 time=88667 us)'&lt;br /&gt;STAT #12 id=4 cnt=60141 pid=3 pos=1 obj=176936 op='TABLE ACCESS FULL A (cr=278 pr=0 pw=0 time=44 us)'&lt;br /&gt;STAT #12 id=5 cnt=60141 pid=2 pos=2 obj=0 op='SORT JOIN (cr=278 pr=0 pw=0 time=231092 us)'&lt;br /&gt;STAT #12 id=6 cnt=60141 pid=5 pos=1 obj=176936 op='TABLE ACCESS FULL A (cr=278 pr=0 pw=0 time=60174 us)'&lt;br /&gt;&lt;br /&gt;SQL&gt; select count(*) cnt from (&lt;br /&gt;  2    select /*+ full(a1) full(a2) use_hash(a1 a2)*/ *&lt;br /&gt;  3    from a a1, a a2&lt;br /&gt;  4    where a1.rn = a2.rn);&lt;br /&gt;&lt;br /&gt;       CNT&lt;br /&gt;----------&lt;br /&gt;     60141&lt;br /&gt;&lt;br /&gt;Execution plan:&lt;br /&gt;STAT #24 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=556 pr=73 pw=0 time=214116 us)'&lt;br /&gt;STAT #24 id=2 cnt=60141 pid=1 pos=1 obj=0 op='HASH JOIN (cr=556 pr=73 pw=0 time=399462 us)'&lt;br /&gt;STAT #24 id=3 cnt=60141 pid=2 pos=1 obj=176936 op='TABLE ACCESS FULL A (cr=278 pr=73 pw=0 time=60803 us)'&lt;br /&gt;STAT #24 id=4 cnt=60141 pid=2 pos=2 obj=176936 op='TABLE ACCESS FULL A (cr=278 pr=0 pw=0 time=60188 us)'&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-4925125758695468038?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/4925125758695468038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=4925125758695468038' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/4925125758695468038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/4925125758695468038'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/10/hints-stronger-than-db-parameters.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-8250503278390438798</id><published>2007-10-17T23:41:00.000+03:00</published><updated>2007-10-17T23:50:33.218+03:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;All latvian Oracle (and not only) users - UNITE!&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;I'd like to announce two resources for people that like relational databases and speak Latvian.&lt;br /&gt;The first one is &lt;a href="http://groups.google.ca/group/lvoug"&gt;discussion group&lt;/a&gt; for Latvian Oracle User Group. The near future plans are described &lt;a href="http://groups.google.ca/group/lvoug/browse_frm/thread/2372a5195e9f753b"&gt;here&lt;/a&gt; (in Latvian).&lt;br /&gt;If you speak Latvian and work with Oracle then it is your duty :) to join it! Of course one can join even if he doesn't speak Latvian, however there will be a small problem - everyone will understand you, but it is doubtful that you will understand anything except some keywords like Oracle, SQL, etc :)&lt;br /&gt;&lt;br /&gt;The second resource is mine. And it is more general, it is &lt;a href="http://datubazes.wordpress.com/"&gt;blog about relational databases&lt;/a&gt; (in Latvian).&lt;br /&gt;Recently I've searched Internet and was very unpleasantly surprised - I've found &lt;a href="http://datubazes.wordpress.com/2007/10/10/db-resursi-latvija/"&gt;very few resources&lt;/a&gt; devoted to relational databases. So not to make only complaints I've started to blog about relational databases in my mother tongue. I'm of course not living in illusions that I can do it only myself and therefore anyone that is at least a little bit eager to help me in this process and has some knowledge either in general SQL, Oracle, MS SQL Server, MySQL, PosgreSQL or another relational db is encouraged to join me and become author in this blog.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-8250503278390438798?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/8250503278390438798/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=8250503278390438798' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/8250503278390438798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/8250503278390438798'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/10/all-latvian-oracle-and-not-only-users.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-2592885554226331936</id><published>2007-10-02T11:43:00.000+03:00</published><updated>2007-10-02T13:31:12.464+03:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;Natural joins are evil&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;em&gt;Motto:&lt;/em&gt;&lt;br /&gt;&lt;em&gt;If you like time bombs use them ;)&lt;br /&gt;&lt;/em&gt;&lt;br /&gt;During my &lt;a href="http://gplivna.blogspot.com/2007/08/new-experience-ive-completed-my-first.html"&gt;teaching courses&lt;/a&gt; I once again stumble upon ANSI SQL NATURAL JOIN syntax. And once again I suspect that creators of them had in mind something like &lt;a href="http://www.web-hits.org/txt/codingunmaintainable.html"&gt;how to write unmaintainable code&lt;/a&gt;. Or probably they liked time bombs ;)&lt;br /&gt;OK for those unfamiliar with Natural joins let's firstly see &lt;a href="http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_10002.htm#sthref9697"&gt;what they mean&lt;/a&gt;:&lt;br /&gt;"A natural join is based on all columns in the two tables that have the same name. It selects rows from the two tables that have equal values in the relevant columns."&lt;br /&gt;So it joins two tables if column names are the same. There &lt;em&gt;isn't any explicit join condition&lt;/em&gt;. And here is the biggest problem. The work has been done &lt;em&gt;behind the scenes&lt;/em&gt;, and that is one of the biggest advantages of &lt;a href="http://www.web-hits.org/txt/codingunmaintainable.html"&gt;writing unmaintainable code&lt;/a&gt;.&lt;br /&gt;So let's assume we have following tables:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CREATE TABLE persons (&lt;br /&gt;person_id NUMBER(10) NOT NULL,&lt;br /&gt;address_id NUMBER(10) NOT NULL,&lt;br /&gt;surname VARCHAR2(40) NOT NULL,&lt;br /&gt;first_name VARCHAR2(40) NOT NULL,&lt;br /&gt;remarks VARCHAR2(1000),&lt;br /&gt;CONSTRAINT person_pk PRIMARY KEY (person_id));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CREATE TABLE addresses (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;address_id NUMBER(10) NOT NULL,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;country VARCHAR2(40) NOT NULL,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;city VARCHAR2(40),&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;text VARCHAR2(100) NOT NULL,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CONSTRAINT address_pk PRIMARY KEY (address_id));&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ALTER TABLE persons ADD CONSTRAINT person_address_fk &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;FOREIGN KEY (address_id) REFERENCES addresses (address_id);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Lets add a few rows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;INSERT INTO addresses &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;VALUES (1, 'LATVIA', 'RIGA', 'BRIVIBAS STREET 100');&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;INSERT INTO persons &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;VALUES (1, 1, 'PLIVNA', 'GINTS', 'Actually he lives in another place');&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So what would be the SQL query to get persons and their countries using NATURAL JOIN syntax?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; SELECT surname, first_name, country&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;2 FROM persons&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;3 NATURAL JOIN addresses;&lt;br /&gt;SURNAME&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;----------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;FIRST_NAME&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;----------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;COUNTRY&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;----------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;PLIVNA&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;GINTS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;LATVIA&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;1 row selected.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Nice one - we got one row as expected.&lt;br /&gt;So assume times goes by and as per our new requirements we have to add some description field also in addresses table. To be consistent and following practices that differ from &lt;a href="http://www.web-hits.org/txt/codingunmaintainable.html"&gt;how to write unmaintainable code&lt;/a&gt; we use the same column name and data type as in persons.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ALTER TABLE addresses ADD remarks VARCHAR2(1000);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So what our query is showing now?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; SELECT surname, first_name, country&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;2 FROM persons&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;3 NATURAL JOIN addresses;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;no rows selected&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;WoW&lt;/span&gt;! Where the row has gone? We didn't change our data!&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Yeahhhh&lt;/span&gt;, everything works as expected. We added column remarks with the same name as in persons table and now join is being done using both columns. And of course data in persons.remarks column doesn't match with addresses.remarks. So our time bomb has blown up and we silently introduced a nasty bug in our system. Code is as valid as before from the compilation viewpoint, so we won't get compilation errors. It simply gives wrong result. Invalid &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;SQL&lt;/span&gt; would be much better, then we'd spotted bug much easier, but this time we got exactly very nasty and in the beginning absolutely unclear bug.&lt;br /&gt;&lt;br /&gt;There are also other things to consider:&lt;br /&gt;1) natural joins between two tables without at least one common column results in cartesian product.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CREATE TABLE numbers AS &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SELECT rownum id &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;FROM all_source;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Lets see how many rows table numbers have and how many rows we got for natural join between them:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; SELECT count(*) FROM numbers;&lt;br /&gt;COUNT(*)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;----------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;549290&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;1 row selected.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; SELECT count(*) FROM (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;2 SELECT * FROM person&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;s&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;3 NATURAL JOIN numbers);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;COUNT(*)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;----------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;549290&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;1 row selected.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;2) with different data types but the same column names there might be type conversion problems and quite strange error messages (see that it is &lt;em&gt;NATURAL OUTER LEFT or RIGHT JOIN&lt;/em&gt;):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ALTER TABLE addresses MODIFY remarks NUMBER (15);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; SELECT surname, first_name, country&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;2 FROM persons&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;3 NATURAL LEFT JOIN addresses;&lt;br /&gt;SURNAME&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;----------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;FIRST_NAME&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;----------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;COUNTRY&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;----------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;PLIVNA&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;GINTS&lt;br /&gt;&lt;br /&gt;1 row selected.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; ed&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Wrote file afiedt.buf&lt;br /&gt;1 SELECT surname, first_name, country&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;2 FROM persons&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;3* NATURAL RIGHT JOIN addresses&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; /&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SELECT surname, first_name, country&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;*&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ERROR at line 1:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ORA-01722: invalid number&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So what to do?&lt;br /&gt;1) Do not use this syntax. This is the most efficient and most obvious solution.&lt;br /&gt;2) Use the same schema object &lt;a href="http://www.gplivna.eu/papers/naming_conventions.htm"&gt;naming conventions&lt;/a&gt; as me :) Natural joins simply never work using my favourite naming conventions.&lt;br /&gt;&lt;br /&gt;Similar threads:&lt;br /&gt;1) &lt;a href="http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:8764523461767"&gt;Natural Join and Index Monitoring&lt;/a&gt; in asktom.&lt;br /&gt;2) Thread &lt;a href="http://www.freelists.org/archives/oracle-l/10-2006/msg00615.html"&gt;should one use ANSI join syntax when writing an Oracle application&lt;/a&gt; from &lt;a href="http://www.freelists.org/archives/oracle-l/"&gt;Oracle-l&lt;/a&gt; list.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-2592885554226331936?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/2592885554226331936/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=2592885554226331936' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/2592885554226331936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/2592885554226331936'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/10/natural-joins-are-evil-motto-if-you.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-5190679400099742066</id><published>2007-09-16T01:34:00.000+03:00</published><updated>2007-09-16T02:14:21.787+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Development process'/><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;Avoiding trouble&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Following post could be seen absolutely obvious mechanism to avoid unnecessary trouble in development process. But it was &lt;em&gt;something new for me&lt;/em&gt; when several years ago I've firstly read it from the long term &lt;a href="http://www.freelists.org/archives/oracle-l/"&gt;oracle-l&lt;/a&gt; list ex member Rachel Carmichael (unfortunately I've lost this e-mail) and now I've seen it is something new for many developers. In one sentence it is:&lt;br /&gt;&lt;strong&gt;Inform your boss (customer, colleague or other responsible person) about possible trouble in a &lt;em&gt;written and provable&lt;/em&gt; way.&lt;/strong&gt;&lt;br /&gt;OK now let's explain a bit more. There are three steps in this process:&lt;br /&gt;1) Understand possibility for eventual trouble;&lt;br /&gt;2) Fight for your &lt;em&gt;right&lt;/em&gt; decision;&lt;br /&gt;3) If you lost the battle inform responsible person about it explaining &lt;em&gt;why&lt;/em&gt; you think there is possibility for trouble.&lt;br /&gt;Let's see what each of these steps mean.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Understand possibility for eventual trouble&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Here is the trickiest part. The first tricky thing is to understand that there might be possible trouble. Of course that comes with experience ;) Probably the first time you'll miss the eventual trouble but next time you'll be already smarter. The second tricky thing is to avoid never ending wretch syndrome. And here of course the main factor is your common sense - decide when to warn responsible person and when to not use false warnings.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Fight for your right decision&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Almost always there is a possibility to fight for your decision. Of course here is also one tricky thing - you have to explain and motivate your decision. You can enforce your decision with test cases, examples, resources from books, Internet etc. You can find supporters among your colleagues and sometimes even usual opponents. Even if you'll loose at least you'll have clear conscience :)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Inform responsible person about it&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This is the easy part. If you have decided that you should warn anybody then most of the time there is no need to seek for a notary. Usually a simple e-mail saved in your sent mails will be enough. You can of course consider possibility to add some more recipients to TO: or CC: fields. If it is a meeting protocol with customer a footnote with warning can be a solution. Of course if the possible consequences are quite serious you have to ensure that your insurance is at least as serious. One thing of course remains - the motivation has to be kept. Also in your written email, meeting protocol or whatever else.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The result&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;With above mentioned mechanism you've got two points:&lt;br /&gt;1) O&lt;em&gt;nce again informed about your decision.&lt;/em&gt;&lt;br /&gt;It might be possible that your boss simply missed your viewpoint. Probably he thought you are not serious enough. Probably he misunderstood you. Written text with appropriate explanation and motivation decrease such probability to the minimum.&lt;br /&gt;2) C&lt;em&gt;over your a$$ (sorry for that expression but I couldn't resist :) in case of failure.&lt;/em&gt;&lt;br /&gt;You will be able to point to your written message and say - I already warned you. Without it there are always place for different interpretations. Even the most ordinary thing - your boss probably simply fairly and honestly forgot about your warnings. With such cover even if you need to clean up the mess you won't pay for it. Your boss, your customer or whatever else responsible party being warned will pay for it.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Have I used that?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Yes, I have. I was lucky enough to have knowing and smart bosses till now so I haven't necessity to use such scenario (3rd step) inside my company. Either I could convince my bosses or the problem was out of my responsibility. But in communication with customers I've used this technique quite much along with &lt;a href="http://gplivna.blogspot.com/2007/03/where-bad-performance-starts-my.html"&gt;catching their bad requirements&lt;/a&gt;. Sometimes that convinced them at last change their minds, sometimes not, but at least I and my company had very strong argument in case of failure.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-5190679400099742066?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/5190679400099742066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=5190679400099742066' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/5190679400099742066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/5190679400099742066'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/09/avoiding-trouble-following-post-could.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-2927963055458703253</id><published>2007-09-03T09:38:00.000+03:00</published><updated>2007-09-03T09:53:39.768+03:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;Unrealistic optimism or just pure stupidity?&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;A while ago I've written a blog entry &lt;a href="http://gplivna.blogspot.com/2007/03/where-bad-performance-starts-my.html"&gt;Where bad performance starts&lt;/a&gt; explaining that we as IT professionals should prevent customers from stupid requirements or at least strongly warn them that their desires will make much harder life both for customers and developers.&lt;br /&gt;&lt;br /&gt;Some days ago I've spotted a nice estimate of a work task that takes the problem described above to the next level i.e. the core of problem is initiated even before the real project begins. Task was much bigger containing of many subtasks including:&lt;br /&gt;1) three separated subtasks for three different reports. Each report was quite precisely explained;&lt;br /&gt;2) a task formulated as follows: "Up to 20 reports defined more accurately in analysis phase". No more information was supplied, no more information was known to anyone.&lt;br /&gt;&lt;br /&gt;So how do you think - what were the estimates for analysis and implementation? According to estimate analysis of each separated report should take 1, 2 and 3 workdays. Implementation estimate of each of them was 2, 3.5 and 3.5 workdays. And now the most interesting part: analysis and implementation of up to 20 unknown reports was estimated 15 days for analysis and 20 days for implementation.&lt;br /&gt;&lt;br /&gt;So for &lt;em&gt;known and quite precisely defined&lt;/em&gt; reports the average analysis and implementation work was estimated &lt;strong&gt;2&lt;/strong&gt; and &lt;strong&gt;3&lt;/strong&gt; days respectively for each report. BUT for &lt;em&gt;completely unknown&lt;/em&gt; reports without any further information and/or restriction estimate was &lt;strong&gt;0.75&lt;/strong&gt; days for analysis and &lt;strong&gt;1&lt;/strong&gt; day for implementation.&lt;br /&gt;BAHHH!&lt;br /&gt;So what to think? What was thinking both analyst and programmer making such estimates? What was thinking PM allowing such estimates to be published and giving them to customer?Are they afraid of big numbers? Why are they being so optimistic? It is a real mystery...&lt;br /&gt;I'd be afraid to give any estimate for such purely defined task at all. And if I'd give I'd take at least average or even probably maximum of other similar tasks and also warn my boss about quite big risk to give estimates of unknown tasks. Probably I've seen too much projects fail or at least delay due to overly optimistic estimates...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-2927963055458703253?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/2927963055458703253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=2927963055458703253' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/2927963055458703253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/2927963055458703253'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/09/unrealistic-optimism-or-just-pure.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-819083864775607893</id><published>2007-08-27T18:12:00.000+03:00</published><updated>2007-08-27T18:20:25.489+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Oracle SQL Server Express Edition'/><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;Oracle Express Edition and MS &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;SQL&lt;/span&gt; Server Express Edition&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Today I was listening to a course from &lt;a href="http://msdn2.microsoft.com/en-us/library/bb418498.aspx"&gt;the dark side&lt;/a&gt; ;) One quite small fact (I was not aware of) about &lt;a href="http://msdn2.microsoft.com/en-us/library/ms345154.aspx"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;SQL&lt;/span&gt; Server 2005 Express Edition&lt;/a&gt; compared to &lt;a href="http://www.oracle.com/technology/pub/articles/cunningham-database-xe.html"&gt;Oracle 10g XE&lt;/a&gt; caught my attention though.&lt;br /&gt;These versions are similar in their limitations i.e.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;1 CPU&lt;/li&gt;&lt;li&gt;1 GB RAM&lt;/li&gt;&lt;li&gt;4 GB user data&lt;/li&gt;&lt;/ul&gt;But there is one difference not in favour of Oracle - for &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;SQL&lt;/span&gt; Server Express Edition one can create up to 16 instances on a single box, but for Oracle XE only one. Of course in general it is not the main decisive factor to choose between &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;SQL&lt;/span&gt; Server and Oracle, but I can imagine some scenarios where more than one instance of Oracle XE on a single box would be nice, for example, simultaneous development of different applications on XE.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-819083864775607893?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/819083864775607893/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=819083864775607893' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/819083864775607893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/819083864775607893'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/08/oracle-express-edition-and-ms-sql.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-6228996617432952280</id><published>2007-08-21T21:31:00.000+03:00</published><updated>2007-08-21T22:02:51.817+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='oracle training'/><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;A new experience&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;I've completed my first Oracle certified training course in &lt;a href="http://www.mebius.lv/"&gt;Mebius Latvia&lt;/a&gt;. This time as a &lt;strong&gt;&lt;em&gt;trainer&lt;/em&gt;&lt;/strong&gt; though.&lt;br /&gt;For already a few years I feel necessity somebody to tell what I've learned and how to do or not to do certain things in Oracle ;)&lt;br /&gt;&lt;br /&gt;The first step was my &lt;a href="http://www.gplivna.eu/"&gt;website&lt;/a&gt; where I could put some &lt;a href="http://www.gplivna.eu/papers_e.htm"&gt;articles&lt;/a&gt; telling some experience stories. Now I've completed the next step – directly telling people how to work with Oracle. The content of my first course as a trainer was quite trivial – 10g PL/SQL fundamentals. Although describing more than 250 slides in two days, even quite easy slides, was a completely new experience for me. I hope I've completed it more or less so that my trainees understood what I was talking about ;) In fact I was really satisfied with them, because all had more or less experience with Oracle and programming as such, so there wasn't necessity to tell for example what the "IF" statement and logical values are. In the very beginning I frankly told them that questions help not only trainees to deeper understand the covered material but questions also help the trainer to feel better and understand that at least some trainees are following the lesson material ;) So they really followed my plea and time after time we had even discussions about one or another topic. So I'm thankful to my trainees, I hope they understood at least main things I told them and I'm looking forward to my next course after a while.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-6228996617432952280?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/6228996617432952280/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=6228996617432952280' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/6228996617432952280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/6228996617432952280'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/08/new-experience-ive-completed-my-first.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-6051359941476707862</id><published>2007-08-09T17:50:00.000+03:00</published><updated>2007-08-09T18:20:49.243+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='drop source code flashback'/><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;Flashback for source code&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Recent &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=541210&amp;tstart=50"&gt;OTN forum question&lt;/a&gt; made me think that I'm quite lucky. Everywhere I've worked we had one or another &lt;a href="http://en.wikipedia.org/wiki/Comparison_of_revision_control_software"&gt;source control software&lt;/a&gt; for source code. All scripts for schema creation as well as procedural units were put and maintained there. Sometimes reading about other people's problems that they've lost the only (sic!) version of their procedure dropping the schema or just recreating the procedure gives me the shudders. So for everyone that yet hasn't understood - keeping procedural units only in the db means it is just matter of time when you'll lose them. Either all of them or just one because of erroneous create or replace but sooner or later the time will come ;)&lt;br /&gt;&lt;br /&gt;OK but what if you are unlucky and just realized that you have overwritten the last and only version of your source code unit (procedure, package, function, etc)? If you are at least on 9i (10g as well of course) you are not completely lost. &lt;a href="http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14251/adfns_flashback.htm#sthref1446"&gt;Flashback&lt;/a&gt; that works on regular user's tables works in the same way also on internal tables holding source code. So the only problem remains how to get it and how to get it fast! Fast because it is just like with lost extremities - surgeon can put it back only if you are acting fast. And fast because the old data can simply be &lt;a href="http://download.oracle.com/docs/cd/B19306_01/server.102/b14231/undo.htm#BJFFIACJ"&gt;overwritten&lt;/a&gt; if Oracle feels the necessity. And now what's the mechanism is?&lt;br /&gt;&lt;br /&gt;There are 2 scenarios:&lt;br /&gt;1. query directly from base tables owned by sys or&lt;br /&gt;2. query using provided dba/all/user views i.e. dba/all/user_source.&lt;br /&gt;&lt;br /&gt;In any case for ordinary user by default it is not possible. You need sys access to do that or grant privilege from sys to any other user. Even DBA role is not enough.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;1st scenario is as follows:&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;1) get object_id (from dba/all/user_objects)&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SELECT object_id &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;FROM user_objects &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;WHERE object_name = 'yourname'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;AND object_type = 'yourtype';&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;2) get text from source$ as of timestamp&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SELECT source&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;FROM sys.source$ &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;AS OF timestamp timestamp_before_error&lt;timestamp&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;WHERE obj# =&lt;/span&gt; object_id_from_1st_step&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ORDER BY line;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;1st step can be done by everyone. 2&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;nd&lt;/span&gt; step needs flashback on source$.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;nd&lt;/span&gt; scenario is as follows:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;simply select text from user/all/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;dba&lt;/span&gt;_source as of timestamp.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SELECT text &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;FROM &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;dba&lt;/span&gt;_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;source&lt;/span&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;AS OF timestamp timestamp_before_error&lt;timestamp&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;WHERE name = '&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;yourname&lt;/span&gt;' &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;AND owner = '&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;yourowner&lt;/span&gt;'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;AND type = 'yourtype'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ORDER BY line;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Of course this can be done by &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;sys&lt;/span&gt;. I was not able to do that by other user because user_source for example is based on source$, obj$ and fixed table x$&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;joxfs&lt;/span&gt;. I was able to grant flashback on source$, obj$ to another user but for fixed tables it is not possible (quite understandable as these are actually memory structures). But it seems on the other hand without flashback one cannot make queries from view that is based both on ordinary tables and fixed tables.&lt;br /&gt;Above experiments were performed both on 9.2.0.7.0 and 10.2.0.1.0 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;EE&lt;/span&gt; Oracle.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-6051359941476707862?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/6051359941476707862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=6051359941476707862' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/6051359941476707862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/6051359941476707862'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/08/flashback-for-source-code-recent-otn.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-2199030579476120376</id><published>2007-06-15T01:19:00.000+03:00</published><updated>2007-06-15T01:41:01.172+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gplivna.eu'/><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;&lt;a href="http://gplivna.eu/desc_e.htm"&gt;gplivna.eu&lt;/a&gt; domain has lived already a year now&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.deac.lv/"&gt;My provider&lt;/a&gt; has provided a wonderful feature - collecting various statistics about visitors of my site. I really suggest everyone to find such provider or at least use &lt;a href="http://www.google.com/analytics"&gt;Google analytics&lt;/a&gt; to collect various stats about your site.&lt;br /&gt;&lt;br /&gt;I started &lt;a href="http://gplivna.eu/desc_e.htm"&gt;my site&lt;/a&gt; a bit more than a year ago on May 2006. In the first month I was the only visitor testing how it looks like and adding some content. In the second month (June 2006) I had already 65 unique ip addresses visited &lt;a href="http://gplivna.eu/desc_e.htm"&gt;my site&lt;/a&gt;. It was a real advancement :) Compared that to today - this is normal weekday rate for my site. Of course on weekends attendance drops.&lt;br /&gt;&lt;br /&gt;Statistics provided by my Internet provider gave me interesting possibility to create a world map. All countries having at least one person visiting &lt;a href="http://gplivna.eu/desc_e.htm"&gt;my site&lt;/a&gt; has been coloured more or less black. More black - more visitors. Colouring the map was interesting task - I even had to look in world atlas for some countries, shame on me - but just using skeleton map I was not sure exactly which country &lt;a href="http://en.wikipedia.org/wiki/Ghana"&gt;Ghana&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Dominican_republic"&gt;Dominican Republic&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Guatemala"&gt;Guatemala&lt;/a&gt; are. The most lovely were countries like &lt;a href="http://en.wikipedia.org/wiki/Indonesia"&gt;Indonesia&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Canada"&gt;Canada&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Philippines"&gt;Philippines&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Russia"&gt;Russia&lt;/a&gt; - having so many islands and each one has to be coloured separately.&lt;br /&gt;&lt;br /&gt;So what are the lessons I've learned this year?&lt;br /&gt;&lt;br /&gt;1. Don't make fun with &lt;a href="http://www.google.com/"&gt;Google&lt;/a&gt;! It can give you so many hits. And it also can be annoyed and give you nothing. Annoyance for my site was because of two reasons:&lt;br /&gt;1) changing content too rapidly&lt;br /&gt;2) having the same articles in 2 different formats - html and doc.&lt;br /&gt;So the medicine was think more about content and change it only once and place deny on &lt;a href="http://www.robotstxt.org/wc/robots.html"&gt;robots.txt&lt;/a&gt; for doc files.&lt;br /&gt;&lt;br /&gt;2. &lt;a href="https://www.google.com/webmasters/tools/siteoverview"&gt;Google webmasters&lt;/a&gt; tool is really useful. One can submit sitemaps, so decreasing the time for Google to catch your new page, view restricted pages by &lt;a href="http://www.robotstxt.org/wc/robots.html"&gt;robots.txt&lt;/a&gt; and a bunch of other features.&lt;br /&gt;&lt;br /&gt;3. All other search engines unfortunately at least for me gives almost nothing. Even &lt;a href="http://www.yahoo.com/"&gt;yahoo&lt;/a&gt; is almost dead for my site.&lt;br /&gt;&lt;br /&gt;4. Placing valuable content is as critical as thinking about titles and words in your articles at least for Google.&lt;br /&gt;&lt;br /&gt;5. Writing articles that hopefully are usable also for other people aren't so easy therefore I even more admire people having written books with precise technical info like &lt;a href="http://asktom.oracle.com/"&gt;Thomas Kyte&lt;/a&gt; and &lt;a href="http://www.jlcomp.demon.co.uk/"&gt;Jonathan Lewis&lt;/a&gt; for example.&lt;br /&gt;&lt;br /&gt;So one month May 2007 gave almost the same stats as all previous year together (actually half of the year because June was the first month for wide public). Let's hope the trend in the future will be the same :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-2199030579476120376?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/2199030579476120376/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=2199030579476120376' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/2199030579476120376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/2199030579476120376'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/06/gplivna.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-5647694955535695559</id><published>2007-05-07T23:04:00.000+03:00</published><updated>2007-05-07T23:46:22.714+03:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;Deferred constraint real life scenario&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;em&gt;Motto:&lt;/em&gt;&lt;br /&gt;&lt;em&gt;It is worth to know oracle features even if you have never used them.&lt;br /&gt;&lt;/em&gt;&lt;br /&gt;Some days ago one of our developers came in and started to tell that our testers found another bug. This time bug is raised in Oracle by violated unique key. Of course developer didn't catch it in unit testing because it was a bit tricky but our testers were smart and nasty :) enough to dig it out.&lt;br /&gt;So we had a form that may have many child records for a previously chosen parent record. To feel something concrete let's choose for the parent an order for tax discount - suppose you have submitted it in written form to your local government (not that I'm suggesting you to do that :))). But of course your local government doesn't want to give you tax discount and therefore as always asks you many documents explaining reason for it. But there is one restriction - each document must be of different kind e.g. one proving that you have 5 children, second proving that your rent has risen by 25% etc.&lt;br /&gt;So as I strongly believe that &lt;a href="http://www.gplivna.eu/papers/data_waste_or_data_base.htm"&gt;business constraints should be enforced in db as much as possible &lt;/a&gt;I've created UK in supporting documents for two columns:&lt;br /&gt;1) FK to order table and&lt;br /&gt;2) document type.&lt;br /&gt;Unfortunately in the form where all documents are entered one can change all attributes and our evil testers of course found the most evil one - swapped type of document A to document B and document B to document A.&lt;br /&gt;So where are the problem you ask? Yea there aren't any problem if one looks on the start point (docs A and B for one order) and finish point (docs B and A for the same order), but somehow situation in the middle is very unpleasant. There is a moment when we have 2 documents with type B simultaneously. And here testers got the error as below:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; create table parent (par_id number not null constraint par_pk primary key);&lt;br /&gt;Table created.&lt;br /&gt;SQL&gt; ed&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Wrote file afiedt.buf&lt;br /&gt;1 create table child (cld_id number not null constraint cld_pk primary key,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;2 cld_par_id number not null constraint cld_par_fk references parent (par_id),&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;3 cld_type varchar2(3) not null,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;4 cld_data varchar2(100),&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;5* constraint cld_uk unique (cld_par_id, cld_type))&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; /&lt;br /&gt;Table created.&lt;br /&gt;SQL&gt; insert into parent values (1);&lt;br /&gt;1 row created.&lt;br /&gt;SQL&gt; insert into child values (1, 1, 'A', 'Doc type A');&lt;br /&gt;1 row created.&lt;br /&gt;SQL&gt; insert into child values (2, 1, 'B', 'Doc type B');&lt;br /&gt;1 row created.&lt;br /&gt;SQL&gt; commit;&lt;br /&gt;Commit complete.&lt;br /&gt;SQL&gt; update child set cld_type = 'B' where cld_id = 1;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;update child set cld_type = 'B' where cld_id = 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;*&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ERROR at line 1:ORA-00001: unique constraint (GINTS.CLD_UK) violated&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So what to do?&lt;br /&gt;My immediate response was - &lt;a href="http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14220/data_int.htm#i4665"&gt;deferred constraints&lt;/a&gt;! I definitely knew that I don't want to loose the constraint forever because I'd like to enforce as much as possible integrity constraints in DB. So how it looks with deferred constraints?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; alter table child drop constraint cld_uk;&lt;br /&gt;Table altered.&lt;br /&gt;SQL&gt; ed&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Wrote file afiedt.buf&lt;br /&gt;1 alter table child add constraint cld_uk unique (cld_par_id, cld_type)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;2* deferrable initially deferred&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; /&lt;br /&gt;Table altered.&lt;br /&gt;SQL&gt; update child set cld_type = 'B' where cld_id = 1;&lt;br /&gt;1 row updated.&lt;br /&gt;SQL&gt; update child set cld_type = 'A' where cld_id = 2;&lt;br /&gt;1 row updated.&lt;br /&gt;SQL&gt; commit;&lt;br /&gt;Commit complete.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Everything works!&lt;br /&gt;How does it look like now?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; select cld_id, cld_par_id, cld_type from child;&lt;br /&gt;CLD_ID CLD_PAR_ID CLD&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;---------- ---------- ---&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;1 1 B&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;2 1 A&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Let's try some more experiments. Let's update only one row back and try to commit:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; update child set cld_type = 'A' where cld_id = 1;&lt;br /&gt;1 row updated.&lt;br /&gt;SQL&gt; commit;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;commit&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;*&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ERROR at line 1:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ORA-02091: transaction rolled back&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ORA-00001: unique constraint (GINTS.CLD_UK) violated&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Bahhh!!! We got expected error!&lt;br /&gt;The only thing - one has to remember that deferred constraints rolls back ALL transaction since it started even if the changed rows are completely valid and unrelated to the deferred constraint for example let's try to insert one completely valid row in parent table at first and then try to do nasty things with deferred constraint:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; insert into parent values (2);&lt;br /&gt;1 row created.&lt;br /&gt;SQL&gt; update child set cld_type = 'A' where cld_id = 1;&lt;br /&gt;1 row updated.&lt;br /&gt;SQL&gt; select * from parent;&lt;br /&gt;PAR_ID&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;----------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;2&lt;br /&gt;SQL&gt; commit;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;commit&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;*&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ERROR at line 1:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ORA-02091: transaction rolled back&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ORA-00001: unique constraint (GINTS.CLD_UK) violated&lt;br /&gt;SQL&gt; select * from parent;&lt;br /&gt;PAR_ID&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;----------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Our inserted row into parent table also has gone. With normal (i.e. not deferred) constraint Oracle rolls back only changes made by the latest statement not all statements since transaction started. One has to remember this behaviour when using deferred constraints.&lt;br /&gt;&lt;br /&gt;Quite popular use of deferred constraints seems to be &lt;a href="http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:914629004506"&gt;update of primary keys&lt;/a&gt; (and after that also foreign keys) but as I'm always (OK almost always) using surrogates and primary key update for me is something &lt;a href="http://spellcaster.com/tomkidd/For%20Sale/DrawingsforSale/Awful%20Itch.jpg"&gt;absolutely awful&lt;/a&gt; I've never had such need and I'd never recommend that to anyone.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-5647694955535695559?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/5647694955535695559/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=5647694955535695559' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/5647694955535695559'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/5647694955535695559'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/05/deferred-constraint-real-life-scenario.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-3669692156575867402</id><published>2007-04-15T22:40:00.000+03:00</published><updated>2007-04-15T23:01:41.093+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='statistics oracle'/><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;Statistics is power! ... And the goat...&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Hmmm, you say absolutely stupid title? OK let's see whether you think the same after you read all this stuff.&lt;br /&gt;&lt;br /&gt;No I'm not going to write about statistics on Oracle tables, although of course we must have stats on Oracle tables for CBO to operate as well as possible. I'm going to write a bit about a very old &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=332623&amp;tstart=0"&gt;problem&lt;/a&gt; that now is at least partially &lt;a href="http://forums.oracle.com/forums/ann.jspa?annID=435"&gt;resolved&lt;/a&gt;. And particularly - inablity to change e-mail in &lt;a href="http://forums.oracle.com"&gt;Oracle forums&lt;/a&gt;. In my &lt;a href="http://gplivna.blogspot.com/2007/01/five-million-and-counting-what_30.html"&gt;previous blog entry&lt;/a&gt; I expressed hope that sometime in the future I'd be able to write another entry about it. Now the time has come. To be precise it came already 3 weeks ago on March 25.&lt;br /&gt;&lt;br /&gt;And I was agreeably surprised that the time came so fast. According to &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=332623&amp;amp;start=68&amp;tstart=0"&gt;this thread&lt;/a&gt; the problem started at July 2002. Since then many people many times write about this problem in &lt;a href="http://forums.oracle.com/forums/forum.jspa?forumID=29"&gt;feedback forum&lt;/a&gt; but the best what we got were promises about the bright future. Just like Communism that according to &lt;a href="http://en.wikipedia.org/wiki/Nikita_Khrushchev"&gt;Khrushchev&lt;/a&gt; had to be built by 1980 but never started. And surprise, surprise! Just about &lt;em&gt;two months after&lt;/em&gt; I published my article summarizing some statistics and counting all the desires, complaints and statements about inability to change the e-mail in 500 most recent threads &lt;strong&gt;we got it&lt;/strong&gt;!&lt;br /&gt;&lt;br /&gt;You see - my ego is fantastically high! ;)&lt;br /&gt;&lt;br /&gt;OK I'll go down some steps.&lt;br /&gt;&lt;br /&gt;The most I'm dare to think of - is that my article was one of the drops that broke up the big rock. But of course important drop that probably showed people the real size of the problem.&lt;br /&gt;&lt;br /&gt;You see - my ego is fantastically high anyway even after stepping down! ;)&lt;br /&gt;&lt;br /&gt;So I personally learned at least one thing - statistics is power! Even outside CBO!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;And where's the goat you ask? &lt;/strong&gt;&lt;br /&gt;OK here is an old story (most probably already known to you in some variation):&lt;br /&gt;&lt;br /&gt;&lt;em&gt;A poor man comes to the rabbi complaining that his family has only one small room, many kids, and almost no money.&lt;br /&gt;The rabbi says, "Take all your money, buy a goat, and keep the goat in your room. Come back in a month."&lt;br /&gt;"But, rabbi, we don't have enough space even for us," the man said&lt;br /&gt;"Just do what I say," the rabbi replied.&lt;br /&gt;A month later the man comes back complaining that the goat smells and breaks everything.&lt;br /&gt;"Sell the goat and come back in a month," the rabbi tells him.&lt;br /&gt;A month later the man comes back to the rabbi with flowers.&lt;br /&gt;"Thank you, rabbi! We're so happy the goat is out, now we have more room and some money!"&lt;br /&gt;&lt;/em&gt;&lt;br /&gt;By objective considerations rabbi was a bit of cheater and poor man of course was stupid.&lt;br /&gt;&lt;br /&gt;So we had a goat in our room for more than four years - much longer than poor man. Of course after removing our own "goat" the feeling is quite releasing and pleasing but we have to understand that it was removing the goat instead of giving a present.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-3669692156575867402?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/3669692156575867402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=3669692156575867402' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/3669692156575867402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/3669692156575867402'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/04/statistics-is-power.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-117489715602544108</id><published>2007-03-26T12:18:00.000+03:00</published><updated>2007-03-26T15:07:50.233+03:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;Where bad performance starts&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;"My application is slow" - who haven't heard this very common complaint? Both from customers and developers (sic!) that created the application. No this won't be story how to diagnose what is slow and/or what to do to make it run faster. This will be a short story - how to try to not reach this complaint.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;So where are the roots of bad performance?&lt;/strong&gt; Many times the roots are very simple - allowing customer to promote and what's worse - accept bad requirements from customer. Bad and many times completely unnecessary requirements. The primary task of system analyst is of course to &lt;a href="http://en.wikipedia.org/wiki/Requirements_analysis"&gt;analyze, formalize, systematize and record customer requirements&lt;/a&gt;. But that should be done using sound criticism of initial requirements. And although the primary goal of specification is to record WHAT is needed and although specification should be implementation independent I'm sure that a really good system analyst has to keep in mind at least the vision HOW specified requirements will be implemented. Otherwise it is possible to result in a SRS describing &lt;em&gt;business illogic instead of business logic&lt;/em&gt; (as was quite precisely named by a user in &lt;a href="http://forums.oracle.com/forums/click.jspa?searchID=5657735&amp;messageID=1700300"&gt;this thread&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Why illogical and unnecessary requirements are bad and should be thrown away instead of just implementing them&lt;/strong&gt; - probably someone sometime would need them? There are at least following reasons to do that:&lt;br /&gt;1) starting from requirements gathering through development and design until the testing and deployment development staff is wasting their time to implement them resulting in wasted man-hours and $$$,&lt;br /&gt;2) every added functionality makes every application at least a little bit more harder to understand for customer and support which also results in wasted man-hours and $$$,&lt;br /&gt;3) every added functionality needs some system resources either in CPU cycles, I/O calls or increased memory space. Everybody knows that resources are finite and so they simply are stolen from other users and useful functionality,&lt;br /&gt;4) every added functionality usually takes some space on the screen. Of course it is not so critical today with common 17' and 19' monitors, but needless functionality many times can be as annoying as advertisements.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;What to do to eliminate unnecessary requirements&lt;/strong&gt;, if customer asks something crazy or you think that every other similar product already has it? There are at least following possibilities starting from the best:&lt;br /&gt;1) frankly tell the customer that the requirement is bad explaining why it should be eliminated and what bad will happen if it would be created. You can even a bit overstate that :) This to my mind is the best solution, because even if customer and/or somebody else would force to implement you this particular bad feature you'd later have a wonderful (of course it should be written on paper or in e-mail!) argument that you have already predicted that!&lt;br /&gt;2) use some scheme of prioritization, for example a nice one (just coincidence) called like very well known city - MoSCoW. I've never seen a project where all requirements REALLY are with the same priority. So mark the foolish requirements "could have", "won't have", "never have" (OK the latter is my own addition :). Thanks God even "could have" usually guarantees the "never have" because - how many software projects have you seen where the actual implementation is ahead of the schedule and budgeted expenses? :) So usually there is no time left for "could have's" that are ugly and undesirable from development perspective.&lt;br /&gt;3) cash more $$$ for the particular feature. This is the most risky solution, because if customer is spiteful you'd cash him 3 times more than normal and would not deliver a good functionality. I in the place of customer would be 3 times angrier. And most of them are.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;How to minimize the impact of the unnecessary requirement? &lt;/strong&gt;If you have to implement it, of course you have to waste your and your customer resources to implement and accept it. The only possibility to minimize the impact is to make it configurable so that after the day (or week or hour) of intensive annoyance customer is able to switch it off. Of course this is also a solution for a pure marketing driven feature, which is absolutely necessary to sell your product but absolutely needless and harmful in real production.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;What are examples of unnecessary functionality? &lt;/strong&gt;Although very common and accustomed functionality of forums the precise threads count, view count and count of found searches actually is nothing more than satisfying the curiosity. What you'd lose if you'd don't know that this particular &lt;a href="http://forums.oracle.com/forums/forum.jspa?forumID=61"&gt;Database-General Oracle forum&lt;/a&gt; wouldn't display that it has &lt;em&gt;Messages: 209,897 - Threads: 48,569 and searching for term Oracle it found 453 Messages&lt;/em&gt;?&lt;br /&gt;Or this &lt;a href="http://www.orafaq.com/forum/"&gt;Oracle FAQ forum for SQL &amp;amp; PL/SQL Newbies&lt;/a&gt; has &lt;em&gt;44090 messages and 11735 topics and here searching for Oracle you'd get 84 results&lt;/em&gt;? Of course I assume that they are not counting these statistical numbers each time the user requests the page, but eventually this requirement can be very disastrous if implemented without caution. I really don't care whether the forum has 209,897 or 185,786 messages, probably the only thing that I care is to see the comparable activity that can be very approximate to judge in which forum there is more probability to get answer. And what I do care the most is &lt;strong&gt;to get the forum page as fast as possible&lt;/strong&gt;. This doesn't mean I'm asking to remove this functionality. This means I'm explaining that for real work this functionality is not needed and if it takes significant additional time it is even harmful to my mind. The same can be said about returning the precise count of search results even if they are some quite big number. Do you really care whether your search resulted in 5000 or 5647 hits? I personally don't unless it is statistical report which is absolutely different subject than everyday search.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Another case study.&lt;/strong&gt; Another quite common incorrectly used potentially very offensive feature is to put wildcards '%' around the search word. As a result we get potential resource intensive and long lasting full scan of table instead of minimal index scan. Actually I think it is really rare occasions when customer really needs to search for something like %A%. What does %A% really mean? A found document where the only symbol left in person name is "A"? A completely absentminded customer only remembering that his product name contains symbol "A"? Both customer and developer will be desperate in this situation - customer because the application is slow, developer because customer constantly complains that application is slow.&lt;br /&gt;&lt;br /&gt;So as a result for the latest case study I thought of writing a basic article how to create indexes in Oracle and put it on my &lt;a href="http://www.gplivna.eu/papers/"&gt;website&lt;/a&gt; but after searching the web I abandoned my idea, because so much articles have already been created and I doubt that mine would be better than already existing :) So here is a very small test case how to effectively search using wildcards either in the end (using the most basic index) or in the start (using function based index) but of course not both. So be aware in the following example how both searches for DBA_DB% and %DB_LINKS uses index range scan. This example was included mostly because I haven't seen any website mentioning the possibility to search using wildcard in the beginning of the string (probably haven't searched long enough :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; create table src (txt varchar2(100) NOT NULL);&lt;br /&gt;Table created.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; insert into src select distinct object_name from dba_objects;&lt;br /&gt;22474 rows created.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; create unique index src_uk1 on src(txt);&lt;br /&gt;Index created.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; create unique index src_uk2 on src(reverse(txt));&lt;br /&gt;Index created.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; exec dbms_stats.gather_table_stats(user, 'src')&lt;br /&gt;PL/SQL procedure successfully completed.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; set autot on explain&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; select * from src where txt like 'DBA_DB%';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;TXT&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;DBA_DB_LINKS&lt;br /&gt;Execution Plan&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;---------------------------------------------------------- &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0 SELECT STATEMENT Optimizer=FIRST_ROWS (Cost=2 Card=1 Bytes=22)&lt;br /&gt;1 0 INDEX (RANGE SCAN) OF 'SRC_UK1' (UNIQUE) (Cost=2 Card=1 Bytes=22)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; select * from src where reverse(txt) like reverse('%DB_LINKS');&lt;br /&gt;TXT&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ORA_KGLR7_DB_LINKS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;DBA_DB_LINKS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ALL_DB_LINKS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;USER_DB_LINKS&lt;br /&gt;Execution Plan&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;---------------------------------------------------------- &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0 SELECT STATEMENT Optimizer=FIRST_ROWS (Cost=3 Card=1 Bytes=22)&lt;br /&gt;1 0 TABLE ACCESS (BY INDEX ROWID) OF 'SRC' (Cost=3 Card=1 Bytes=22)&lt;br /&gt;2 1 INDEX (RANGE SCAN) OF 'SRC_UK2' (UNIQUE) (Cost=2 Card=1)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;And here are many links mentioning how to create indexes in Oracle and what one or another access path means:&lt;br /&gt;&lt;br /&gt;Oracle® Database Concepts 10g Release 2 (10.2)&lt;br /&gt;Chapter 5 Schema Objects&lt;br /&gt;Overview of Indexes&lt;br /&gt;Overview of Index-Organized Tables&lt;br /&gt;Overview of Application Domain Indexes&lt;br /&gt;&lt;a href="http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14220/schema.htm#i5671"&gt;http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14220/schema.htm#i5671&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Oracle® Database Application Developer's Guide - Fundamentals 10g Release 2 (10.2)&lt;br /&gt;Chapter 5 Using Indexes in Application Development&lt;br /&gt;&lt;a href="http://download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14251/adfns_indexing.htm"&gt;http://download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14251/adfns_indexing.htm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Oracle® Database Performance Tuning Guide 10g Release 2 (10.2)&lt;br /&gt;Chapter 15 Using Indexes and Clusters&lt;br /&gt;&lt;a href="http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14211/data_acc.htm#i17778"&gt;http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14211/data_acc.htm#i17778&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Oracle® Database Concepts 10g Release 2 (10.2)&lt;br /&gt;Chapter 18 Partitioned Tables and IndexesT&lt;br /&gt;Overview of Partitioned Indexes&lt;br /&gt;&lt;a href="http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14220/partconc.htm#i461446"&gt;http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14220/partconc.htm#i461446&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When to Use an Index by Cary Millsap&lt;br /&gt;&lt;a href="http://www.hotsos.com/e-library/abstract.php?id=5"&gt;http://www.hotsos.com/e-library/abstract.php?id=5&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Indexing options available in Oracle by Brian Hengen&lt;br /&gt;&lt;a href="http://download-uk.oracle.com/oowsf2005/137wp.pdf"&gt;http://download-uk.oracle.com/oowsf2005/137wp.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Why isn't Oracle using my index ?! by Jonathan Lewis&lt;br /&gt;&lt;a href="http://www.jlcomp.demon.co.uk/12_using_index.doc"&gt;http://www.jlcomp.demon.co.uk/12_using_index.doc&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Index Internals by Julian Dyke&lt;br /&gt;&lt;a href="http://julian.dyke.users.btopenworld.com/com/Presentations/IndexInternals.ppt#28"&gt;http://julian.dyke.users.btopenworld.com/com/Presentations/IndexInternals.ppt#28&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Understanding Indexes By Tim Gorman&lt;br /&gt;&lt;a href="http://www.evdbt.com/2004_paper_549.doc"&gt;http://www.evdbt.com/2004_paper_549.doc&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Oracle B-Tree Index Internals: Rebuilding The Truth by Richard Foote&lt;br /&gt;&lt;a href="http://www.miracleas.dk/images/upload/Docs/Richard%20Foote.pdf"&gt;http://www.miracleas.dk/images/upload/Docs/Richard%20Foote.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Bitmap index Internals by Julian Dyke&lt;br /&gt;&lt;a href="http://julian.dyke.users.btopenworld.com/com/Presentations/BitmapIndexInternals.ppt"&gt;http://julian.dyke.users.btopenworld.com/com/Presentations/BitmapIndexInternals.ppt&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Understanding Bitmap indexes by Jonathan Lewis&lt;br /&gt;&lt;a href="http://www.jlcomp.demon.co.uk/03_bitmap_1.doc"&gt;http://www.jlcomp.demon.co.uk/03_bitmap_1.doc&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Bitmap Indexes 3 - Bitmap Join Indexes by Jonathan Lewis&lt;br /&gt;&lt;a href="http://www.jlcomp.demon.co.uk/07_bitmap_3.doc"&gt;http://www.jlcomp.demon.co.uk/07_bitmap_3.doc&lt;/a&gt; - &lt;em&gt;what are Bitmap Join Indexes and when these are useful.&lt;br /&gt;&lt;/em&gt;&lt;br /&gt;Operations of execution plans by Julian Dyke&lt;br /&gt;&lt;a href="http://julian.dyke.users.btopenworld.com/com/Optimisation/Operations/Operations.html"&gt;http://julian.dyke.users.btopenworld.com/com/Optimisation/Operations/Operations.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Is this an index I use ? by Jonathan Lewis&lt;br /&gt;&lt;a href="http://www.jlcomp.demon.co.uk/index_usage.html"&gt;http://www.jlcomp.demon.co.uk/index_usage.html&lt;/a&gt; - &lt;em&gt;how to find indexes that are not used. &lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Rebuilding indexes – why, when, how? by Jonathan Lewis&lt;br /&gt;&lt;a href="http://www.jlcomp.demon.co.uk/indexes.doc"&gt;http://www.jlcomp.demon.co.uk/indexes.doc&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;How high can you go ? by Jonathan Lewis&lt;br /&gt;&lt;a href="http://www.jlcomp.demon.co.uk/22_how_high.doc"&gt;http://www.jlcomp.demon.co.uk/22_how_high.doc&lt;/a&gt; - &lt;em&gt;what is the biggest possible height of a b-tree index?&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Expert Oracle Database Architecture 9i and 10g Programming by Thomas Kyte&lt;br /&gt;Chapter 11 Indexes&lt;br /&gt;&lt;a href="http://www.apress.com/ApressCorporate/supplement/1/10008/1590595300-2993.pdf"&gt;Table of contents&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.apress.com/book/bookDisplay.html?bID=10008"&gt;Book&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Cost-Based Oracle Fundamentals by Jonathan Lewis&lt;br /&gt;Chapter 4 Simple B-tree Access&lt;br /&gt;Chapter 8 Bitmap Indexes&lt;br /&gt;&lt;a href="http://www.apress.com/ApressCorporate/supplement/1/10081/1590596366-3079.pdf"&gt;Table of contents&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.apress.com/book/bookDisplay.html?bID=10081"&gt;Book&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-117489715602544108?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/117489715602544108/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=117489715602544108' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/117489715602544108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/117489715602544108'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/03/where-bad-performance-starts-my.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22727713.post-117019123586522360</id><published>2007-01-30T22:55:00.001+02:00</published><updated>2007-02-01T23:48:31.553+02:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:130%;"&gt;Five Million and Counting - WHAT???&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Recently I got one of the regular mails from Oracle (called OTN TechBlast). Title of the first article was "Five Million and Counting" and it was written by &lt;a href="http://blogs.oracle.com/otn/"&gt;Justin Kestelyn&lt;/a&gt;, Editor-in-Chief, OTN.&lt;br /&gt;So what is he counting? First paragraph answers that question:&lt;br /&gt;"I can hardly believe it, but OTN membership passed the 5-million benchmark in 2006. But why should you care?"&lt;br /&gt;&lt;br /&gt;What is so remarkable in this statement? Yes of course it is a big number. Yes of course it is nice that people around the world are interested in Oracle and its products. But the question remains - What the author is counting?&lt;br /&gt;&lt;br /&gt;And the question remains for the on big reason - OTN member cannot change his e-mail for already at least a few years (according to &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=332623&amp;start=68&amp;amp;tstart=0"&gt;this&lt;/a&gt; post since about July 2002). It is surprising in nowadays when&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;people change their works quite often and the right thing is not to work all the life in one company;&lt;/li&gt;&lt;li&gt;companies merge, crash, change names, domains;&lt;/li&gt;&lt;li&gt;free e-mail servers come and go.&lt;/li&gt;&lt;/ul&gt;One of the important parts of OTN is forums. Among other forums there exists one called &lt;a href="http://forums.oracle.com/forums/forum.jspa?forumID=29"&gt;Feedback&lt;/a&gt;. The goal of the forum is defined as follows: "Use this forum for feedback about OTN services and problems with OTN accounts.". Actually nothing is said that someone will solve your problem... Anyway people obviously are hoping for the best and continually posting their problems. As the &lt;a href="http://blogs.oracle.com/otn/"&gt;Justin Kestelyn&lt;/a&gt;, Editor-in-Chief, OTN hasn't gathered statistics of what the main problem for OTN members is (or at least hasn't indicated that in his article about 5 million members), I've tried to do this job myself.&lt;br /&gt;&lt;br /&gt;The source of statistics were 500 most recent threads starting from Mar 6, 2006 6:04 PM till Jan 30, 2007 ~20:00 PM.&lt;br /&gt;&lt;br /&gt;So 49 of 500 threads (or &lt;strong&gt;9.8%&lt;/strong&gt;) were only about this very problem asking how to change email, asking for possibility to do that or asking to delete old account because they've created new with lack of possibility to change email. When looking at such statistics like thread views and replies on threads the situation was even more dramatic:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;79632 out of 329834 views (&lt;strong&gt;24.1%&lt;/strong&gt;) were on above mentioned threads;&lt;/li&gt;&lt;li&gt;412 out of 1684 replies (including original posts) were to above mentioned threads.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So &lt;strong&gt;24.5% &lt;/strong&gt;or about &lt;strong&gt;one fourth&lt;/strong&gt; of all posted messages were about only one problem.&lt;/p&gt;&lt;p&gt;I can at least try to convert that to lost $$.&lt;/p&gt;&lt;p&gt;Assuming each view took 10 seconds (which is very very modest assumption due to fact that forum response times cannot be called very short :) employees of Oracle and its partners and clients have used 79632 views * 10 sec = 796320 person seconds = 13272 person minutes = 221 person hours = 28 person days = more than one person month to just watch threads about this particular topic. Of course that is not including&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;time to formulate and write responses including OTN members from Oracle;&lt;/li&gt;&lt;li&gt;people not knowing about such forums and trying to find out how to change their e-mails;&lt;/li&gt;&lt;li&gt;people wasting time for creating new accounts;&lt;/li&gt;&lt;li&gt;people wasting time for asking to delete old accounts because they have created new ones;&lt;/li&gt;&lt;li&gt;forums support group wasting time to delete old accounts;&lt;/li&gt;&lt;li&gt;time wasted by other Oracle employees according to &lt;a href="http://forums.oracle.com/forums/thread.jspa?messageID=1377645?"&gt;this&lt;/a&gt; message;&lt;/li&gt;&lt;li&gt;people getting angry and tearing their hairs wondering how such basic functionality cannot be included;&lt;/li&gt;&lt;li&gt;people loosing trust to Oracle seeing how their feedback is (not) being listened to;&lt;/li&gt;&lt;li&gt;6 hours of my time to gather above mentioned statistics and write these paragraphs :)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Yeahhh, as we can see even &lt;a href="http://www.oracle.com/technology/community/oracle_ace/index.html"&gt;Oracle ACEs&lt;/a&gt; are suffering from this forced duplication of individualities (see &lt;a href="http://forums.oracle.com/forums/profile.jspa?userID=16769"&gt;here&lt;/a&gt; and &lt;a href="http://forums.oracle.com/forums/profile.jspa?userID=399319"&gt;here&lt;/a&gt;) so what can we say?&lt;/p&gt;&lt;p&gt;Anyway I hope that I will waste another hour or so to write another article that this nightmare has been ended!&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;P.S. Here is the list of the above mentioned 49 of 500 threads speaking about the same problem along with thread views and replies (the first is one of the most famous in forum history :)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=332623&amp;tstart=0"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=332623&amp;amp;tstart=0&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 32374 260 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=466383&amp;tstart=0"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=466383&amp;amp;tstart=0&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 83 2 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=465156&amp;tstart=0"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=465156&amp;amp;tstart=0&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 129 2 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=315641&amp;tstart=0"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=315641&amp;amp;tstart=0&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 785 6 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=457141&amp;tstart=50"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=457141&amp;amp;tstart=50&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 489 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=455907&amp;tstart=50"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=455907&amp;amp;tstart=50&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 273 1 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=454522&amp;tstart=50"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=454522&amp;amp;tstart=50&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 257 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=449311&amp;tstart=50"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=449311&amp;amp;tstart=50&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 392 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=448357&amp;tstart=50"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=448357&amp;amp;tstart=50&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 406 2 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=296695&amp;tstart=100"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=296695&amp;amp;tstart=100&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1342 9 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=228506&amp;tstart=100"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=228506&amp;amp;tstart=100&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 4593 15 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=442434&amp;tstart=100"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=442434&amp;amp;tstart=100&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 418 2 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=438887&amp;tstart=150"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=438887&amp;amp;tstart=150&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 582 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=245541&amp;tstart=150"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=245541&amp;amp;tstart=150&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 981 3 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=435750&amp;tstart=150"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=435750&amp;amp;tstart=150&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 370 0 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=434911&amp;tstart=150"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=434911&amp;amp;tstart=150&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 348 0 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=433808&amp;tstart=150"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=433808&amp;amp;tstart=150&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 442 0 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=432352&amp;tstart=150"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=432352&amp;amp;tstart=150&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 620 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=426951&amp;tstart=150"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=426951&amp;amp;tstart=150&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 2033 5 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=421480&amp;tstart=200"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=421480&amp;amp;tstart=200&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1313 6 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=426240&amp;tstart=200"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=426240&amp;amp;tstart=200&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 2031 3 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=426944&amp;tstart=200"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=426944&amp;amp;tstart=200&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1622 3 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=427706&amp;tstart=200"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=427706&amp;amp;tstart=200&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 779 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=425728&amp;tstart=200"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=425728&amp;amp;tstart=200&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1218 2 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=425827&amp;tstart=200"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=425827&amp;amp;tstart=200&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1819 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=422451&amp;tstart=200"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=422451&amp;amp;tstart=200&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1843 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=414598&amp;tstart=250"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=414598&amp;amp;tstart=250&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1955 2 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=415593&amp;tstart=250"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=415593&amp;amp;tstart=250&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1173 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=410096&amp;tstart=300"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=410096&amp;amp;tstart=300&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1447 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=406747&amp;tstart=300"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=406747&amp;amp;tstart=300&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1442 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=404058&amp;tstart=300"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=404058&amp;amp;tstart=300&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1952 5 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=405247&amp;tstart=300"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=405247&amp;amp;tstart=300&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 659 2 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=405701&amp;tstart=300"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=405701&amp;amp;tstart=300&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1111 0 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=329360&amp;tstart=300"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=329360&amp;amp;tstart=300&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1860 4 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=241768&amp;tstart=300"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=241768&amp;amp;tstart=300&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1048 2 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=295366&amp;tstart=350"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=295366&amp;amp;tstart=350&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 1075 3 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=397480&amp;tstart=350"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=397480&amp;amp;tstart=350&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 572 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=389207&amp;tstart=350"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=389207&amp;amp;tstart=350&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 417 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=384777&amp;tstart=400"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=384777&amp;amp;tstart=400&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 395 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=385759&amp;tstart=400"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=385759&amp;amp;tstart=400&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 228 0 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=385698&amp;tstart=400"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=385698&amp;amp;tstart=400&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 810 0 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=384225&amp;tstart=400"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=384225&amp;amp;tstart=400&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 986 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=384041&amp;tstart=400"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=384041&amp;amp;tstart=400&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 718 0 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=376500&amp;tstart=450"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=376500&amp;amp;tstart=450&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 459 3 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=376822&amp;tstart=450"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=376822&amp;amp;tstart=450&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 819 3 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=375016&amp;tstart=450"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=375016&amp;amp;tstart=450&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 726 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=373244&amp;tstart=450"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=373244&amp;amp;tstart=450&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 789 1 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=372422&amp;tstart=450"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=372422&amp;amp;tstart=450&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 709 0 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=369961&amp;tstart=450"&gt;&lt;span style="font-size:85%;"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=369961&amp;amp;tstart=450&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; 740 1 &lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22727713-117019123586522360?l=gplivna.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gplivna.blogspot.com/feeds/117019123586522360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22727713&amp;postID=117019123586522360' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/117019123586522360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22727713/posts/default/117019123586522360'/><link rel='alternate' type='text/html' href='http://gplivna.blogspot.com/2007/01/five-million-and-counting-what_30.html' title=''/><author><name>Gints Plivna</name><uri>http://www.blogger.com/profile/17716037729002528529</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry></feed>
