Job Seekers   Employers
dbapool: Authors | Submissions | Contact Us
   Forgot password? | Sign up
  Home   Discussion Forum   Articles   Interview Questions   FAQs   Scripts   Rewards   Analyzer   White Papers   Blog   Certification   Downloads   Tools
   
ANSI ISO SQL1999




By menon srivalsala kumar
Aug 03, 2009

Digg! digg!     Print    email to friend Email to Friend

Note: This article was written for educational purpose only. Please refer to the related vendor documentation for detail.




1.                Introduction

 

Running sqls on  various database and Standardizing the sql’s will be the best option in Development of Application. We can make the sql’s are standardizes using ANSI/ISO SQL:1999:

 

The various sql’s joins available herein below:

 

    1. SQL:1999 joins

    2. CASE expressions

    3. Explicit defaults

    4. WITH clause

 

 

1. SQL:1999 Joins

 

SQL:1999 join syntax differs from traditional Oracle join syntax in that the join type is specified explicitly in the FROM clause.

 

Oracle9i onwards the following SQL:1999-compliant joins are available:

 

    1.1 NATURAL Join

    1.2 CROSS Join

    1.3 OUTER Join

    1.3.1 LEFT OUTER Join

    1.3.2 RIGHT OUTER Join

    1.3.3 FULL OUTER Join

 

 

 

 1.1 NATURAL Join

 

A NATURAL join selects rows from the tables which have equal values in all matched columns(same column names). If the columns having the same names have different datatypes, an error is returned.

 

If SELECT * syntax is used, the common columns appear only once in the result set.

 

Qualifiers such as table names or aliases may not be used for those columns involved in the natural join.

 

Example:

 

    For this example, assume tables empand departments have one common

 

    column, department_id.

 

    SELECT employee_id, last_name, department_id   FROM emp

    NATURAL JOIN departments;

 

This is equivalent to the following:

 

    SELECT employee_id, last_name, departments.department_id

    FROM employees, departments

    WHERE employees.department_id = departments.department_id;

 

If several columns have the same names but all of the datatypes do not match,  then the NATURAL JOIN can be modified to a join with a USING clause which  specifies which columns should be used for the equi-join.

 

The columns in the USING clause should also not have a qualifier (table name or alias) anywhere in the SQL statement.

 

The key words NATURAL and USING are mutually exclusive.

 

Example:

 

Assume tables empand job_history have two columns in common,  employee_id and department_id. The following query joins the two tables  together using only the employee_id as a join condition.

 

    SELECT employee_id, last_name, job_history.department_id

    FROM emp

    JOIN job_history

    USING (employee_id);

 

This is equivalent to the following:

 

    SELECT employees.employee_id, last_name, job_history.department_id

    FROM employees, job_history

    WHERE employees.employee_id=job_history.employee_id;

 

To specify arbitrary conditions or specify columns to be used in the join, the  ON clause is used. This also separates the join condition from other conditions. It can also be used to specify a join for which the columns have different  names. Another use for the ON clause is simply to make the SQL easier to read 

and understand by explicitly stating the join condition.

 

Examples:

    The following is equivalent to the example above for the USING clause.

 

    SELECT employees.employee_id, last_name, job_history.department_id

    FROM emp

    JOIN job_history

    ON (employees.employee_id=job_history.employee_id);

 

This example adds an additional where clause to the query:

 

    SELECT employees.employee_id, last_name, job_history.department_id

    FROM emp

    JOIN job_history

    ON (employees.employee_id=job_history.employee_id)

    WHERE mgrid=3;

 

The following illustrates a self-join of the emptable to itself based on the employee_id and manager_id columns:

 

    SELECT e.last_name employee, m.last_name manager

    FROM empe

    JOIN empm

    ON (e.manager_id=m.employee_id);

 

       1.1 CROSS Join

       A CROSS join is the cross-product of two tables. It is the equivalent of a Cartesian product.

                     Example:

     SELECT last_name, department_name

    FROM   emp

    CROSS JOIN departments;

  This is equivalent to the following:

     SELECT last_name, department_name  FROM employees, departments;

 

 1.3 OUTER Join

The join of two tables returning only matched rows is considered an INNER JOIN.

 

A join between two tables which returns the result of the INNER join as well as unmatched rows from the LEFT(or RIGHT) table is a LEFT(or RIGHT) OUTER join.

 

INNER and OUTER JOINS were available in prior relaeses. The '(+)' symbol was used on one of the tables to create outer joins. 

  

1.3.1 LEFT OUTER Join

A join between two tables which returns the result of the INNER join as well as unmatched rows from the LEFT table is a LEFT OUTER join.

 

Example:

    This query returns rows from the departments table even if no empare  assigned to it.

 

    SELECT employee_id, department_name

    FROM departments d

    LEFT OUTER JOIN empe

    ON (e.department_id= d.department_id);

 

This is equivalent to the following pre-Oracle9i outer join notation:

 

    SELECT employee_id, department_name

    FROM departments d, empe

    WHERE e.department_id(+) = d.department_id;

 

 

1.3.2 RIGHT OUTER Join

 

A join between two tables which returns the result of the INNER join as well as unmatched rows from the RIGHT table is a RIGHT OUTER join.

 

     Example:

     This query returns rows from the customers table even if this customer has  not placed any orders.

 

    SELECT cust_last_name, order_id,order_date

    FROM orders o

    RIGHT OUTER JOIN customers c

    ON (o.customer_id = c.customer_id);

 

     This is equivalent to the following pre-Oracle9i outer join notation:

 

    SELECT cust_last_name, order_id, order_date

    FROM orders o, customers c

    WHERE c.customer_id = o.customer_id(+);

 

 

1.3.3 FULL OUTER Join

 

A join between two tables which returns the result of the INNER join as well as unmatched rows from the LEFT and RIGHT outer joins is a FULL OUTER join. This  is a new type of join in Oracle9i which did not exist previously.

 

              Example:

 

This query returns locations which have no corresponding country and  countries which have no locations assigned.

 

    SELECT l.city, c.country_name

    FROM locations l

    FULL OUTER JOIN countries c

    ON (l.country_id = c.country_id);

 

This could have been accomplished in earlier versions using a UNION:

 

    SELECT l.city, c.country_name

    FROM locations l, countries c

    WHERE l.country_id = c.country_id(+)

    UNION

    SELECT l.city, c.country_name

    FROM locations l, countries c

    WHERE l.country_id(+) = c.country_id;

 

 

Restrictions

 

Use of these new joins is allowed in the definition of materialized views. However, query rewrite is only possible if the query could also be expressed using traditional Oracle syntax. The same restrictions apply when determining whether the materialized view can be fast refreshed.

 

For example, the following materialized view can make use of query rewrite:

 

    CREATE MATERIALIZED VIEW mv1 AS

    SELECT employee_id, department_name

    FROM departments d

    LEFT OUTER JOIN empe

    ON (e.department_id= d.department_id);

 

But, this query cannot use query rewrite because the use of subqueries was not permitted with outer joins:

 

    CREATE MATERIALIZED VIEW mv2 AS

    SELECT employee_id, department_name

    FROM departments d

    LEFT OUTER JOIN empe

    ON (e.department_id= d.department_id)

    WHERE e.department_id > 10;

 

The columns that are referenced in the USING or ON clause cannot be a  collection or LOB type.

 

 

2. CASE statements

 

There are 4 types of CASE logic available in SQL:1999:

 

    2.1 Simple CASE

    2.2 Searched CASE

    2.3 NULLIF

    2.4 COALESCE

 

 

2.1 Simple CASE

 

The simple CASE is similar to DECODE. It was available in Oracle 8.1.7. It can  be used to search and replace values within a given expression. You can specify a return value for each searched value. No comparison operators can be used in  the simple CASE.

 

Example:

 

    Assume the emptable has a salgrade column.

 

    SELECT employee_id,

    CASE salgrade WHEN 'A' THEN 'Low'

    WHEN 'B' THEN 'Medium'

    WHEN 'C' THEN 'High' END "Salary Grade"

    FROM employees;

 

It is also possible to have an ELSE clause for a default.

 

The above query is equivalent to the following with DECODE:

 

    SELECT employee_id,

    DECODE(salgrade,'A','Low','B','Medium','C','High')

    FROM employees;

 

 

2.2 Searched CASE

 

The searched CASE is similar to IF..THEN..ELSE. Searched CASE was available  beginning in version 8.1.6.

 

Each WHEN clause can be different and logical operators can be used to combine  multiple conditions. Comparison operators are also allowed.

 

Example:

 

    SELECT employee_id,

    CASE

    WHEN salary >=75000 THEN 'High'

    WHEN salary <=30000 THEN 'Low'

    ELSE 'Medium'

    END "Salary"

    FROM employees;

 

 

2.3 NULLIF

 

NULLIF returns NULL if the first argument is equal to the second. Otherwise,  the first value of the first argument is returned.

 

Example:

 

    SELECT employee_id,

    NULLIF(commission_pct,.1) "new commission"

    FROM employees;

 

 

2.4 COALESCE

 

COALESCE returns the first argument (beginning on the left) that is NOT NULL.

It is similar to the NVL function, but it can take multiple alternate values.

It accepts any number of arguments.

 

Example:

 

    SELECT employee_id,

    COALESCE(to_char(commission_pct),'none') commission

    FROM employees;

 

 

3. Explicit Defaults

 

If a column has a default value defined, the explicit default allows the DEFAULT keyword to be used in an INSERT or UPDATE statement. It can also be  used in bind variables. The use of the explicit default eliminates any  ambiguity of which values will be placed in a column and avoids hard-coding of  literals in applications.

 

Benefits of EXPLICIT DEFAULTS:

 

    * provides better data integrity

    * avoids the use of hard-coded litterals in applications

    * more user-friendly and provide a more flexible interface

 

Examples:

 

    Assume the employee table has a default defined for the department_id 

    column.

 

    INSERT INTO emp

    (employee_id, first_name, last_name, department_id)

    VALUES

    (1, 'Tom', 'Smith', DEFAULT);

 

    UPDATE emp

    SET department_id = DEFAULT

    WHERE department_id=20;

 

 

4. WITH clause

 

The WITH clause allows a query block to be assigned a name and used multiple times in a query by referring to this name. This is very useful to reduce the cost of a query block which will need to be evaluated more than once in a query by materializing the query block.

 

Here is an example of a query which benefits from a WITH clause:

 

    SELECT department_name, SUM(salary) dept_total

    FROM employees, departments

    WHERE employees.department_id=departments.department_id

    GROUP BY department_name HAVING

      SUM(salary) > (

      SELECT sum(salary) * 1/3

      FROM employees, departments

      WHERE employees.department_id=departments.department_id

    )

    ORDER BY dept_total;

 

This query can be rewritten as follows:

 

    WITH summary AS (

    SELECT department_name, SUM(salary) dept_total

    FROM employees, departments

    WHERE employees.department_id=departments.department_id

    GROUP BY department_name

    )

    SELECT department_name, dept_total

    FROM summary

    WHERE dept_total > (

    SELECT SUM(dept_total) * 1/3

    FROM summary

    )

    ORDER BY dept_total DESC;

 

By using the WITH clause, summarizing the department total more than once is avoided.

 

Another example:

 

    WITH

       dept_costs AS (

          SELECT department_name, SUM(salary) dept_total

             FROM empe, departments d

             WHERE e.department_id = d.department_id

          GROUP BY department_name),

       avg_cost AS (

          SELECT SUM(dept_total)/COUNT(*) avg

          FROM dept_costs)

    SELECT * FROM dept_costs

       WHERE dept_total >

          (SELECT avg FROM avg_cost)

          ORDER BY department_name;

 

 

 
About author:

Seventeen years of experience in the IT Industry in Software, MIS,development, design and database administration. Worked for more than 12 years as Oracle Database Administrator. Working with FunDtech India Ltd as Asst. Vice President - ORACLE TECHNOLOGY and DBA for the last six years. Strengths Include: Database Administration on 11g,10g,9i,8i, 8.0 and 7.x in Unix, Windows NT and Novel Netware Environment. Conducted design reviews with an aim to enhance performance in production scenario. Has also carried out Design and Development in Oracle and Developer 2000 and Forms Reports 10g.

 

Please login to post your comments





  About Us Advertise Terms of Use Privacy Newsletters Contact Us    

Home   Discussion Forum   FAQs  Articles  Jobs   Newsletters  Directory  Downloads 

Our Premium Sponsor