MacLochlainns Weblog

Michael McLaughlin's Technical Blog

Site Admin

Archive for the ‘Oracle Development’ tag

Leaf node queries

without comments

A reader posted A dynamic level limiting hierarchical query about Oracle’s hierarchical queries. They wanted to know how to capture only the hierarchy above the level where the first leaf node occurs. They gave me the following hierarchy map as an example:

               1                                    2
        +-------------+                       +-----------+
        |             |                       |           |      
        3             5                       4           6
    +---------+    +-----------+           +-----+    +------+
    |         |    |           |           |     |    |      |
    7         9    11          13          8     10   12     14
+-----+   +-----+  +--+    +-------+                       +-----+ 
|     |   |     |     |    |       |                       |     |
15    17  19    21    23   27      29                     16     18
                                                                 +---+
                                                                     |
                                                                     20

You can find the node values and hierarchical level with the following query:

SELECT   tt.child_id
,        LEVEL
FROM     test_temp tt
WHERE    CONNECT_BY_ISLEAF  = 1
START
WITH     tt.parent_id IS NULL 
CONNECT
BY PRIOR tt.child_id = tt.parent_id
ORDER BY 2;

We really don’t need the node values to solve the problem. We only need the lowest LEVEL value returned by the query, which is 3. The combination of the MIN and CONNECT_BY_ISLEAF functions let us solve this problem without writing a PL/SQL solution. The subquery returns the lowest level value, which is the first level where a leaf node occurs.

SELECT   LPAD(' ', 2*(LEVEL - 1)) || tt.child_id AS child_id
FROM     test_temp tt
WHERE    LEVEL <= (SELECT   MIN(LEVEL)
                   FROM     test_temp tt
                   WHERE    CONNECT_BY_ISLEAF  = 1
                   START
                   WITH     tt.parent_id IS NULL 
                   CONNECT
                   BY PRIOR tt.child_id = tt.parent_id)
START
WITH     tt.parent_id IS NULL
CONNECT
BY PRIOR tt.child_id = tt.parent_id;

It returns:

               1                                    2
        +-------------+                       +-----------+
        |             |                       |           |      
        3             5                       4           6
    +---------+    +-----------+           +-----+    +------+
    |         |    |           |           |     |    |      |
    7         9    11          13          8     10   12     14

While I answered the question in a comment originally, it seemed an important trick that should be shared in its own post.

Written by maclochlainn

April 30th, 2015 at 4:31 pm

Wrapping SQL*Plus

without comments

One annoying thing from installing Oracle Database 11g on Fedora, was that the up arrows for command history didn’t work. I decided to fix that today after seeing Lutz Hartmann’s article on rlwrap. Unfortunately, the epel (Extra Packages for Enterprise Linux) package he recommended doesn’t run on Fedora 20. You can read my tale of woe, or skip to the .bashrc function that fixed it when I installed only rlwrap.

Attempting it on yum, gave me these errors:

# yum install http://www.mirrorservice.org/sites/dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
Loaded plugins: langpacks, refresh-packagekit
epel-release-6-8.noarch.rpm                                 |  14 kB  00:00     
Examining /var/tmp/yum-root-5CLTPa/epel-release-6-8.noarch.rpm: epel-release-6-8.noarch
Marking /var/tmp/yum-root-5CLTPa/epel-release-6-8.noarch.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package epel-release.noarch 0:6-8 will be installed
--> Processing Conflict: epel-release-6-8.noarch conflicts fedora-release
No package matched to upgrade: epel-release
--> Finished Dependency Resolution
Error: epel-release conflicts with fedora-release-20-3.noarch
 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles –nodigest

Poking around for an epel fix wasn’t successful, so I chose to install only the rlwrap package. Here’s that command and log file:

[root@localhost ~]# yum install rlwrap 
Loaded plugins: langpacks, protectbase, refresh-packagekit
0 packages excluded due to repository protections
Resolving Dependencies
--> Running transaction check
---> Package rlwrap.x86_64 0:0.41-1.fc20 will be installed
--> Finished Dependency Resolution
 
Dependencies Resolved
 
================================================================================
 Package         Arch            Version                 Repository        Size
================================================================================
Installing:
 rlwrap          x86_64          0.41-1.fc20             updates           95 k
 
Transaction Summary
================================================================================
Install  1 Package
 
Total download size: 95 k
Installed size: 204 k
Is this ok [y/d/N]: y
Downloading packages:
rlwrap-0.41-1.fc20.x86_64.rpm                               |  95 kB  00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
  Installing : rlwrap-0.41-1.fc20.x86_64                                    1/1 
  Verifying  : rlwrap-0.41-1.fc20.x86_64                                    1/1 
 
Installed:
  rlwrap.x86_64 0:0.41-1.fc20                                                   
Complete!

The next step was getting it to work. A sqlplus function wrapper inside the .bashrc file seemed the easiest. Here’s the code to the .bashrc file:

# .bashrc
 
# Source global definitions
if [ -f /etc/bashrc ]; then
	. /etc/bashrc
fi
 
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=
 
# User specific aliases and functions
. /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh
 
# Wrap sqlplus with rlwrap to edit prior lines.
sqlplus()
{
  if [ "$RLWRAP" = "0" ]; then
    sqlplus "$@"
  else
    rlwrap sqlplus "$@"
  fi
}
 
# Set vi as a command line editor.
set -o vi

As always, I hope this helps some folks.

Written by maclochlainn

August 20th, 2014 at 6:58 pm