f

(CIIE) Des responsables et entrepreneurs �trangers pr�sents � la CIIE font l'�loge de l'ouverture de la Chine et des opportunit�s qu'elle offre

Lors de l'Exposition internationale d'importation de la Chine (CIIE) de cette ann�e � Shanghai, Ghazaryan Koryun, conseiller commercial � l'Ambassade d'Arm�nie en Chine, a pr�sent� aux visiteurs, dans un chinois courant, les vins et fruits de grande...




f

L'arm�e chinoise effectue des patrouilles de pr�paration au combat � Huangyan Dao

L'arm�e chinoise a effectu� mercredi des patrouilles de pr�paration au combat dans les eaux territoriales et l'espace a�rien territorial de Huangyan Dao, �le chinoise en mer de Chine m�ridionale, ainsi que dans des zones avoisinantes. Le...




f

La modernisation chinoise favorise un nouveau mod�le de d�veloppement humain

Un rapport conjoint intitul� "Un nouveau mod�le pour le progr�s humain et son importance mondiale" a �t� publi� lors du Forum des m�dias et des groupes de r�flexion du Sud global qui s'est tenu lundi � Sao Paulo, au Br�sil. R�dig� par des groupes...




f

Airbus pr�voit une forte demande d'avions en Chine au cours des 20 prochaines ann�es

Airbus a pr�vu que la Chine aurait besoin de plus de 9.500 nouveaux avions de transport de passagers et d'avions cargos au cours des deux prochaines d�cennies, en raison de la forte croissance de la demande de transport a�rien et de fret. Selon...




f

Xi entame une tourn�e en Am�rique latine pour d�fendre la coop�ration et le multilat�ralisme

Le pr�sident chinois Xi Jinping entame mercredi une tourn�e en Am�rique latine, o� il assistera � la 31e r�union des dirigeants �conomiques de la Coop�ration �conomique pour l'Asie-Pacifique (APEC) � Lima, capitale du P�rou, et au 19e sommet du G20...




f

Chine : la puissance de l'aviation et de la d�fense de la partie continentale est une protection solide pour les compatriotes taiwanais

Une porte-parole de la partie continentale de la Chine a qualifi� les r�sultats et la puissance de la partie continentale dans les domaines de l'aviation, de l'a�rospatiale et de la d�fense nationale de protection "solide et immense" pour les...




f

La Chine adopte des politiques fiscales pour soutenir le march� de l'immobilier

La Chine a promulgu� mercredi des politiques fiscales pour soutenir le d�veloppement stable et sain du march� de l'immobilier. Le minist�re des Finances a d�clar� que le pays augmenterait les incitations en termes de taxe sur les actes pour...




f

Chine : les investissements ferroviaires en hausse de 10,9% au cours des dix premiers mois

La Chine a continu� � accro�tre ses investissements dans la construction ferroviaire depuis le d�but de cette ann�e, d'apr�s des donn�es publi�es mercredi par l'op�rateur ferroviaire du pays. Durant la p�riode janvier-octobre, les investissements...




f

La Chine et le Vietnam conviennent de renforcer leur coop�ration en mati�re de s�curit�

Chen Wenqing, haut responsable du Parti communiste chinois (PCC), a rencontr� Phan Dinh Trac, membre du Bureau politique et pr�sident de la Commission des affaires int�rieures du Comit� central du Parti communiste vietnamien (PCV), mardi � Beijing. ...




f

La Chine est pr�te � cr�er davantage d'opportunit�s pour les partenaires de l'Asie-Pacifique gr�ce au d�veloppement et � l'ouverture

La Chine est pr�te � profiter de la 31e r�union des dirigeants �conomiques de l'APEC pour cr�er davantage d'opportunit�s pour les partenaires de l'Asie-Pacifique avec un d�veloppement de haute qualit� et une ouverture de haut niveau, a d�clar�...




f

Guide To Installing Fedora Core 6 On HP Pavilion dv2000 Series Laptops

This guide provides installation and configuration instructions for installing Fedora Core 6 on HP Pavilion dv2000 series laptops.




f

Developing Rich EJB ClientsWith GlassFish

GlassFish provides features to make it easy to develop stand alone, Java Swing based EJB clients. In this article we explain how to take advantage of these features.




f

A Java Developer's Review of Fedora 8

The latest version of the Fedora Linux Distribution includes a completely open source Java compiler and JVM called IcedTea, in addition to several Java tools and libraries. We took Fedora 8's tools for a spin and reported our findings in this article.






f

It's Official - Blog Bloke has moved

Hi Blokesters. It's official now and InstaBloke has moved over to Blog Bloke dot com, so please make a note of it and update your bookmarks as well as the newsfeed. You should also check out my latest post explaining all of the gory details. It's a doozy.

See you there!




f

Blog News from Blog Bloke

Blogging News as it happens, updated 24/7



TechBLOKE: More Blog and Technology News...




More links: blog bloke, instabloke, blog, weblog, blogging, blog tools, blogtech, webtech, web 2.0, blog search, blog resources, diary, writing, write, computing, internet, computers and internet, technology, tech, software, hardware, search engine, google, music, audio, ipod, podcasting, podcast, video, media, business, marketing, daily fisk, political football, news, world news, us-news, in the news, news headlines, headline news, news and politics, politics, political, current events, current events, opinion, rant, ramblings, random thoughts, terror, terrorism, terrorist, london bombing, society, law, legal, dispute resolution, music, entertainment, fun, funny humor, humour, canada, canadian, canadian news, canadian-news, canada news, canada-news, canadian politics, canadian-politics




f

New Release - Land for Sale in Burton-on-Trent, Staffordshire

Pasture and Potential Investment land for sale. This attractive parcel of land totals over 62 acres and has the unique benefit of river frontage.




f

New Release - Land for Sale in Towcester, Northamptonshire

Around 15 acres of flat land for sale, the land is available as a whole or in lots and benefits from strong investment potential due to the proximity of nearby developments.




f

New Release - Land for Sale in Ilkeston, Derbyshire

The land forms an excellent block of highly productive arable land totalling over 15 acres. It is perfectly placed between Derby and Nottingham, with excellent transport links and just 3 miles from Ilkeston town centre.




f

New Release - Land for Sale in Melton Mowbray, Leicestershire

A well managed block of agricultural land for sale available freehold as a whole or in lots suitable for paddock conversion. The land benefits from extensive road frontage and superb track access.




f

New Release - Land for Sale in Solihull, Birmingham

A rare and desirable opportunity to purchase a block of strategic land just 8 miles from Birmingham City Centre. Totalling over 14 acres the land is available freehold as a whole or lots, with strong investment potential.




f

New Release - Land for Sale in Stokenchurch

An opportunity to buy land for sale in affluent Buckinghamshire with superb access next to land that has recently been reclassified and granted planning permission.The land is available freehold as a whole or in lots.




f

New Release - Land for Sale in Hemel Hempstead

Just two lots remaining at this land for sale just 24 miles from the City of London within the affluent county of Hertfordshire. This lush grazing land is available freehold and is suitable for paddock conversion.




f

New Release - Land for Sale in Buckinghamshire, Water End

Just one lot of lush grazing land for sale in Buckinghamshire, one of the most affluent counties in the UK. The land measures approx 2.5 acres and with superb access, would be ideal for paddock conversion.




f

In welke provincie wonen de beste fietsers?

De Nederlandse man rijdt gemiddeld 50,9 kilometer per keer als hij op zijn racefiets klimt. De Zeeuwen fietsen het snelst ...... Lees verder: In welke provincie wonen de beste fietsers?




f

Trekz Titanium maakt fietsen met muziek veilig

Veilig muziek luisteren op de fiets Het is een goedbewaard geheim dat wij ook met ons kaakbeen geluiden opvangen. De Aftershokz ...... Lees verder: Trekz Titanium maakt fietsen met muziek veilig






f

Bitemojo self-guided foodtours: een review

BARCELONA – Het is goed uitkijken in het drukke Barcelona. Bitemojo heeft wielrennen.blog.nl een self-guided food tour aangeboden die wij ...... Lees verder: Bitemojo self-guided foodtours: een review











f

Performance Counters in Delphi, sample project and article

Implementing performance monitors in your app is very helpful for profiling, debugging and general satisfaction of the more qualified endusers. It's also a non-trivial excercise, to put it mildly. Microsoft have done their part in making it obscure and hard to use, so naturally, we can't leave it alone, can we? This particular implementation only implements raw and delta counters, but that covers almost anything you'll ever need. The basis is there for other types of counters, though, such as instance based counters and high-precision. Both precompiled and full project source is available.




f

Forum RSS Feeds

I've added RSS Feeds to both my fora. These allow you to instantly see new posts in any public forum, including both subject and full body text. Things are only getting cooler.




f

ACM and IEEE/CS are good for you

Some months back I joined both ACM and IEEE Computer Society and I'm definitely a better human being now. Most won't notice, I guess. And you can take that any way you want to.




f

Hania is Famous at Last

Hania was interviewed for regional radio and ended up with a nice, cute story on their website.




f

RFE - source code now available

On request, I've posted the source code to the RSS Feed Editor.




f

Are older releases of the database really unsupported?

articles: 

I see posts on Oracle related forums about various releases (anything that isn't 11.x or 12.x) being "unsupported". This is wrong. Of course you should upgrade any 9i or 10g databases, but you don't have to.

Oracle Corporation's lifetime support policy is documented here,
Lifetime Support Policy
take a look, and you'll see that release 10.2 was in premier support until end July 2010 when it went into extended support. At end July 2013, it goes into sustaining support. Sustaining support will continue indefinitely. Even release 8.1.7 will have sustaining support indefinitely.
So what is sustaining support? That is documented here,
Lifetime support benefits
To summarize, extended support gives you everything you are likely to need. What you do not get is certification against new Oracle products or new third party products (principally, operating systems). But does that matter? I don't think so. For example, release 11.2.0.3 (still in premier support) is not certified against Windows 8, but it works fine.
Sustaining support has a more significant problem: no more patches. Not even patches for security holes, or changes in regulatory requirements. The security patch issue may of course be serious, but regulatory issues are unlikely to matter (this is a database, not a tax management system.) Think about it: 10g has been around for many years. It is pretty well de-bugged by now. If you hit a problem with no work around, you are pretty unlucky. Sustaining support gives you access to technical support, available patches, software, and documentation. That is all most sites will ever need.
Right now, I am working on a 9.2.0.8 database. It cannot be upgraded because the application software is written by a company that does not permit a database upgrade. Why not? Well, the reason may be commercial: they have a replacement product that is supported on newer databases. But that is nothing to do with me. The database works, the software works. Making it work better is a challenge - but that is what a DBA is paid to do. Don't just write it off as "unsupported".
Of course I am not suggesting that users should not upgrade to current releases - but upgrades are a huge project, and can have major implications. Running out dated software is silly, unless you have an irrefutable reason for so doing. The lack of security patches make you vulnerable to data loss. The lack of regulatory patches may make it illegal. The lack of newer facilities will be restricting the utility of the system. You may be losing money by not taking of advantage of changes of newer technology that can better exploit your hardware.
If anyone is looking for consulting support to upgrade their database - my boss will be happy to give you a quote. But I won't refuse to support you in the meantime.
--
John Watson
Oracle Certified Master DBA
http://skillbuilders.com




f

Finding gaps with analytic functions

articles: 

Finding gaps is classic problem in PL/SQL. The basic concept is that you have some sort of numbers (like these: 1, 2, 3, 5, 6, 8, 9, 10, 15, 20, 21, 22, 23, 25, 26), where there’s supposed to be a fixed interval between the entries, but some entries could be missing. The gaps problem involves identifying the ranges of missing values in the sequence. For these numbers, the solution will be as follows:
START_GAP END_GAP
4 4
7 7
11 14
16 19
24 24

First, run the following code, to create tab1 table:


CREATE TABLE tab1
(
col1 INTEGER
);

Then, insert a few rows:


INSERT INTO tab1 VALUES (1);
INSERT INTO tab1 VALUES (2);
INSERT INTO tab1 VALUES (3);
INSERT INTO tab1 VALUES (5);
INSERT INTO tab1 VALUES (6);
INSERT INTO tab1 VALUES (8);
INSERT INTO tab1 VALUES (9);
INSERT INTO tab1 VALUES (10);
INSERT INTO tab1 VALUES (15);
INSERT INTO tab1 VALUES (20);
INSERT INTO tab1 VALUES (21);
INSERT INTO tab1 VALUES (22);
INSERT INTO tab1 VALUES (23);
INSERT INTO tab1 VALUES (25);
INSERT INTO tab1 VALUES (26);

COMMIT;

With data, you can take care of solving the gaps problem…

One of the most efficient solutions to the gaps problem involves using analytic functions (also known as window functions)


WITH aa AS
(SELECT col1 AS cur_value, LEAD (col1) OVER (ORDER BY col1) AS next_value
FROM tab1)
SELECT cur_value + 1 AS start_gap, next_value - 1 AS end_gap
FROM aa
WHERE next_value - cur_value > 1
ORDER BY start_gap

Using the LEAD function, you can return for each current col1 value (call it cur_value) the next value in the sequence (call it next_value). Then you can filter only pairs where the difference between the two is greater than the one.




f

SQL*Plus error logging – New feature release 11.1

articles: 

One of the most important things that a developer does apart from just code development is, debugging. Isn’t it? Yes, debugging the code to fix the errors that are raised. But, in order to actually debug, we need to first capture them somewhere. As of now, any application has it’s own user defined error logging table(s).

Imagine, if the tool is rich enough to automatically capture the errors. It is very much possible now with the new SQL*PLus release 11.1

A lot of times developers complain that they do not have privilege to create tables and thus they cannot log the errors in a user defined error logging table. In such cases, it’s a really helpful feature, at least during the unit testing of the code.

I made a small demonstration in SCOTT schema using the default error log table SPERRORLOG, hope this step by step demo helps to understand easily :

NOTE : SQL*Plus error logging is set OFF by default. So, you need to “set errorlogging on” to use the SPERRORLOG table.

SP2 Error

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

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> desc sperrorlog;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------

 USERNAME                                           VARCHAR2(256)
 TIMESTAMP                                          TIMESTAMP(6)
 SCRIPT                                             VARCHAR2(1024)
 IDENTIFIER                                         VARCHAR2(256)
 MESSAGE                                            CLOB
 STATEMENT                                          CLOB

SQL> truncate table sperrorlog;

Table truncated.

SQL> set errorlogging on;
SQL> selct * from dual;
SP2-0734: unknown command beginning "selct * fr..." - rest of line ignored.
SQL> select timestamp, username, script, statement, message from sperrorlog;

TIMESTAMP
---------------------------------------------------------------------------
USERNAME
--------------------------------------------------------------------------------

SCRIPT
--------------------------------------------------------------------------------

STATEMENT
--------------------------------------------------------------------------------

MESSAGE
--------------------------------------------------------------------------------

11-SEP-13 01.27.29.000000 AM
SCOTT


TIMESTAMP
---------------------------------------------------------------------------
USERNAME
--------------------------------------------------------------------------------

SCRIPT
--------------------------------------------------------------------------------

STATEMENT
--------------------------------------------------------------------------------

MESSAGE
--------------------------------------------------------------------------------

selct * from dual;
SP2-0734: unknown command beginning "selct * fr..." - rest of line ignored.

ORA Error

SQL> truncate table sperrorlog;

Table truncated.

SQL> select * from dula;
select * from dula
              *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL> select timestamp, username, script, statement, message from sperrorlog;

TIMESTAMP
---------------------------------------------------------------------------
USERNAME
--------------------------------------------------------------------------------

SCRIPT
--------------------------------------------------------------------------------

STATEMENT
--------------------------------------------------------------------------------

MESSAGE
--------------------------------------------------------------------------------

11-SEP-13 01.36.08.000000 AM
SCOTT


TIMESTAMP
---------------------------------------------------------------------------
USERNAME
--------------------------------------------------------------------------------

SCRIPT
--------------------------------------------------------------------------------

STATEMENT
--------------------------------------------------------------------------------

MESSAGE
--------------------------------------------------------------------------------

select * from dula
ORA-00942: table or view does not exist

Like shown above, you can capture PLS errors too.

If you want to execute it through scripts, you can do it like this, and later spool the errors into a file. I kept these three lines in the sperrorlog_test.sql file -

truncate table sperrorlog;
selct * from dual;
select * from dula;

SQL> @D:sperrorlog_test.sql;

Table truncated.

SP2-0734: unknown command beginning "selct * fr..." - rest of line ignored.
select * from dula
              *
ERROR at line 1:
ORA-00942: table or view does not exist


SQL> select TIMESTAMP, SCRIPT, STATEMENT, MESSAGE from sperrorlog;

TIMESTAMP
---------------------------------------------------------------------------
SCRIPT
--------------------------------------------------------------------------------

STATEMENT
--------------------------------------------------------------------------------

MESSAGE
--------------------------------------------------------------------------------

11-SEP-13 01.50.17.000000 AM

D:sperrorlog_test.sql;
SP2-0734: unknown command beginning "D:sperror..." - rest of line ignored.


TIMESTAMP
---------------------------------------------------------------------------
SCRIPT
--------------------------------------------------------------------------------

STATEMENT
--------------------------------------------------------------------------------

MESSAGE
--------------------------------------------------------------------------------

11-SEP-13 01.50.27.000000 AM
D:sperrorlog_test.sql
selct * from dual;
SP2-0734: unknown command beginning "selct * fr..." - rest of line ignored.


TIMESTAMP
---------------------------------------------------------------------------
SCRIPT
--------------------------------------------------------------------------------

STATEMENT
--------------------------------------------------------------------------------

MESSAGE
--------------------------------------------------------------------------------

11-SEP-13 01.50.27.000000 AM
D:sperrorlog_test.sql
select * from dula
ORA-00942: table or view does not exist

SQL>

Check Oracle documentation on SPERRORLOG.

In addition to above, if you want to be particularly specific about each session’s error to be spooled into a file you could do this -

SQL> set errorlogging on identifier my_session_identifier

Above mentioned IDENTIFIER keyword becomes a column in SPERRORLOG table. It would get populated with the string value “my_session_identifier”. Now you just need to do this -
SQL> select timestamp, username, script, statement, message
2 from sperrorlog
3 where identifier = 'my_session_identifier';

To spool the session specific errors into a file, just do this -

SQL> spool error.log
SQL> select timestamp, username, script, statement, message
2 from sperrorlog
3 where identifier = 'my_session_identifier';
SQL> spool off




f

Recursive WITH, part III: IS_LEAF

articles: 

The CONNECT BY syntax provides a useful pseudocolumn, CONNECT_BY_ISLEAF, which identifies leaf nodes in the data: it’s 1 when a row has no further children, 0 otherwise. In this post, I’ll look at emulating this pseudocolumn using recursive WITH.

Let’s continue with the example from my previous posts about hierarchical data: the skeleton from the old song “Dem Dry Bones”.

UPDATE skeleton SET connected_to_the=NULL WHERE bone='head';
SELECT * FROM skeleton;

BONE                                     CONNECTED_TO_THE
---------------------------------------- ----------------------------------------
shoulder                                 neck
back                                     shoulder
hip                                      back
thigh                                    hip
knee                                     thigh
leg                                      knee
foot                                     heel
head
neck                                     head
toe                                      foot
arm                                      shoulder
wrist                                    arm
ankle                                    leg
heel                                     ankle
finger                                   wrist
a rib                                    back
b rib                                    back
c rib                                    back

With CONNECT BY, we can use the CONNECT_BY_ISLEAF pseudocolumn to identify leaf nodes:

SELECT bone, level, 
ltrim(sys_connect_by_path(bone,' -> '),' -> ') AS path
FROM skeleton
WHERE connect_by_isleaf=1
START WITH connected_to_the IS NULL
CONNECT BY prior bone=connected_to_the 
ORDER siblings BY 1;

BONE      LEVEL PATH                                                                                            
--------- ----- ----------------------------------------------------------------------------------------------- 
finger        6 head -> neck -> shoulder -> arm -> wrist -> finger                                              
a rib         5 head -> neck -> shoulder -> back -> a rib                                                       
b rib         5 head -> neck -> shoulder -> back -> b rib                                                       
c rib         5 head -> neck -> shoulder -> back -> c rib                                                       
toe          12 head -> neck -> shoulder -> back -> hip -> thigh -> knee -> leg -> ankle -> heel -> foot -> toe

This pseudocolumn takes a little more thought to replicate using recursive WITH than the LEVEL pseudocolumn and the SYS_CONNECT_BY_PATH, which, as we saw in my last post, fall naturally out of the recursion.

We can imitate CONNECT_BY_ISLEAF by searching DEPTH FIRST and using the LEAD function to peek at the next row’s the_level value. If the next row’s level is higher than the current row, then it’s a child of the current row; otherwise, it’s not a child. Since, with DEPTH FIRST, all the children of a row come out before any siblings, if the next row isn’t a child, then the current row is a leaf.

WITH skellarchy (bone, parent, the_level) AS
 ( SELECT bone, connected_to_the, 0  FROM skeleton 
   WHERE bone = 'head'                         
 UNION ALL
   SELECT s.bone, s.connected_to_the , r.the_level + 1
   FROM skeleton s, skellarchy r
   WHERE r.bone = s.connected_to_the           
 )
SEARCH DEPTH FIRST BY bone SET bone_order
CYCLE bone SET is_a_cycle TO 'Y' DEFAULT 'N'
SELECT lpad(' ',2*the_level, ' ') || bone AS bone_tree , the_level,
  lead(the_level) OVER (ORDER BY bone_order) AS next_level,
  CASE 
    WHEN the_level < lead(the_level) OVER (ORDER BY bone_order) THEN NULL
    ELSE 'LEAF'
  END is_leaf
FROM skellarchy
ORDER BY bone_order;

BONE_TREE                                      THE_LEVEL NEXT_LEVEL IS_L
--------------------------------------------- ---------- ---------- ----
head                                                   0          1
  neck                                                 1          2
    shoulder                                           2          3
      arm                                              3          4
        wrist                                          4          5
          finger                                       5          3 LEAF
      back                                             3          4
        a rib                                          4          4 LEAF
        b rib                                          4          4 LEAF
        c rib                                          4          4 LEAF
        hip                                            4          5
          thigh                                        5          6
            knee                                       6          7
              leg                                      7          8
                ankle                                  8          9
                  heel                                 9         10
                    foot                              10         11
                      toe                             11            LEAF

Watch out for Cycles

The first point of caution about this solution concerns cycles. In my last post, I had created a cycle by making the ‘head’ node’s parent the ‘toe’ node. If I’d left the cycle in the data, the toe node wouldn’t be a leaf any more, but this query would falsely identify the head as a leaf:

UPDATE skeleton SET connected_to_the='toe' WHERE bone='head';

BONE_TREE                                      THE_LEVEL NEXT_LEVEL IS_L
--------------------------------------------- ---------- ---------- ----
head                                                   0          1
  neck                                                 1          2
    shoulder                                           2          3
      arm                                              3          4
        wrist                                          4          5
          finger                                       5          3 LEAF
      back                                             3          4
        a rib                                          4          4 LEAF
        b rib                                          4          4 LEAF
        c rib                                          4          4 LEAF
        hip                                            4          5
          thigh                                        5          6
            knee                                       6          7
              leg                                      7          8
                ankle                                  8          9
                  heel                                 9         10
                    foot                              10         11
                      toe                             11         12
                        head                          12            LEAF
 
19 rows selected.

This can be corrected for by adding WHERE IS_A_CYCLE=’N’ to the query.

Respect the order of evaluation…

A second point of caution: if I add a WHERE clause to the query that limits the number of levels, the last line of the resultset will always be identified as a leaf.

WITH skellarchy (bone, parent, the_level) AS
 ( SELECT bone, connected_to_the, 0  FROM skeleton 
   WHERE bone = 'head'                         
 UNION ALL
   SELECT s.bone, s.connected_to_the , r.the_level + 1
   FROM skeleton s, skellarchy r
   WHERE r.bone = s.connected_to_the           
 )
SEARCH DEPTH FIRST BY bone SET bone_order
CYCLE bone SET is_a_cycle TO 'Y' DEFAULT 'N'
SELECT lpad(' ',2*the_level, ' ') || bone AS bone_tree , the_level,
  lead(the_level) OVER (ORDER BY bone_order) AS next_level,
  CASE 
    WHEN the_level < lead(the_level) OVER (ORDER BY bone_order) THEN NULL
    ELSE 'LEAF'
  END is_leaf
FROM skellarchy
WHERE the_level < 8 
ORDER BY bone_order;

BONE_TREE                                                     THE_LEVEL NEXT_LEVEL IS_L
------------------------------------------------------------ ---------- ---------- ----
head                                                                  0          1
  neck                                                                1          2
    shoulder                                                          2          3
      arm                                                             3          4
        wrist                                                         4          5
          finger                                                      5          3 LEAF
      back                                                            3          4
        a rib                                                         4          4 LEAF
        b rib                                                         4          4 LEAF
        c rib                                                         4          4 LEAF
        hip                                                           4          5
          thigh                                                       5          6
            knee                                                      6          7
              leg                                                     7            LEAF      <<<=====

The leg is falsely identified as a leaf, and NEXT_LEVEL comes out as NULL, even though the ‘leg’ row has a child row. Why is that? It’s because this solution uses the LEAD analytic function. With analytic functions, WHERE clauses are evaluated before the analytic functions.

Highlighting the relevant bits from the query:

WITH skellarchy AS ...[recursive WITH subquery]...
SELECT ... LEAD(the_level) OVER (ORDER BY bone_order) AS next_level ... --analytic function
FROM skellarchy
WHERE the_level < 8 ...                                                 --where clause

To quote the documentation:

Analytic functions compute an aggregate value based on a group of rows…. The group of rows is called a window and is defined by the analytic_clause. For each row, a sliding window of rows is defined. The window determines the range of rows used to perform the calculations for the current row…. Analytic functions are the last set of operations performed in a query except for the final ORDER BY clause. All joins and all WHERE, GROUP BY, and HAVING clauses are completed before the analytic functions are processed.

In the query above, “where the_level < 8" will be evaluated before LEAD(the_level). The EXPLAIN PLAN shows this very clearly:

-----------------------------------------------------------------------------------------------------
| Id  | Operation                                | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                         |          |     2 |    76 |     8  (25)| 00:00:01 |
|   1 |  WINDOW BUFFER                           |          |     2 |    76 |     8  (25)| 00:00:01 |  <<=== LEAD
|*  2 |   VIEW                                   |          |     2 |    76 |     8  (25)| 00:00:01 |  <<=== filter("THE_LEVEL"<8)
|   3 |    UNION ALL (RECURSIVE WITH) DEPTH FIRST|          |       |       |            |          |
|*  4 |     TABLE ACCESS FULL                    | SKELETON |     1 |    24 |     2   (0)| 00:00:01 |
|*  5 |     HASH JOIN                            |          |     1 |    49 |     5  (20)| 00:00:01 |
|   6 |      RECURSIVE WITH PUMP                 |          |       |       |            |          |
|   7 |      TABLE ACCESS FULL                   | SKELETON |    18 |   432 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - filter("THE_LEVEL"<8)
   4 - filter("BONE"='head')
   5 - access("R"."BONE"="S"."CONNECTED_TO_THE")

The WINDOW BUFFER (analytic window) is evaluated after the VIEW which filters on “THE_LEVEL”<8. So, "lead(the_level) over (order by bone_order)" will be null where the_level=7, and the 'leg' wrongly identified as a leaf node. What we actually want is for the analytic function LEAD to run over the whole resultset, and only then limit the results to show the levels 0-7. The obvious way to do this is to wrap the query in a second SELECT statement:

SELECT * FROM (
  WITH skellarchy (bone, parent, the_level) AS
   ( SELECT bone, connected_to_the, 0  FROM skeleton 
     WHERE bone = 'head'                         
   UNION ALL
     SELECT s.bone, s.connected_to_the , r.the_level + 1
     FROM skeleton s, skellarchy r
     WHERE r.bone = s.connected_to_the           
   )
  SEARCH DEPTH FIRST BY bone SET bone_order
  CYCLE bone SET is_a_cycle TO 'Y' DEFAULT 'N'
  SELECT lpad(' ',2*the_level, ' ') || bone AS bone_tree , the_level,
    lead(the_level) OVER (ORDER BY bone_order) AS next_level,
    CASE 
      WHEN the_level < lead(the_level) OVER (ORDER BY bone_order) THEN NULL
      ELSE 'LEAF'
    END is_leaf
  FROM skellarchy
  ORDER BY bone_order
) WHERE the_level < 8;

BONE_TREE                                                     THE_LEVEL NEXT_LEVEL IS_L
------------------------------------------------------------ ---------- ---------- ----
head                                                                  0          1
  neck                                                                1          2
    shoulder                                                          2          3
      arm                                                             3          4
        wrist                                                         4          5
          finger                                                      5          3 LEAF
      back                                                            3          4
        a rib                                                         4          4 LEAF
        b rib                                                         4          4 LEAF
        c rib                                                         4          4 LEAF
        hip                                                           4          5
          thigh                                                       5          6
            knee                                                      6          7
              leg                                                     7          8

Now, the analytic function in the inner query is evaluated first, before the WHERE clause in the outer query. We can see this in the EXPLAIN PLAN too, of course. Now the WINDOW BUFFER (analytic window) is evaluated before the VIEW with filter(“THE_LEVEL”<8) :

------------------------------------------------------------------------------------------------------
| Id  | Operation                                 | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                          |          |     2 |  4068 |     8  (25)| 00:00:01 |
|*  1 |  VIEW                                     |          |     2 |  4068 |     8  (25)| 00:00:01 |  <<=== filter("THE_LEVEL"<8)
|   2 |   WINDOW BUFFER                           |          |     2 |    76 |     8  (25)| 00:00:01 |  <<=== LEAD
|   3 |    VIEW                                   |          |     2 |    76 |     8  (25)| 00:00:01 |
|   4 |     UNION ALL (RECURSIVE WITH) DEPTH FIRST|          |       |       |            |          |
|*  5 |      TABLE ACCESS FULL                    | SKELETON |     1 |    24 |     2   (0)| 00:00:01 |
|*  6 |      HASH JOIN                            |          |     1 |    49 |     5  (20)| 00:00:01 |
|   7 |       RECURSIVE WITH PUMP                 |          |       |       |            |          |
|   8 |       TABLE ACCESS FULL                   | SKELETON |    18 |   432 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("THE_LEVEL"<8)
   5 - filter("BONE"='head')
   6 - access("R"."BONE"="S"."CONNECTED_TO_THE")

This is one case of the general point that, as Tom Kyte explains in this Ask Tom answer,“select analytic_function from t where CONDITION” is NOT THE SAME AS “select * from (select analytic_function from t) where CONDITION”.

So, to sum up my last few posts, we can do everything that CONNECT BY can do with the 11g recursive WITH syntax. Plus, the recursive WITH syntax makes it easy to express simple recursive algorithms in SQL.


Republished with permission. Original URL: http://rdbms-insight.com/wp/?p=135




f

NIP Friday #15 ...


This week’s photo's are an extension of the last installment of Nude In Public Friday. They were taken on the same day, just a little farther down the road.
I'll leave the possible captions for the pictures up to you... hee hee!

I've received a lot of email in response to my "Pop Machine" photo from a few weeks ago.



I would say that it was the most popular Nude In Public Friday so far! For those who have asked, yes, there are more hotel pictures and I'll be sharing them over the next few weeks.






f

NIP Friday #16 ...

Well, it's the end of the week and time again for Nude In Public Friday.
This weeks picture was taken during an evening of flashing a little over a year ago in Denver's North Cherry Creek area.

I think most women, at one time or another, have either performed a quick boob flash in an elevator or have at least been tempted to. I mean it's exciting.There you are in public and all of a sudden you have few moments of privacy to go a little crazy. Add to this the excitement of the possibility of being caught should the elevator doors open, and you can really see why elevators play into so many fantasies .

I've had my share of experiences in elevators and it would be fair to say that I've went down more often than I've gone up in them.





f

NIP Friday #17 ...

I picked this week’s picture for Nude In Public Friday for one reason... it reminded me of the warm summer evening that it was taken. Why do I find this so appealing you may ask? Four inches of fucking snow on May 1st, that's the reason! I awoke yesterday to the snow. I had to drive to a meeting in Castle Rock in it and got stuck in an hour long jam on the way back... Colorado weather, you've got to love it.


If my memory doesn't fail me, this picture was taken last summer on our way to dinner up in Longmont. It was warm, I was horny and I thought that I would show some boobage. I certainly didn't feel that way yesterday.





f

NIP Friday #18 ...

This is the 18th installment of Nude In Public Friday and I've received a lot of positive feedback so far. Out of the previous 17 NIP posts, the two most popular seem to have been the hotel pop machine and elevator pictures.


I suspect that there's some kind of freudian correlation between my tits and the machines going on here, all I know is that I've received more email from those two posts, than all the rest combined.

Most of them wanted to know if I had more of these photo's and would I post them. In an attempt to fulfill these requests, I'll be posting a few more from those two occasions over the next couple of weeks.