The traditional Oracle join syntax supports natural joining, outer joins, and Cartesian joins, as shown in the following queries: Query 1: select regions.region_name, countries.country_n
Trang 1The first two row counts are performed on the COUNTRIES and REGIONS tables, yielding 25 and 4 rows respectively The third query counts the number of rows
returned from a cross join of these tables and yields 100 Query 4 would return 100
records if the WHERE clause were absent Each of the four rows in the REGIONS table
is joined to the one row from the COUNTRIES table Each row returned contains every column from both tables
Oracle Join Syntax
A proprietary Oracle join syntax has evolved that is stable and understood by millions
of users This traditional syntax is supported by Oracle and is present in software systems across the world This syntax performs a Cartesian product, and then filters the result with a WHERE clause while the ANSI syntax joins the tables first, and then any separate WHERE clause conditions are applied to the joined results set You will
no doubt encounter the traditional Oracle join syntax that is now making way for the standardized ANSI-compliant syntax discussed in this chapter
The traditional Oracle join syntax supports natural joining, outer joins, and Cartesian joins, as shown in the following queries:
Query 1: select regions.region_name, countries.country_name
from regions, countries
where regions.region_id=countries.region_id;
Query 2: select last_name, department_name
from employees, departments
where employees.department_id (+) = departments.department_id;
Query 3: select * from regions,countries;
Query 1 performs a natural join by specifying the join as a condition in the WHERE
clause This is the most significant difference between the traditional and ANSI SQL
join syntaxes Take note of the column aliasing using the TABLE.COLUMN_NAME notation to disambiguate the identical column names This notation is discussed later
in this chapter Query 2 specifies the join between the source and target tables as a
WHERE condition with a plus symbol enclosed in brackets (+) to the left of the equal sign that indicates to Oracle that a right outer join must be performed This query returns
employees’ LAST_NAME and their matching DEPARTMENT_NAME values In addition, the outer join retrieves DEPARTMENT_NAME from the rows with DEPARTMENT_ID values not currently assigned to any employee records Query 3 performs a Cartesian
or cross join by excluding the join condition
EXAM TIP The traditional Oracle join syntax is widely used However, the
exam assesses your understanding of joins and the ANSI SQL forms of its
syntax Be prepared, though: some questions may tap your knowledge of the traditional syntax
Trang 2Chapter 12: SQL Joins
487
Joining Tables Using SQL:1999 Syntax
Prior to Oracle 9i, the traditional join syntax was the only language available to join
tables Since then, Oracle has introduced a new language that is compliant to the ANSI
SQL:1999 standards It offers no performance benefits over the traditional syntax Natural,
outer, and cross joins may be written using both SQL:1999 and traditional Oracle SQL
The general form of the SELECT statement using ANSI SQL:1999 syntax is as follows:
SELECT table1.column, table2.column
FROM table1
[NATURAL JOIN table2] |
[JOIN table2 USING (column_name)] |
[JOIN table2 ON (table1.column_name = table2.column_name)] |
[LEFT | RIGHT | FULL OUTER JOIN table2
ON (table1.column_name = table2.column_name)] |
[CROSS JOIN table2];
This is dissected and examples are explained in the following sections The general
form of the traditional Oracle-proprietary syntax relevant to joins is as follows:
SELECT table1.column, table2.column
FROM table1, table2
[WHERE (table1.column_name = table2.column_name)] |
[WHERE (table1.column_name(+)= table2.column_name)] |
[WHERE (table1.column_name)= table2.column_name) (+)] ;
If no joins or fewer than N – 1 joins are specified in the WHERE clause conditions,
where N refers to the number of tables in the query, then a Cartesian or cross join is
performed If an adequate number of join conditions is specified, then the first optional
conditional clause specifies an equijoin, while the second two optional clauses specify
the syntax for right and left outer joins
Qualifying Ambiguous Column Names
Columns with the same names may occur in tables involved in a join The columns
named DEPARTMENT_ID and MANAGER_ID are found in both the EMPLOYEES and
DEPARTMENTS tables The REGION_ID column is present in both the REGIONS and
COUNTRIES tables Listing such columns in a query becomes problematic when Oracle
cannot resolve their origin Columns with unique names across the tables involved in
a join cause no ambiguity, and Oracle can easily resolve their source table
The problem of ambiguous column names is addressed with dot notation A column
may be prefixed by its table name and a dot or period symbol to designate its origin
This differentiates it from a column with the same name in another table Dot notation
may be used in queries involving any number of tables Referencing some columns
using dot notation does not imply that all columns must be referenced in this way
Dot notation is enhanced with table aliases A table alias provides an alternate,
usually shorter name for a table A column may be referenced as TABLE_NAME
.COLUMN_NAME or TABLE_ALIAS.COLUMN_NAME Consider the query shown
in Figure 12-3
Trang 3The EMPLOYEES table is aliased with the short name EMP, while the DEPARTMENTS table is not The SELECT clause references the EMPLOYEE_ID and MANAGER_ID columns as EMP.EMPLOYEE_ID and EMP.MANAGER_ID The MANAGER_ID column from the DEPARTMENTS table is referred to as DEPARTMENTS.MANAGER_ID Qualifying the EMPLOYEE_ID column using dot notation is unnecessary because there is only one column with this name between the two tables Therefore, there
is no ambiguity
The MANAGER_ID column must be qualified to avoid ambiguity because it occurs
in both tables Since the JOIN USING format is applied, only DEPARTMENT_ID is used as the join column If a NATURAL JOIN was employed, both the DEPARTMENT_
ID and MANAGER_ID columns would be used If the MANAGER_ID column was not
Figure 12-3 Dot notation
Trang 4Chapter 12: SQL Joins
489
qualified, an “ORA-00918: column ambiguously defined” error would be returned If
DEPARTMENT_ID was aliased, an “ORA-25154: column part of USING clause cannot
have qualifier” error would be raised
SQL Developer provides the heading MANAGER_ID to the first reference made in
the SELECT clause The string “_1” is automatically appended to the second reference,
creating the heading MANAGER_ID_1
TIP Qualifying column references with dot notation to indicate a column’s
table of origin has a performance benefit Time is saved because Oracle is
directed instantaneously to the appropriate table and does not have to
resolve the table name
The NATURAL JOIN Clause
The general syntax for the NATURAL JOIN clause is as follows:
SELECT table1.column, table2.column
FROM table1
NATURAL JOIN table2;
The pure natural join identifies the columns with common names in table1 and
table2 and implicitly joins the tables using all these columns The columns in the
SELECT clause may be qualified using dot notation unless they are one of the join
columns Consider the following queries:
Query 1: select * from locations natural join countries;
Query 2: select * from locations, countries
where locations.country_id = countries.country_id;
Query 3: select * from jobs natural join countries;
Query 4: select * from jobs, countries;
In query 1, COUNTRY_ID occurs in both tables and becomes the join column
Query 2 is written using traditional Oracle syntax and retrieves the same rows as query 1
Unless you are familiar with the columns in the source and target tables, natural joins
must be used with caution, as join conditions are automatically formed between all
columns with shared names
Query 3 performs a natural join between the JOBS and COUNTRIES tables There
are no columns with identical names and this results in a Cartesian product Query 4
is equivalent to query 3, and a Cartesian join is performed using traditional Oracle
syntax
The natural join is simple but prone to a fundamental weakness It suffers the risk
that two columns with the same name might have no relationship and may not even
have compatible data types Figure 12-4 describes the COUNTRIES, REGIONS, and
SALE_REGIONS tables The SALES_REGIONS table was constructed to illustrate the
following important point: Although it has REGION_ID in common with the
COUNTRIES table, it cannot be naturally joined to it because their data types are
Trang 5incompatible The data types of the COUNTRIES.REGION_ID and SALES_REGIONS REGION_ID columns are NUMBER and VARCHAR2, respectively The character data cannot be implicitly converted into numeric data and an “ORA-01722: invalid number” error is raised The REGIONS.REGION_ID column is of type NUMBER, and its data is related to the data in the COUNTRIES table Therefore, the natural join between the REGIONS and COUNTRIES table works perfectly
Exercise 12-1: Use the NATURAL JOIN The JOB_HISTORY table shares three identically named columns with the EMPLOYEES table: EMPLOYEE_ID, JOB_
ID, and DEPARTMENT_ID Describe the tables and fetch the EMPLOYEE_ID, JOB_ID, DEPARTMENT_ID, LAST_NAME, HIRE_DATE, and END_DATE values for all rows
Figure 12-4 The natural join
Trang 6Chapter 12: SQL Joins
491
retrieved using a pure natural join Alias the EMPLOYEES table as EMP and the JOB_
HISTORY table as JH and use dot notation where necessary
1 Start SQL*Plus and connect to the HR schema
2 The tables are described and the columns with identical names and their data
types may be examined using
desc employees;
desc job_history;
3 The FROM clause is
FROM JOB_HISTORY JH
4 The JOIN clause is
NATURAL JOIN EMPLOYEES EMP
5 The SELECT clause is
SELECT EMP.LAST_NAME, EMP.HIRE_DATE, JH.END_DATE
6 Executing the following statement returns a single row with the same
EMPLOYEE_ID, JOB_ID, and DEPARTMENT_ID values in both tables
and is shown in the following illustration:
select employee_id, job_id, department_id,
emp.last_name, emp.hire_date, jh.end_date
from job_history jh natural join employees emp;
Trang 7The Natural JOIN USING Clause
The format of the syntax for the natural JOIN USING clause is as follows:
SELECT table1.column, table2.column
FROM table1
JOIN table2 USING (join_column1, join_column2 );
While the pure natural join contains the NATURAL keyword in its syntax, the JOIN USING syntax does not An error is raised if the keywords NATURAL and USING occur in the same join clause The JOIN USING clause allows one or more equijoin columns to be explicitly specified in brackets after the USING keyword This avoids the shortcomings associated with the pure natural join Many situations demand that tables be joined only on certain columns, and this format caters to this requirement Consider the following queries:
Query 1: select * from locations join countries using
(country_id);
Query 2: select * from locations, countries
where locations.country_id = countries.country_id;
Query 3: select * from jobs join countries using ;
Query 1 specifies that the LOCATIONS and COUNTRIES tables must be joined on common COUNTRY_ID column values All columns from these tables are retrieved for the rows with matching join column values Query 2 shows a traditionally specified query that retrieves the same rows as query 1 Query 3 illustrates that a Cartesian join
cannot be accidentally specified with the JOIN USING syntax since only columns
with shared names are permitted after the USING keyword The join columns cannot
be qualified using table names or aliases when they are referenced Since this join syntax potentially excludes some columns with identical names from the join clause, these must be qualified if they are referenced to avoid ambiguity
As Figure 12-5 shows, the JOB_HISTORY and EMPLOYEES tables were joined based on the presence of equal values in their JOB_ID and EMPLOYEE_ID columns Rows conforming to this join condition are retrieved These tables share three
identically named columns The JOIN USING syntax allows the specification of only two of these as join columns Notice that although the third identically named
column is DEPARTMENT_ID, it is qualified with a table alias to avoid ambiguity However, the join columns in the USING clause cannot be qualified with table aliases
The Natural JOIN ON Clause
The format of the syntax for the natural JOIN ON clause is as follows:
SELECT table1.column, table2.column
FROM table1
JOIN table2 ON (table1.column_name = table2.column_name);
The pure natural join and the JOIN USING clauses depend on join columns with identical column names The JOIN ON clause allows the explicit specification
Trang 8Chapter 12: SQL Joins
493
of join columns, regardless of their column names This is the most flexible and widely
used form of the join clauses The equijoin columns are fully qualified as table1.column1
= table2.column2 and are optionally specified in brackets after the ON keyword The
following queries illustrate the JOIN ON clause:
Query 1: select * from departments d
join employees e on (e.employee_id=d.department_id);
Query 2: select * from employees e, departments d
where e.employee_id=d.department_id;
Query 1 retrieves all column values from both the DEPARTMENTS and EMPLOYEES
tables for the rows that meet the equijoin condition that is fulfilled by EMPLOYEE_ID
values matching DEPARTMENT_ID values from the DEPARTMENTS table The
traditional Oracle syntax in query 2 returns the same results as query 1 Notice the
similarities between the traditional join condition specified in the WHERE clause
and the join condition specified after the ON keyword
The START_DATE column in the JOB_HISTORY table is joined to the HIRE_DATE
column in the EMPLOYEES table in Figure 12-6 This equijoin retrieves the details of
employees who worked for the organization and changed jobs
Figure 12-5 Natural join using the JOIN USING clause
Trang 9Exercise 12-2: Use the NATURAL JOIN ON Clause Each record in the DEPARTMENTS table has a MANAGER_ID column matching an EMPLOYEE_ID value in the EMPLOYEES table You are required to produce a report with one column aliased as Managers Each row must contain a sentence of the format FIRST_NAME LAST_NAME is manager of the DEPARTMENT_NAME department Alias the EMPLOYEES table as E and the DEPARTMENTS table as D and use dot notation where possible
1 Start SQL Developer and connect to the HR schema
2 The expression aliased as Managers may be constructed by concatenating the required items and separating them with spaces
3 Executing the following statement returns 11 rows describing the managers of each department:
select e.first_name||' '||e.last_name||' is manager of the '||d.department_name||'department.' "Managers" from employees e
Figure 12-6 Natural join using the JOIN ON clause
Trang 10Chapter 12: SQL Joins
495
N-Way Joins and Additional Join Conditions
The joins just discussed were demonstrated using two tables There is no restriction on
the number of tables that may be related using joins Third normal form consists of
a set of tables connected through a series of primary and foreign key relationships
Traversing these relationships using joins enables consistent and reliable retrieval of
data When multiple joins exist in a statement, they are evaluated from left to right
Consider the following query using pure natural joins:
select r.region_name, c.country_name, l.city, d.department_name
from departments d natural join locations l
natural join countries c natural join regions r;
The join between DEPARTMENTS and LOCATIONS creates an interim result set
consisting of 27 rows These tables provide the DEPARTMENT_NAME and CITY
columns This set is naturally joined to the COUNTRIES table Since the interim set
does not contain the COUNTRY_ID column, a Cartesian join is performed The
27 interim rows are joined to the 25 rows in the COUNTRIES table, yielding a new
interim results set with 675 (27 × 25) rows and three columns: DEPARTMENT_
NAME, CITY, and COUNTRY_NAME This set is naturally joined to the REGIONS
table Once again, a Cartesian join occurs because the REGION_ID column is absent
from the interim set The final result set contains 2700 (675 × 4) rows and four
columns Using pure natural joins with multiple tables is error prone and not
recommended
The JOIN USING and JOIN ON syntaxes are better suited for joining
multiple tables The following query joins correctly these four tables using the pure
natural join syntax, by including the required join columns in the SELECT clause:
select region_id, country_id, c.country_name, l.city, d.department_name
from departments d natural join locations l
natural join countries c natural join regions r;
This query correctly yields 27 rows in the final results set The following query
demonstrates how the JOIN ON clause is used to fetch the same 27 rows A join
condition can reference only columns in its scope In the following example, the join
from DEPARTMENTS to LOCATIONS may not reference columns in the COUNTRIES
or REGIONS tables, but the join between COUNTRIES and REGIONS may reference
any column from the four tables involved in the query
select r.region_name, c.country_name, l.city, d.department_name
from departments d
join locations l on (l.location_id=d.location_id)
join countries c on (c.country_id=l.country_id)
join regions r on (r.region_id=c.region_id);
The JOIN USING clause can also be used to join these four tables as follows:
select r.region_name, c.country_name, l.city, d.department_name
from departments d
join locations l using (location_id)
join countries c using (country_id)