转自:http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=4095208

Oracle语法&SQL1999语法:

1.笛卡尔乘积(CROSS JOIN)

   第一张表的所有行会与第二张表的所有行进行连接,即n*m方式进行连接

   oracle语法

   select count(*) from hr.employees a,hr.departments b;

    2889行

   雇员表的107行记录与部门表的27行记录相乘积(107*27),得到2889条记录

   SQL1999语法:

  select count(*) from hr.employees a cross join hr.departments b

    2889行

 

2.等价连接

   select a.department_id,b.department_id, a.employee_id, b.department_name

  from hr.employees a, hr.departments b

 where a.department_id = b.department_id

   and a.department_id = 90

a.DEPARTMENT_ID

b.DEPARTMENT_ID

EMPLOYEE_ID

DEPARTMENT_NAME

90

90

100

Executive

90

90

101

Executive

90

90

102

Executive


把在a表和b表,部门相同,且部门号为90的员工匹配出来。

SQL1999语法:

在sql1999语法中的naturaljion连接中,与oracle语法中的等值连接是有区别的.

先举例说明:

 natural jion连接的条件是:两表连接中的列名要有相同的、相同的列名的值要相同的、相同的列名的数据类型要相同的。


sql-1:

selecta.employee_id, a.manager_id, a.department_id

  from hr.employees a

 where a.employee_id in (114, 115, 116, 117, 118, 119)

雇员表雇员114,115,116,117,118,119的相关结果集如下:

EMPLOYEE_ID MANAGER_ID  DEPARTMENT_ID

114                     100              30

115                  114             30

116                  114            30

117                     114             30

118                  114             30

119                     114             30

 

sql-2:

等值连接:

selecta.employee_id, a.manager_id, a.department_id

  from hr.employees a, hr.departments b

 where a.department_id = b.department_id

   and a.department_id = 30

EMPLOYEE_ID MANAGER_ID  DEPARTMENT_ID

114                        100    30

115                      114    30

116                        114    30

117                     114     30

118                        114    30

119                        114    30

 

sql-3:

netural join:

selectemployee_id, manager_id, department_id

  from hr.employees a natural

  join hr.departments b

 where department_id = 30

EMPLOYEE_ID MANAGER_ID  DEPARTMENT_ID

115                      114    30

116                        114    30

117                     114     30

118                        114    30

119                        114    30


大家注意看,在sql-1中,我列出了雇员114~119的一些情况,在sql-2中,进行的是等值连接,而在sql-3中,进行的是NATURALJOIN连接.

sql-2与sql-3的结果集的区别在哪里?

sql-2的等值连接中有雇员114的记录,而sql-3的NATURALJOIN连接中没有雇员114的记录,为什么?

natural jion连接的条件是:

 (1) 两表连接的列名要有相同的

 (2) 两表连接的列名的数据类型要相同的

 (3) 两表连接的列名的值要相同的,原因就在这里。

原因就是雇员表中部门30的雇员114的manager_id的值是100,而部门表中30号部门中没有manager_id=100的记录,所以,不符合条件(3),故而neturaljoin连接中没有匹配雇员为为114的记录了,然而,等值连接则没有这样的条件,故而能匹配雇员为114的记录。

  这就是NATURALJOIN与等值连接的区别。

其实NATURAL JOIN自然连接是两表中的相同的列的自然连接,换句话说,就是不需要人工干预,比方说,A表与B表有3列名相同,那么oracleNATURAL JOIN自然连接就连接相同的三列,自然连接的这相同的三列的列值是AND的关系,三列的条件必须同时满足才匹配,如果其中一列值不匹配,那么该列的列值就被抛弃。如果进行人工干预,比方说,我只需要使用其中一列作为连接列,那么这就是不是自然连接了,可以是USING子句,oracle等价连接来完成。

再举例一个:

看一个需要人工干预的等值连接:

selectb.department_id "b-manager_id",

       a.department_id"a-department_id",

       b.manager_id    "b-department_id",

       a.manager_id    "a-manager_id"

  from hr.employees a, hr.departments b

 where a.department_id = b.department_id

   and a.department_id = 30

b-department_id

a-department_id

b-manager_id

a-manager_id

30

30

114

100

30

30

114

114

30

30

114

114

30

30

114

114

30

30

114

114

30

30

114

114

看上述表格的第一行,a表列department_id,manager_id与b表department_id

,manager_id两列相同,但是这里我使用人工控制的方式来进行连接,就是说我选择了其中一个相同列deparament_id来进行连接,只有两表department_id匹配,就返回记录,而不管manager_id匹配不匹配.

自然连接则不同,下面举例:

selectdepartment_id "b-department_id",

       department_id"a-department_id",

       manager_id    "b-manager_id",

       manager_id    "a-manager_id"

  from hr.employees a natural join  hr.departments b

   where department_id = 30

b-department_id

a-department_id

b-manager_id

a-manager_id

30

30

114

114

30

30

114

114

30

30

114

114

30

30

114

114

30

30

114

114

看上图,自然连接就是两表所有相同的列进行连接,其实看sql语句也看出来了,上面的sql并没有连接条件,这也表示了是用两表中所有的相同的列进行连接,这是自然连接的第一个点,再有就是,比较两张表格的结果集,有所不同,b-manager_id=114与a-manager_id=100的结果集不符合自然连接的要求,故而自然连接的结果集中并没有显示,因为必须满足b-manager_id= a-manager_id的要求,其实,上述自然连接的sql可以等价如下语句:

selectb.department_id "b-department_id",

         a.department_id"a-department_id",

         b.manager_id    "b-manager_id",

         a.manager_id    "a-manager_id"

    from hr.employees a, hr.departments b

   where a.department_id = 30

     and a.department_id = b.department_id

     and a.manager_id = b.manager_id

b-department_id

a-department_id

b-manager_id

a-manager_id

30

30

114

114

30

30

114

114

30

30

114

114

30

30

114

114

30

30

114

114

注意的是,自然连接的select 列表中,不允许有别名来限定表名,where 条件中也不允许有别名来限定表名。

上面讲的是两表连接。

自然连接中的多表(2张表以上)连接也是一样的。

selectdepartment_id "b-department_id",

       department_id"a-department_id",

       manager_id    "b-manager_id",

       manager_id    "a-manager_id",

       job_id   "c-job_id"

  from hr.employees a natural join  hr.departments b natural join hr.jobs c

   where department_id = 30

b-department_id  a-department_id b-manager_id a-manager_id c-job_id

30  30 114   114   PU_CLERK

30  30 114   114   PU_CLERK

30  30 114   114   PU_CLERK

30  30 114   114   PU_CLERK

30  30 114   114   PU_CLERK


3.外连接

    Oracle语法:

   3.1 左外连接

 select a.employee_id,a.department_id, b.department_id, b.department_name

  from hr.employees a, hr.departments b

 where a.department_id = b.department_id(+)

   and a.employee_id in (100, 101, 178)

 order by a.employee_id

EMPLOYEE_ID

DEPARTMENT_ID

DEPARTMENT_ID

DEPARTMENT_NAME

100

90

90

Executive

101

90

90

Executive

178        

 空值

空值

空值

雇员178号没有部门号,这个如果连接条件是a.department_id =b.department_id,则不会匹配出雇员178,因为雇员表没有雇员178的的部门号,部门表也没有雇员178的部门号,空值与空值的匹配仍然是空值.但是如果是部门表b.department_id(+)这样与雇员表a.department_id进行连接,那么就会把雇员178给匹配出来.这就是oracle的左外连接.

    SQL1999语法:

selecta.employee_id, a.department_id, b.department_id, b.department_name

  from hr.employees a left outer join hr.departments b

    on a.department_id = b.department_id

 where a.employee_id in (100, 101, 178)

 order by a.employee_id

得出一样的结果集

  3.2 右外连接

selecta.employee_id, a.department_id, b.department_id, b.department_name

  from hr.employees a, hr.departments b

 where a.department_id(+) = b.department_id

 and b.department_id in (110,120)

EMPLOYEE_ID

DEPARTMENT_ID

DEPARTMENT_ID

DEPARTMENT_NAME

205

110

110

Accounting

206

110

110

Accounting

空值

空值

120

Treasury

部门号120没有雇员,如果这个连接条件为a.department_id =b.department_id,将不会匹配部门号120的记录,因为雇员表的没有部门为120的部门,为空值,部门表有120号部门,空值与部门120进行匹配,得到的结果仍然是空值。但是如果雇员表想知道部门表里面还有哪些部门是没有雇员的,怎么办?那么这样可以解决这个问题,雇员表department_id(+)与部门表department_id进行连接,则可以将部门表没有雇员的部门也匹配出来。这就是Oracle的右外连接.

SQL1999语法:

selecta.employee_id, a.department_id, b.department_id, b.department_name

  from hr.employees a right outer join hr.departments b

  on a.department_id = b.department_id

 where b.department_id in (110,120)

得出一样的结果集

  3.2 全外连接

     oracle语法中并没有全外连接的写法,在sql1999语法中,有这个写法:

     使用 fullouter join关键字来连接

      (略)


4.自连接

oracle语法中的自连接,是在一张表中进行连接,雇员表中的员工与管理员的关系,可以在一张雇员表中找出来,比如员工的管理者是谁。

举例:

比如90号部门的雇员情况如下:

selectw.employee_id,

        w.first_name,

        w.last_name,

        w.manager_id,

        w.department_id

   from hr.employees w

  where w.department_id = 90

EMPLOYEE_ID

FIRST_NAME

LAST_NAME

MANAGER_ID

DEPARTMENT_ID

100

Steven

King

 

90

101

Neena

Kochhar

100

90

102

Lex

De Haan

100

90

员工101,102的的管理者为100,即Steven King.如果通过两张表的连接体现在一行上面.使用oracle的自连接可以实现这一点.

selectw.employee_id as "员工编号",

        w.first_name || ' '||

        w.last_name as "员工姓名",

        m.employee_id as "管理者编号",

        m.first_name ||' ' ||

        m.last_name as "部门管理者",

        m.manager_id as  "部门管理者编号"

   from hr.employees w, hr.employees m

  where w.manager_id = m.employee_id

    and w.department_id = 90

员工编号

员工姓名

管理者编号

部门管理者

部门管理者编号

101

Neena Kochhar

100

Steven

 

102

Lex De Haan

100

Steven

 

使用自连接,实现了一行记录即有员工,也有管理者的记录,其实就是把雇员ID为100的一行记录分别与雇员ID为101,102的两行记录进行了合并而已。

这就是oracle的自连接。

 

5.using子句进行表连接

sql1999语法:

其实using 子句是相对于natural join来说的,其实就是等值连接

举例:

selectdepartment_id "b-department_id",

       department_id"a-department_id",

       manager_id    "b-manager_id",

       manager_id    "a-manager_id"

  from hr.employees a  join  hr.departments b using (department_id)

   where department_id = 30

b-department_id

a-department_id

b-manager_id

a-manager_id

30

30

114

100

30

30

114

114

30

30

114

114

30

30

114

114

30

30

114

114

30

30

114

114

相当于等值连接

注意的是,select 列表中,不允许有别名来限定表名,where 条件中也不允许有别名来限定表名。

也可以这样写:

selectdepartment_id "b-department_id",

       department_id"a-department_id",

       manager_id    "b-manager_id",

       manager_id    "a-manager_id"

  from hr.employees a  join  hr.departments b using(department_id,manager_id)

   where department_id = 30

b-department_id

a-department_id

b-manager_id

a-manager_id

30

30

114

114

30

30

114

114

30

30

114

114

30

30

114

114

30

30

114

114

相等于自然连接。

注意的是,select 列表中,不允许有别名来限定表名,where 条件中也不允许有别名来限定表名。

6.on子句

 

sql1999语法:

其实on子句只不过是等值连接另外一种写法罢了。

举例说明:

selectb.department_id "b-department_id",

       a.department_id"a-department_id",

       b.manager_id    "b-manager_id",

       a.manager_id    "a-manager_id"

  from hr.employees a

  join hr.departments b

    on (a.department_id = b.department_id)

 where a.department_id = 30

相当于:

selectb.department_id "b-department_id",

       a.department_id"a-department_id",

       b.manager_id    "b-manager_id",

       a.manager_id    "a-manager_id"

  from hr.employees a, hr.departments b

 where a.department_id = 30

   and b.department_id = a.department_id

得到相同的结果集:

b-department_id

a-department_id

b-manager_id

a-manager_id

30

30

114

100

30

30

114

114

30

30

114

114

30

30

114

114

30

30

114

114

30

30

114

114

注意的是,在on子句中,select 列表中,允许有别名来限定表名,where 条件中允许有别名来限定表名。


09-19 15:03