符合ANSI 标准的SQL连接(原自:http://www.joeco.com.cn/wj/yykf/oracle/oracle_sqllj.htm


Oracle9i中的新SQL连接简化了经常要用到的连接并加入了完全的外连接的支持。
对SQL/92标准连接语法的支持是Oracle9i所提供的众多的新特性之一。这一支持使得可移植的应用程序的编写比以往更加容易,而且它还允许完全的外连接。?

Oracle9i之前的连接语法
过去, Oracle数据库支持为SQL/86而定义的连接语法。 程序清单1 给出了这种老标准连接语法的一个例子。
Oracle9i出现以前,Oracle 数据库通过使用专用语法来支持外连接。程序清单2 展示了COURSE 和ENROLLMENT之间的外连接。

请注意:表ENROLLMENT中的列名后面的WHERE子句使用了"(+)" ,其目的是使得此表成为连接中的可选表。

传统的连接语法存在一些问题。例如,给定一个复杂的查询,解析其WHERE子句以从对查询结果的其它限制条件中分隔出连接条件通常是很困难的。此外,程序员有时会漏了指定任何连接条件,这将导致一个笛卡儿乘积。

ANSI 标准连接语法
ANSI 标准连接语法在Oracle9i 中加入了一些新关键字和子句,它们使您能完全在一条SELECT语句的FROM子句中指定连接。让我们看一下连接表COURSE 和表ENROLLMENT 的问题。按照传统方法,第一步您通常会在查询的FROM子句中列出这两张表,如下:
FROM courses c, enrollment e

但是,在这个新的ANSI标准语法中,你无需使用逗号;相反,你可显式地指定所需的连接类型。例如,要对COURSE 和ENROLLMENT 表进行内连接,代码是:

FROM courses c
INNER JOIN enrollment e

Jonathan Gennick在网站http://gennick.com 上提供了更多的在线Oracle 提示。
指明了你所需的是一个内连接后,接下来就得指定连接的条件。这是通过在FROM 子句的ON子句部分指定连接条件实现的,而不是将连接条件与WHERE 子句其他的限制条件混杂在一起,如下例所示:

SELECT c.course_name, c.period,
e.student_name
FROM course c INNER JOIN enrollment e
ON c.course_name = e.course_name
AND c.period = e.period;

如果你习惯了使用老的连接语法,那么你可能要花一定的时间才能适应这个新的连接语法。但是,这是很值得的,因为新语法有不少优点:

一个连接的所有信息都在同一处指定。你无需再费力地编写复杂的WHERE子句,辛苦地将连接条件从其它限制条件中分离开来。
你也绝对不会"忘记"指定连接条件。 例如,一旦指定了一个内连接,Oracle9i 就会要求你使用ON子句--或其它子句--显式地指定连接条件。如果你确实需要一个笛卡儿乘积,则你就必须明示这个要求。
你还可以执行完全外连接,这在以前的Oracle数据库连接语法中是不可能实现的。
此外,新语法中,你不必再担心由于粗心漏掉了"(+),"符号而导致外连接转变为内连接。
指定连接条件
到目前为止,我已使用了ON 子句来指定连接条件:
SELECT c.course_name, c.period,
e.student_name
FROM course c INNER JOIN enrollment e
ON c.course_name = e.course_name
AND c.period = e.period;

从webstore.ansi.org 可以购买到大量的ANSI 标准的SQL 文档。
ON子句允许你将任意的布尔表达式指定为一个连接条件。然而,大多数的连接都是相等连接。所谓相等连接,意即在此连接中比较两张表的相关列的相等性。因此,如果定义连接的列在两张表中的命名完全相同,那么你就可以利用简化的语法编写出高清晰度的查询。除了用ON 子句指定某个布尔连接条件外,你还可以用USING子句取代ON来指定连接列。例如,你可以将如下语句:

ON c.course_name = e.course_name
AND c.period = e.period;

代之以:

USING (course_name, period);

上例中的USING 子句指定当两表各自的COURSE_NAME和PERIOD列的值对应相等时,连接这两个表的行。程序清单3 给出了一个使用USING子句执行相等连接的例子。不难发现,程序清单3中的SELECT 语句非常简洁易懂。但是,USING子句对整个查询的语义会有微秒的影响。当编写带有ON子句的连接时,两张表的所有列都是可用的。因而,你可以把这两张表的COURSE_NAME 列都选择出来:

SELECT C.COURSE_NAME, E.COURSE_NAME

《Oracle9i SQL 参考》 包括了有关连接的信息和示例。从otn.oracle.com/docs/可以访问到此手册的在线版本。
如果在USING子句中像上例那样使用列别名,你将收到一个"无效列名"的错误信息。当指定了USING子句,数据库引擎将合并这两个COURSE_NAME 列并且在结果中只识别一个这样的列。此列与任何一个被连接的表都没有关联,所以你不能用别名来限定它。这一规定是合理的,因为,按照定义,一个相等连接意味着对查询返回的每一行只存在唯一的COURSE_NAME 值。

使用USING子句可以方便简明地表达出相等联;在我看来,由此生成的查询要比使用ON的查询更容易让人理解。当然,还有另外一个捷径,即NATURAL 子句--不过,是否应该提及它,我有些犹豫,而且也不推荐你使用它。使用NATURAL 子句可以创建一个NATURAL 连接-- 一种特殊类型的相等连接,在此连接中,连接列由两表中所有命名完全相同的列组成,如程序清单4 所示。但是,我不推荐使用NATURAL 连接,我觉得这是ANSI所犯的一个错误。如果使用了一个NATURAL 连接,那么当你向一张表添加的列不经意地恰好与另一张表中的列同名时,你有可能也在不知情的情况下更改了你NATURAL 连接。

ANSI风格的外连接
新的ANSI 语法承认三种类型的外连接:向左外连接,向右外连接,以及完全外连接。向左和向右外连接事实上做的是相同的事-- 一张表的所有行将全被包含,再加上另一张表中所有相匹配的行。两者中唯一的区别在于它们列出表的顺序不同。以下示例的三个查询在语义上完全等价,其中第一个使用的是老的语法:
SELECT c.course_name, c.period,
e.student_name
FROM course c, enrollment e
WHERE c.course_name = e.course_name(+)
AND c.period = e.period(+);

SELECT c.course_name, c.period,
e.student_name
FROM course c LEFT OUTER JOIN enrollment e
ON c.course_name = e.course_name
AND c.period = e.period;

SELECT c.course_name, c.period,
e.student_name
FROM enrollment e RIGHT OUTER JOIN course c
ON c.course_name = e.course_name
AND c.period = e.period;

完全外连接则代表了一种全新的功能,它把来自两张表的所有行都返回。行在连接列上进行可能的匹配,对于在另一张表中没有匹配值的任一行都用NULL填充空列。程序清单5 给出了两个示例,其一是Oracle9i出现以前模拟的完全外连接,另一个则是Oracle9i的完全外连接。

在程序清单5 的输出结果中,COURSE 表中课程名为Spanish I 和 U.S. History的行在表ENROLLMENT中没有相对应的行。 因此,这些行的STUDENT_NAME列为NULL.。课程名为Sky Lynn's German I 的行在COURSE 表中没有对应行。但是,请注意,此行的COURSE_NAME 和PERIOD 列却不是NULL。这些列是由USING子句指定的连接列,. 因而,当COURSE表中没有可用的行时,Oracle9i 将表ENROLLMENT 中这些列的值赋给了COURSE表中对应行的对应列。对于相等连接的情况,这样做是有意义的。 如果你倾向于将列视作NULL,可以使用ON子句来指定连接条件,如程序清单6 所示。

由于程序清单6 使用了ON子句, 因此取值Sky Lynn 的行的COURSE_NAME 和 PERIOD 列均为NULL。

多条件连接
你可以在查询中指定多个连接条件以连接两张以上的表。默认情况下, Oracle9i 从左至右处理连接。但是,可以使用圆括号控制连接的顺序。以下两个查询是等价的:
SELECT course_name, period, student_name,
s.grade_level
FROM course c INNER JOIN enrollment e
USING (course_name, period)
INNER JOIN student s USING (student_name);

SELECT course_name, period, student_name,
s.grade_level
FROM (course c INNER JOIN enrollment e
USING (course_name, period))
INNER JOIN student s USING (student_name);

第一个查询将 COURSE 连接到 ENROLLMENT 并将结果连接到STUDENT。第二个查询使用圆括号指定了完全相同的连接次序。


例子:

来源:http://www.cnoug.org/viewthread.php?tid=1174&highlight=%CD%E2%C1%AC%BD%D3

一般的相等连接:
select * from a, b where a.id = b.id;
这个就属于内连接。
 
对于外连接:
Oracle中可以使用“(+) ”来表示,9i可以使用LEFT/RIGHT/FULL OUTER JOIN 
 
LEFT OUTER JOIN:左外关联 
SELECT e.last_name, e.department_id, d.department_name 
FROM employees e 
LEFT OUTER JOIN departments d 
ON (e.department_id = d.department_id); 
等价于 
SELECT e.last_name, e.department_id, d.department_name 
FROM employees e, departments d 
WHERE e.department_id=d.department_id(+) 
结果为:所有员工及对应部门的记录,包括没有对应部门编号department_id的员工记录。 
 
RIGHT OUTER JOIN:右外关联 
SELECT e.last_name, e.department_id, d.department_name 
FROM employees e 
RIGHT OUTER JOIN departments d 
ON (e.department_id = d.department_id); 
等价于 
SELECT e.last_name, e.department_id, d.department_name 
FROM employees e, departments d 
WHERE e.department_id(+)=d.department_id 
结果为:所有员工及对应部门的记录,包括没有任何员工的部门记录。 
 
FULL OUTER JOIN:全外关联 
SELECT e.last_name, e.department_id, d.department_name 
FROM employees e 
FULL OUTER JOIN departments d 
ON (e.department_id = d.department_id); 
结果为:所有员工及对应部门的记录,包括没有对应部门编号department_id的员工记录和没有任何员工的部门记录。

ORACLE8i是不直接支持完全外连接的语法,也就是说不能在左右两个表上同时加上(+),下面是在ORACLE8i可以参考的完全外连接语法
select t1.id,t2.id from table1 t1,table t2 where t1.id=t2.id(+)
union
select t1.id,t2.id from table1 t1,table t2 where t1.id(+)=t2.id