BC remote Oracle DBA - Call (800) 766-1884  
Oracle Consulting Oracle Training Development

Remote DBA

Remote DBA Plans  

Remote DBA Service

Remote DBA RAC

   
Remote DBA Oracle Home
Remote DBA Oracle Training
Remote DBA SQL Tuning Consulting
Remote DBA Oracle Tuning Consulting
Remote DBA Data Warehouse Consulting
Remote DBA Oracle Project Management
Remote DBA Oracle Security Assessment
Remote DBA Unix Consulting
Burleson Books
Burleson Articles
Burleson Web Courses
Burleson Qualifications
Oracle Links
Remote DBA Oracle Monitoring
Remote DBA Support Benefits
Remote DBA Plans & Prices
Our Automation Strategy
What We Monitor
Oracle Apps Support
Print Our Brochure
Contact Us (e-mail)
Oracle Job Opportunities
Oracle Consulting Prices





   

 

 

 

Remote DBA services

Remote DBA Support

Remote DBA RAC

Remote DBA Reasons

Remote Oracle Tuning

Remote DBA Links

Oracle DBA Support

Oracle DBA Forum

Oracle Disaster

Oracle Training

Oracle Tuning

Oracle Training

 Remote DBA SQL Server

Remote MSSQL Consulting

Oracle DBA Hosting

Oracle License Negotiation

 

 


 

 

 

 

 

 

 

Advanced Oracle SQL: Using Multiple Expressions

Oracle Tips by Laurent Schneider

Laurent Schneider is considered one of the top Oracle SQL experts, and he is the author of the book "Advanced Oracle SQL Programming" by Rampant TechPress.  The following is an excerpt from the book.

1.      Compounded expression

An expression can be composed of multiple expressions. The operators available in Oracle are addition, subtraction, multiplication, division and concatenation.

The string concatenation operator is formed by two pipe symbols:

SELECT
   'X'||'Y'
FROM
   DUAL;
'X
--
XY 

Or:

SELECT
   CONCAT('X','Y')
FROM
   DUAL;
CO
--
XY

The internal string concatenation operator's equivalent function is CONCAT.

The numerical operators are +, -, * and /: 

SELECT
   1+1,
   3-2,
   5*5,
   10/4
FROM
   DUAL;
 
       1+1        3-2        5*5       10/4
---------- ---------- ---------- ----------
         2          1         25        2.5

Those operators can be used with date and time expressions:

SELECT
   DATE '1582-10-15' – DATE '1582-10-04'
FROM
   DUAL;
DATE'1582-10-15'-DATE'1582-10-04'
---------------------------------
                                1

The difference in days between the last day of the Julian calendar to the first day of the Gregorian calendar:

SELECT
   DATE '2000-02-29' + INTERVAL '1' MONTH
FROM
   DUAL;
DATE'2000-02-29'+IN
-------------------
29.03.2000 00:00:00

One month after February 29th, 2000:

SELECT
   2*INTERVAL '7' MONTH,
   INTERVAL '1' / 7
FROM
   DUAL;
2*INTERVAL'7'MONTH INTERVAL'1'DAY/7
------------------ ------------------------------
+000000001-02      +000000000 03:25:42.857142857

Two periods of seven months is 1 year + 2 months. A seventh of a day is close to 3 hours and 26 minutes.

2.      NULL

NULL is a special expression that represents the absence of a value:

SELECT
   TO_DATE(NULL),
   TO_CHAR(NULL),
   TO_NUMBER(NULL)
FROM
   DUAL;
TO_DATE(NULL) TO_CHAR(NULL) TO_NUMBER(NULL)
------------- ------------- ---------------
<NULL>        <NULL>        <NULL>

To display nulls as something more visible than an empty string in SQL*Plus, it is possible to set it to a specific string like '<NULL>':

SET NULL "<NULL>"

Null has no type in itself; it has also no length and no value. When comparing NULL with NULL, the result is NULL.

BEGIN
   IF (NULL=NULL) IS NULL
   THEN
      DBMS_OUTPUT.PUT_LINE('(NULL=NULL) IS NULL');
   END IF;
   IF (NULL!=NULL) IS NULL
   THEN
      DBMS_OUTPUT.PUT_LINE('(NULL!=NULL) IS NULL');
   END IF;
   IF (NULL OR FALSE) IS NULL
   THEN
      DBMS_OUTPUT.PUT_LINE('(NULL OR FALSE) IS NULL');
   END IF;
   IF (NULL OR TRUE)=TRUE
   THEN
      DBMS_OUTPUT.PUT_LINE('(NULL OR TRUE) IS TRUE');
   END IF;
   IF (NULL AND TRUE) IS NULL
   THEN
      DBMS_OUTPUT.PUT_LINE('(NULL AND TRUE) IS NULL');
   END IF;
   IF (NULL AND FALSE)=FALSE
   THEN
      DBMS_OUTPUT.PUT_LINE('(NULL AND FALSE) IS FALSE');
   END IF;
   IF (NOT(NULL)) IS NULL
   THEN
      DBMS_OUTPUT.PUT_LINE('(NOT(NULL)) IS NULL');
   END IF;
END;
/
(NULL=NULL) IS NULL
(NULL!=NULL) IS NULL
(NULL OR FALSE) IS NULL
(NULL OR TRUE) IS TRUE
(NULL AND TRUE) IS NULL
(NULL AND FALSE) IS FALSE
(NOT(NULL)) IS NULL

The logical operations with NULL are printed out.

3.      Pseudo column

A pseudo column is an expression that has a special meaning in Oracle but is neither a function nor a literal or a column:

SELECT
   ROWNUM,
   DNAME
FROM
   DEPT
    ROWNUM DNAME
---------- --------------
         1 ACCOUNTING
         2 RESEARCH
         3 SALES
         4 OPERATIONS

ROWNUM is probably the most common pseudo column. It is used to enumerate the rows.

A common usage of ROWNUM is to select a limited number of rows:

SELECT
   ENAME,
   SAL
FROM
   (
      SELECT
         *
      FROM
         EMP
      ORDER BY SAL DESC
   )
WHERE
   ROWNUM<=5;
 

ENAME             SAL
---------- ----------
KING             5000
SCOTT            3000
FORD             3000
JONES            2975
BLAKE            2850

--------------------------------------------------------------------------------
| Id  | Operation               | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |      |     5 |   100 |     3  (34)| 00:00:01 |
|*  1 |  COUNT STOPKEY          |      |       |       |            |          |
|   2 |   VIEW                  |      |    14 |   280 |     3  (34)| 00:00:01 |
|*  3 |    SORT ORDER BY STOPKEY|      |    14 |   518 |     3  (34)| 00:00:01 |
|   4 |     TABLE ACCESS FULL   | EMP  |    14 |   518 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------------

   1 - filter(ROWNUM<=5)
 
   3 - filter(ROWNUM<=5) 

The top 5 rows are returned:

SELECT
   ENAME,
   SAL
FROM
   (
      SELECT
         E.*,
         ROWNUM R
      FROM
         (
            SELECT
               *
            FROM
               EMP
            ORDER BY
               SAL DESC
         ) E
      WHERE ROWNUM<=10
   )
WHERE
   R>5;

ENAME             SAL
---------- ----------
CLARK            2450
ALLEN            1600
TURNER           1500
MILLER           1300
WARD             1250

---------------------------------------------------------------------------------
| Id  | Operation                | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |      |    10 |   330 |     3  (34)| 00:00:01 |
|*  1 |  VIEW                    |      |    10 |   330 |     3  (34)| 00:00:01 |
|*  2 |   COUNT STOPKEY          |      |       |       |            |          |
|   3 |    VIEW                  |      |    14 |   280 |     3  (34)| 00:00:01 |
|*  4 |     SORT ORDER BY STOPKEY|      |    14 |   518 |     3  (34)| 00:00:01 |
|   5 |      TABLE ACCESS FULL   | EMP  |    14 |   518 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------------

   1 - filter("R">5)
   2 - filter(ROWNUM<=10)
   4 - filter(ROWNUM<=10)

Note: WHERE ROWNUM>1 is always false, because ROWNUM is evaluated after the WHERE condition, but before GROUP BY, HAVING and ORDER BY. It is incremented only for returned rows, so if ROWNUM 1 is not returned, no rows are returned.

The rows 6 to 10 are returned.

ROWID is useful when accessing a single row of a table:

SELECT
   *
FROM
   EMP
WHERE
   ROWID
IN
(
   SELECT
      ROWID
   FROM
      (
         SELECT
            ROWID
         FROM
            EMP
         ORDER BY
            EMPNO
      )
   WHERE
      ROWNUM=1
);
 

EMPNO ENAME      JOB         MGR HIREDATE    SAL  COMM DEPTNO
----- ---------- --------- ----- --------- ----- ----- ------
 7369 SMITH      CLERK      7902 17-DEC-80  1300           20

----------------------------------------------------------------------------------------
| Id  | Operation                   | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |          |     1 |    49 |     3  (34)| 00:00:01 |
|   1 |  NESTED LOOPS               |          |     1 |    49 |     3  (34)| 00:00:01 |
|   2 |   VIEW                      | VW_NSO_1 |     1 |    12 |     1   (0)| 00:00:01 |
|   3 |    HASH UNIQUE              |          |     1 |    12 |            |          |
|*  4 |     COUNT STOPKEY           |          |       |       |            |          |
|   5 |      VIEW                   |          |     1 |    12 |     1   (0)| 00:00:01 |
|   6 |       INDEX FULL SCAN       | PK_EMP   |     1 |    16 |     1   (0)| 00:00:01 |
|   7 |   TABLE ACCESS BY USER ROWID| EMP      |     1 |    37 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------

   4 - filter(ROWNUM=1)

The primary key index returns ROWID. The first entry is selected to access the table.  Note the operation TABLE ACCESS BY USER ROWID.

Compare with:

SELECT
   *
FROM
(
   SELECT
      *
   FROM
      EMP
   ORDER BY
      EMPNO
)
WHERE
   ROWNUM=1;
 

EMPNO ENAME      JOB         MGR HIREDATE    SAL  COMM DEPTNO
----- ---------- --------- ----- --------- ----- ----- ------
 7369 SMITH      CLERK      7902 17-DEC-80  1300           20

----------------------------------------------------------------------------------------
| Id  | Operation                     | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |        |     1 |    87 |     2   (0)| 00:00:01 |
|*  1 |  COUNT STOPKEY                |        |       |       |            |          |
|   2 |   VIEW                        |        |     1 |    87 |     2   (0)| 00:00:01 |
|   3 |    TABLE ACCESS BY INDEX ROWID| EMP    |    14 |   518 |     2   (0)| 00:00:01 |
|   4 |     INDEX FULL SCAN           | PK_EMP |     1 |       |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------

   1 - filter(ROWNUM=1)

The second query may be less efficient, depending on the size of the table and the size of the index because the STOPKEY operation is executed after the table access.

ROWID is often used by the database administrator to identify the block or the datafile where a row is physically stored; for example, in case of a block corruption. The package DBMS_ROWID contains some useful conversion functions.


Expert Remote DBA

BC is America's oldest and largest Remote DBA Oracle support provider.  Get real Remote DBA experts, call
BC Remote DBA today.

 

 

Remote DBA Service
 

Oracle Tuning Book

 

Advance SQL Tuning Book 

BC Oracle support

Oracle books by Rampant

Oracle monitoring software

 

 

 

 

 

 

BC Remote Oracle Support

Remote DBA

Remote DBA Services

Copyright © 1996 -  2013 by Burleson. All rights reserved.

Oracle® is the registered trademark of Oracle Corporation.



Hit Counter