OCA/OCP Oracle Database 11g All-in-One Exam Guide 486 The 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. Chapter 12: SQL Joins 487 PART II 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. OCA/OCP Oracle Database 11g All-in-One Exam Guide 488 The 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 Chapter 12: SQL Joins 489 PART II 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 OCA/OCP Oracle Database 11g All-in-One Exam Guide 490 incompatible. 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 Chapter 12: SQL Joins 491 PART II 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; OCA/OCP Oracle Database 11g All-in-One Exam Guide 492 The 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 Chapter 12: SQL Joins 493 PART II 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 OCA/OCP Oracle Database 11g All-in-One Exam Guide 494 Exercise 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 join departments d on (e.employee_id=d.manager_id); Figure 12-6 Natural join using the JOIN . . . ON clause Chapter 12: SQL Joins 495 PART II 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) join regions r using (region_id); . column may be referenced as TABLE_NAME .COLUMN_NAME or TABLE_ALIAS.COLUMN_NAME. Consider the query shown in Figure 12-3. OCA/ OCP Oracle Database 11g All-in-One Exam Guide 488 The EMPLOYEES table. cannot be naturally joined to it because their data types are OCA/ OCP Oracle Database 11g All-in-One Exam Guide 490 incompatible. The data types of the COUNTRIES.REGION_ID and SALES_REGIONS. REGION_ID. job_id, department_id, emp.last_name, emp.hire_date, jh.end_date from job_history jh natural join employees emp; OCA/ OCP Oracle Database 11g All-in-One Exam Guide 492 The Natural JOIN USING Clause The