Key joins when there are multiple foreign key relationships

When SQL Anywhere attempts to generate a join condition based on a foreign key relationship, it sometimes finds more than one relationship. In these cases, SQL Anywhere determines which foreign key relationship to use by matching the role name of the foreign key to the correlation name of the primary key table that the foreign key references.

The following sections describe how SQL Anywhere generates join conditions for key joins. This information is summarized in Rules describing the operation of key joins.

Correlation name and role name

A correlation name is the name of a table or view that is used in the FROM clause of the query—either its original name, or an alias that is defined in the FROM clause.

A role name is the name of the foreign key. It must be unique for a given foreign (child) table.

If you do not specify a role name for a foreign key, the name is assigned as follows:

  • If there is no foreign key with the same name as the primary table name, the primary table name is assigned as the role name.

  • If the primary table name is already being used by another foreign key, the role name is the primary table name concatenated with a zero-padded three-digit number unique to the foreign table.

If you don't know the role name of a foreign key, you can find it in Sybase Central by expanding the database container in the left pane. Select the table in left pane, and then click the Constraints tab in the right pane. A list of foreign keys for that table appears in the right pane.

See Sample database schema for a diagram that includes the role names of all foreign keys in the SQL Anywhere sample database.

Generating join conditions

SQL Anywhere looks for a foreign key that has the same role name as the correlation name of the primary key table:

  • If there is exactly one foreign key with the same name as a table in the join, SQL Anywhere uses it to generate the join condition.

  • If there is more than one foreign key with the same name as a table, the join is ambiguous and an error is issued.

  • If there is no foreign key with the same name as the table, SQL Anywhere looks for any foreign key relationship, even if the names don't match. If there is more than one foreign key relationship, the join is ambiguous and an error is issued.

Example 1

In the SQL Anywhere sample database, two foreign key relationships are defined between the tables Employees and Departments: the foreign key FK_DepartmentID_DepartmentID in the Employees table references the Departments table; and the foreign key FK_DepartmentHeadID_EmployeeID in the Departments table references the Employees table.

The Employees table and Departments table, showing their foreign key relationships.

The following query is ambiguous because there are two foreign key relationships and neither has the same role name as the primary key table name. Therefore, attempting this query results in the syntax error SQLE_AMBIGUOUS_JOIN (-147).

SELECT Employees.Surname, Departments.DepartmentName
FROM Employees KEY JOIN Departments;
Example 2

This query modifies the query in Example 1 by specifying the correlation name FK_DepartmentID_DepartmentID for the Departments table. Now, the foreign key FK_DepartmentID_DepartmentID has the same name as the table it references, and so it is used to define the join condition. The result includes all the employee last names and the departments where they work.

SELECT Employees.Surname, 
    FK_DepartmentID_DepartmentID.DepartmentName
FROM Employees KEY JOIN Departments 
    AS FK_DepartmentID_DepartmentID;

The following query is equivalent. It is not necessary to create an alias for the Departments table in this example. The same join condition that was generated above is specified in the ON clause in this query:

SELECT Employees.Surname, Departments.DepartmentName
FROM Employees JOIN Departments
   ON Departments.DepartmentID = Employees.DepartmentID;
Example 3

If the intent was to list all the employees that are the head of a department, then the foreign key FK_DepartmentHeadID_EmployeeID should be used and Example 1 should be rewritten as follows. This query imposes the use of the foreign key FK_DepartmentHeadID_EmployeeID by specifying the correlation name FK_DepartmentHeadID_EmployeeID for the primary key table Employees.

SELECT FK_DepartmentHeadID_EmployeeID.Surname, Departments.DepartmentName
FROM Employees AS FK_DepartmentHeadID_EmployeeID 
    KEY JOIN Departments;

The following query is equivalent. The join condition that was generated above is specified in the ON clause in this query:

SELECT Employees.Surname, Departments.DepartmentName
FROM Employees JOIN Departments
   ON Departments.DepartmentHeadID = Employees.EmployeeID;
Example 4

A correlation name is not needed if the foreign key role name is identical to the primary key table name. For example, you can define the foreign key Departments for the Employees table:

ALTER TABLE Employees 
   ADD FOREIGN KEY Departments (DepartmentID) 
   REFERENCES Departments (DepartmentID);

Now, this foreign key relationship is the default join condition when a KEY JOIN is specified between the two tables. If the foreign key Departments is defined, then the following query is equivalent to Example 3.

SELECT Employees.Surname, Departments.DepartmentName
FROM Employees KEY JOIN Departments;
Note

If you try this example in Interactive SQL, you should reverse the change to the SQL Anywhere sample database with the following statement:

ALTER TABLE Employees DROP FOREIGN KEY Departments;