多表连接

***********************************************
 ORACLE的连接(非SQL99的连接)
***********************************************

一、多表连接的起因
1、关系数据库的设计范式
(1)第一范式(1NF):属性不可分。
(2)第二范式(2NF):非主属性完全依赖于码。
(3)第三范式(3NF):符合2NF,并且,消除传递依赖。
 还有另外三个范式我就不多说了!

2、下面是范化的一个例子:我们来设一个EMPLOYEES(雇员表),其中字段有:EMPLOYEE_ID,NAME,JOB_ID,DEPARTMENT_ID
EMPLOYEES这个表用于保存雇员的信息,而你想要删除其中的一个雇员,这时你就必须同时删除一个部门和职位。范式就是要解决这个问题,你可以将这个表化为三个表,一个用于存储雇员的信息(EMPLOYEES),一个用于存储每个雇员所在部门的信息(DEPARTMENTS),另一个用于存储雇员的职位信息(JOBS),这样对其中一个表做添加或删除操作就不会影响另一个表。

3、我们在查询信息的往往要显示比较全面的信息,比如就上面的例子,我要查雇员的所有信息(雇员号、姓名,部门名称,职位等),这些信息分布在这三个表中,这时候就要把EMPLOYEES、DEPARTMENTS、JOBS这几个表连接起来显示全面的雇员信息。下面我们来讲讲各种连接。


 

二、笛卡尔乘积(以HR用户做测试)
1、要想从多个表中取数据,命令非常简单。我们可以在SELECT命令的FROM后,加多个表名,就是告诉Oracle我要从多个表中取数据。
select * from employees,departments;
显示的结果的总行数等于EMPLOYEES表的总行数乘以DEPARTMENTS表的总行数,如下操作:


hr@OCM> select count(*) from employees;

  COUNT(*)
----------
       105

hr@OCM> select count(*) from departments;

  COUNT(*)
----------
        28

hr@OCM> select count(*) from employees,departments;

  COUNT(*)
----------
      2940

hr@OCM> select 105*28 from dual;

    105*28
----------
      2940


2、就是将EMPLOYEES表的每一行,和DEPARTMENTS表的每一行,组合到一起。这种连接方式,叫笛卡尔乘积。也就是EMPLOYEES表有105行,DEPARTMENTS表有28行。连接结果有105*28,一共2940行。这样的连接结果,没有什么意义。

 

三、等值连接
1、操作如下:
EMPLOYEES表和DEPARTMENTS表有一个共同的列,就是DEPARTMENT_ID。


hr@OCM> select EMPLOYEE_ID,FIRST_NAME,DEPARTMENT_NAME
  2          from EMPLOYEES e,DEPARTMENTS d
  3     where e.DEPARTMENT_ID=d.DEPARTMENT_ID;

EMPLOYEE_ID FIRST_NAME           DEPARTMENT_NAME
----------- -------------------- ------------------------------
        200 Jennifer             Administration
        201 Michael              Marketing
        202 Pat                  Marketing
        114 Den                  Purchasing
        119 Karen                Purchasing
        115 Alexander            Purchasin


hr@OCM> select EMPLOYEE_ID,FIRST_NAME,DEPARTMENT_ID,DEPARTMENT_NAME
  2         from EMPLOYEES e,DEPARTMENTS d
  3         where e.DEPARTMENT_ID=d.DEPARTMENT_ID;
select EMPLOYEE_ID,FIRST_NAME,DEPARTMENT_ID,DEPARTMENT_NAME
                              *
ERROR at line 1:
ORA-00918: column ambiguously defined


2、只对两个表中,某些列相等的行进行连接,就是等值连接。在连接条件中,列名前的表名,e.DEPARTMENT_ID=d.DEPARTMENT_ID,也就是e和d有时可以省略。但是,只有当列名不相同时,才可省略。

3、表别名的意义:我为EMPLOYEES表定义了别名e,也就是在表名后加空格,然后再输入的字符,就是表的别名。DEPARTMENTS的别名是d。然后,表名.DEPARTMENT_ID就可以打为e.DEPARTMENT_ID或d.DEPARTMENT_ID。

4、针对错误:ORA-00918: column ambiguously defined。就是Oracle无法确定DEPARTMENT_ID的值来自于FROM后的哪一个表。这时,必须将表名加在列名前,明确告诉ORACLE,此列的值,来值于哪一个表。命令如下:


hr@OCM> select EMPLOYEE_ID,FIRST_NAME,e.DEPARTMENT_ID,DEPARTMENT_NAME
  2          from EMPLOYEES e,DEPARTMENTS d
  3     where e.DEPARTMENT_ID=d.DEPARTMENT_ID;

EMPLOYEE_ID FIRST_NAME           DEPARTMENT_ID DEPARTMENT_NAME
----------- -------------------- ------------- ------------------------------
        200 Jennifer                        10 Administration
        201 Michael                         20 Marketing
        202 Pat                             20 Marketing
        114 Den                             30 Purchasing
        119 Karen                           30 Purchasing
        115 Alexander                       30 Purchasing


5、附加其他条件:在WHERE后的连接条件,也是普通条件,完全可以和其他条件混合使用。比如,我想将EMPLOYEES和DEPARTMENTS连接显示,但只显示名字Karen这个人的信息。两个表的等值连接,条件是e.DEPARTMENT_ID=d.DEPARTMENT_ID,现在还要有一个条件是FIRST_NAME='Karen'。多个条件的组合,可以使用AND、OR,此处应该使用AND,因为WHERE后的两个条件,是且的关系。我们要显示的是e.DEPARTMENT_ID=d.DEPARTMENT_ID,并在此条件基础上,FIRST_NAME='Karen'的行,命令如下:


hr@OCM> select EMPLOYEE_ID,FIRST_NAME,e.DEPARTMENT_ID,DEPARTMENT_NAME
  2          from EMPLOYEES e,DEPARTMENTS d
  3     where e.DEPARTMENT_ID=d.DEPARTMENT_ID and FIRST_NAME='Karen';

EMPLOYEE_ID FIRST_NAME           DEPARTMENT_ID DEPARTMENT_NAME
----------- -------------------- ------------- ------------------------------
        119 Karen                           30 Purchasing
        146 Karen                           80 Sales


6、三个以上表的连接,有时可能会需要将多个表连接起来,比如上例的结果中,再加上雇员的职位信息(JOBS)。


hr@OCM> select EMPLOYEE_ID,FIRST_NAME,e.DEPARTMENT_ID,DEPARTMENT_NAME,JOB_TITLE
  2          from EMPLOYEES e,DEPARTMENTS d,JOBS j
  3     where e.DEPARTMENT_ID=d.DEPARTMENT_ID and e.JOB_ID=j.JOB_ID and FIRST_NAME='Karen';

EMPLOYEE_ID FIRST_NAME           DEPARTMENT_ID DEPARTMENT_NAME                JOB_TITLE
----------- -------------------- ------------- ------------------------------ -----------------------------------
        119 Karen                           30 Purchasing                     Purchasing Clerk
        146 Karen                           80 Sales                          Sales Manager


7、下面我们试验一个四表连接,在上面的结果中,再加上雇员的所在的城市(LOCATIONS)。


hr@OCM> select e.EMPLOYEE_ID,e.FIRST_NAME,e.DEPARTMENT_ID,d.DEPARTMENT_NAME,j.JOB_TITLE, l.CITY
  2          from EMPLOYEES e,DEPARTMENTS d,JOBS j ,LOCATIONS l
  3     where e.DEPARTMENT_ID=d.DEPARTMENT_ID and e.JOB_ID=j.JOB_ID and d.LOCATION_ID =l.LOCATION_ID  and FIRST_NAME='Karen';

EMPLOYEE_ID FIRST_NAME           DEPARTMENT_ID DEPARTMENT_NAME                JOB_TITLE                           CITY
----------- -------------------- ------------- ------------------------------ ----------------------------------- ------------------------------
        119 Karen                           30 Purchasing                     Purchasing Clerk                    Seattle
        146 Karen                           80 Sales                          Sales Manager                       Oxford


有些列占的字符位比较宽,格式不太好看,我们来设一下sqlplus环境


hr@OCM> col DEPARTMENT_NAME for a20
hr@OCM> col JOB_TITLE  for a20
hr@OCM> col CITY for a20
hr@OCM> select e.EMPLOYEE_ID,e.FIRST_NAME,e.DEPARTMENT_ID,d.DEPARTMENT_NAME,j.JOB_TITLE, l.CITY
  2          from EMPLOYEES e,DEPARTMENTS d,JOBS j ,LOCATIONS l
  3     where e.DEPARTMENT_ID=d.DEPARTMENT_ID and e.JOB_ID=j.JOB_ID and d.LOCATION_ID =l.LOCATION_ID  and FIRST_NAME='Karen';
EMPLOYEE_ID FIRST_NAME           DEPARTMENT_ID DEPARTMENT_NAME      JOB_TITLE            CITY
----------- -------------------- ------------- -------------------- -------------------- --------------------
        119 Karen                           30 Purchasing           Purchasing Clerk     Seattle
        146 Karen                           80 Sales                Sales Manager        Oxford

 

四、不等值连接
1、不等值连接与等值连接本质上没有不同,都是按一定的条件,将两个表某些行的列组合起来。只不过等值连接的条件,是A表中的甲列等于B表中的乙列。而不等值连接,连接条件不是相等。
建一个工资级别表:SALARY
100000至1000000间的,顶级工资
50000至99999间的,一级工资。
10000至49999间,二级工资。
5000至9999间的,三级工资。
800至4999间的,四级工资


hr@OCM> create table SALARY
  2  (
  3  CLASS_ID    NUMBER(2),
  4  CLASS_NAME VARCHAR2(10),
  5  MIN_SALARY  NUMBER(10,
  6 MAX_SALARY  NUMBER(10)) ;                                                                                                   );

Table created.

hr@OCM> insert into salary values(0,'顶级',100000,1000000);

1 row created.

hr@OCM> insert into salary values(1,'一级',50000,99999);

1 row created.

hr@OCM> insert into salary values(2,'二级',10000,49999);

1 row created.

hr@OCM> insert into salary values(3,'三级',5000,9999);

1 row created.

hr@OCM> insert into salary values(4,'四级',800,4999);

1 row created.

hr@OCM> commit;

Commit complete.


2、查找雇员的工资级别


hr@OCM> select e.EMPLOYEE_ID,e.FIRST_NAME, e.SALARY, s.CLASS_NAME,s.MIN_SALARY,s.MAX_SALARY
        from  EMPLOYEES e,SALARY s
 where e.SALARY  BETWEEN s.MIN_SALARY and s.MAX_SALARY;

EMPLOYEE_ID FIRST_NAME               SALARY CLASS_NAME MIN_SALARY MAX_SALARY
----------- -------------------- ---------- ---------- ---------- ----------
        132 TJ                         2100 四级              800       4999
        136 Hazel                      2200 四级              800       4999
    24 Kevin                       5800 三级             5000       9999
        169 Harrison                  10000 二级            10000      49999
        156 Janette                   10000 二级            10000      49999


Oracle取出EMPLOYEES表中第一行,和SALARY表中每一行的MIN_SALARY、MAX_SALARY相比较,满足条件的就组合在一起。依次类推。。。
这就是连接的过程,无论等值连接,还是不等值连接都是一样。取出一个表中的一行,按连接条件,和另一表的每一行比较,将满足连接条件行的列,组合到一起。再取出表中第二行,再和另一表每一行比较一遍,将满足连接条件行的列,组合到一起,等等。这就是连接命令的步骤。

3、再试验一个等值连接和不等值连接的综合应用,在此结果集基础上,增加部门信息(DEPARTMENTS)


hr@OCM> hr@OCM> select e.EMPLOYEE_ID,e.FIRST_NAME,d.DEPARTMENT_NAME, e.SALARY, s.CLASS_NAME,s.MIN_SALARY,s.MAX_SALARY
  2  from  EMPLOYEES e,SALARY s,DEPARTMENTS d
  3  where e.DEPARTMENT_ID=d.DEPARTMENT_ID and e.SALARY  BETWEEN s.MIN_SALARY and s.MAX_SALARY;


结果就不显示了。
总之吧,连接的条件,也是一个普通的条件,我们可以使用AND、OR逻辑运算符,将各种连接条件、各种其他条件,组合到一起使用。

 

五、外连接
1、无论等值连接,还是不等值连接。都是只将两个表中满足条件的行组合到一起,这种连接方式,也叫内连接。而外连接,则是在组合满足条件行的基础上,再把两个表的某一个表中不满足连接条件的行也显示出来。这就是外连接。
先来看一个等值内连接的例子:


gyj@OCM> select * from t1;

        ID NAME           SALARY HIRE_DATE DEPARTMENT_ID
---------- ---------- ---------- --------- -------------
         2 gyj2             8000 21-FEB-13             2
         3 gyj3            10000 21-FEB-13             2
         4 gyj4            15000 21-FEB-13             2
         5 gyj5                0 21-FEB-13             3
         7 gyj7            12000 21-FEB-13             3
         6 gyj6            12000 21-FEB-13             3
         1 gyj1            20000 21-FEB-13             1
         8 gyj8                  21-FEB-13             4
         9 Joe             22000 21-FEB-13             4
        10 Tom             28000 21-FEB-13             4

10 rows selected.

gyj@OCM>  select * from d1;

DEPARTMENT_ID DEPARTMENT_NAME                MANAGER_ID LOCATION_ID
------------- ------------------------------ ---------- -----------
            1 Administration                        200        1700
            2 Marketing                             201        1800
            3 Purchasing                            114        1700

3 rows selected.


2、单表显示t1表10条记录,d1表3条记录,对t1表和d1表做内连接,操作结果如下:


gyj@OCM> select id,name,salary,department_name from t1,d1 where t1.department_id=d1.department_id;

        ID NAME           SALARY DEPARTMENT_NAME
---------- ---------- ---------- ------------------------------
         2 gyj2             8000 Marketing
         3 gyj3            10000 Marketing
         4 gyj4            15000 Marketing
         5 gyj5                0 Purchasing
         7 gyj7            12000 Purchasing
         6 gyj6            12000 Purchasing
         1 gyj1            20000 Administration

7 rows selected.


两个表中,满足条件行的列组合到一起,结果一共有7行,在内连接中,这样不符合条件的行,是显示不出来的。如果不仅要显示满足条件的行,还要把t1表中,不满足条件的行也要显示出来,对上面的语句修改后,操作如下:


gyj@OCM> select id,name,salary,department_name from t1,d1 where t1.department_id=d1.department_id(+);

        ID NAME           SALARY DEPARTMENT_NAME
---------- ---------- ---------- ------------------------------
         1 gyj1            20000 Administration
         4 gyj4            15000 Marketing
         3 gyj3            10000 Marketing
         2 gyj2             8000 Marketing
         6 gyj6            12000 Purchasing
         7 gyj7            12000 Purchasing
         5 gyj5                0 Purchasing
        10 Tom             28000
         9 Joe             22000
         8 gyj8

10 rows selected.


结果在d1表中和DEPARTMENT_NAME对应的行显示为NULL。因为在d1表中,没有DEPARTMENT_id为4的行的相关信息。因此,只有显示为空了。d.department_id(+)中(+)就是外连接的意思了。它的意义,就是在d1表中补进去一些空值。

2、、外连接的注意事项:
 (1)外连接操作符(+),只能出现在表达式一侧—缺少信息的一侧,但不能两边都放。
 (2)一个条件中,如果有了外连接,就不能再出现OR 操作符。还有,IN操作符是以OR为基础的,不能用OR,也就不能用IN。否则,将会报出错误:


gyj@OCM> select id,name,salary,department_name from t1,d1 where t1.department_id=d1.department_id(+) or id=1;
         select id,name,salary,department_name from t1,d1 where t1.department_id=d1.department_id(+) or id=1
 
                                                                                 *
ERROR at line 1:
ORA-01719: outer join operator (+) not allowed in operand of OR or IN

 

六、自连接
1、顾名思义,也就是自己连接自己,就是自连接。自己为什么要和自己连接,看下面的一个例子。
2、对雇员表,我只想显示雇员表中的雇员编号,姓名,以及领导的姓名


hr@OCM> select * from employees;

EMPLOYEE_ID FIRST_NAME           LAST_NAME                 EMAIL                     PHONE_NUMBER         HIRE_DATE JOB_ID           SALARY COMMISSION_PCT MANAGER_ID DEPARTMENT_ID
----------- -------------------- ------------------------- ------------------------- -------------------- --------- ---------- ---------- -------------- ---------- -------------
        200 Jennifer             Whalen                    JWHALEN                   515.123.4444         17-SEP-03 AD_ASST            4400                       101            10
        201 Michael              Hartstein                 MHARTSTE                  515.123.5555         17-FEB-04 MK_MAN            13000                       100            20
        202 Pat                  Fay                       PFAY                      603.123.6666         17-AUG-05 MK_REP             6000                       201            20
        203 Susan                Mavris                    SMAVRIS                   515.123.7777         07-JUN-02 HR_REP             6500                       101            40

hr@OCM> select a.EMPLOYEE_ID,a.FIRST_NAME,b.FIRST_NAME MANAGER_NAME from employees a,employees b where a.manager_id=b.employee_id;

EMPLOYEE_ID FIRST_NAME           MANAGER_NAME
----------- -------------------- --------------------
        173 Sundita              Gerald
        172 Elizabeth            Gerald
        171 William              Gerald
 100 Steven


上边的例子中,为EMPLOYEES表分别起别名A和B。这个时候,对于Oracle来讲,就没有EMPLOYEES表了,只有A表和B表。这个连接,是A表和B表间的连接。其实A表和B表都是EMPLOYEES表,因此,这个连接是EMPLOYEES表和EMPLOYEES表的连接,也就是自连接。

2、Steven是公司的最高领导,他没有领导,按我们上面的自连接条件,他也不被显示,我们可以使用外连接解决这个问题:


hr@OCM> select a.EMPLOYEE_ID,a.FIRST_NAME,b.FIRST_NAME MANAGER_NAME from employees a,employees b where a.manager_id=b.employee_id(+);

EMPLOYEE_ID FIRST_NAME           MANAGER_NAME
----------- -------------------- --------------------
        173 Sundita              Gerald
        172 Elizabeth            Gerald
        171 William              Gerald
 100 Steven


3、显示结果,Steven的领导为NULL。更进一步的,假设Steven是总经理,我想将领导姓名列为NULL的显示为总经理,这可以通过NVL函数来实现:


hr@OCM> select a.EMPLOYEE_ID,a.FIRST_NAME,nvl(b.FIRST_NAME,'总经理') MANAGER_NAME from employees a,employees b where a.manager_id=b.employee_id(+);
EMPLOYEE_ID FIRST_NAME           MANAGER_NAME
----------- -------------------- --------------------
        173 Sundita              Gerald
        172 Elizabeth            Gerald
        171 William              Gerald
 100 Steven               总经理


好了,自连接我们就接到这里。基本的连接格式,其实就这么多了。我们当现在为止,所讲的连接语法,都是Oracle自己提供的。


*****************************
   SQL99的连接
******************************
在1999年,由美国国家标准协会(ANSI)和国际标准化组织(ISO)共同批准了一个有关SQL语句的标准,被称为SQL99。在SQL99中,有关连接的语法,和Oracle中原有的连接语法格式并不一样。Oracle为了使自己的命令兼容SQL99,除了这些原有的连接语法外,又定义了一套和SQL99标准中,一模一样的连接语法。下面,我们来学习一下SQL99中的连接。

 

一、笛卡尔乘积
又名:交叉连接。在非SQL99中,SELECT * FROM employees,departments 就是笛卡尔乘积了。只要你省略连接条件,连接就是笛卡尔乘积。
在SQL99中,它的语法形式是:表1  CROSS JOIN  表2。如下例:


hr@OCM> select * from employees cross join departments;


employees cross join departments 的意义就是:employees交叉连接到 departments。

 

二、等值连接
语法格式:表1  JOIN  表2  ON  连接条件。看下面的例子:


hr@OCM> select EMPLOYEE_ID,FIRST_NAME,DEPARTMENT_NAME from employees e join departments d on e.DEPARTMENT_ID=d.DEPARTMENT_ID;

EMPLOYEE_ID FIRST_NAME           DEPARTMENT_NAME
----------- -------------------- ------------------------------
        200 Jennifer             Administration
        201 Michael              Marketing
        202 Pat                  Marketing
        114 Den                  Purchasing


等价的非SQL99形式:
select EMPLOYEE_ID,FIRST_NAME,DEPARTMENT_NAME from employees e,departments d where e.DEPARTMENT_ID=d.DEPARTMENT_ID;
基本上是大同小异的。多了一个JOIN,把连接连接从Where中,挪到了ON之后。
我们要明白的是SQL99和ORACLE本身的连接,作用是完全一样的,只不过语法格式不所不同。SQL99本来就只是一个标准,它只规定了命令的语法格式。
在SQL99的连接中,我们一样可以使用WHERE增加一些条件,比如,我只想显示Michael的信息:


hr@OCM> select EMPLOYEE_ID,FIRST_NAME,DEPARTMENT_NAME from employees e join departments d on e.DEPARTMENT_ID=d.DEPARTMENT_ID where e.FIRST_NAME='Michael';

EMPLOYEE_ID FIRST_NAME           DEPARTMENT_NAME
----------- -------------------- ------------------------------
        201 Michael              Marketing
        134 Michael              Shipping


ON在连接中,也是代表条件的开始,作用和WHERE一样,我们也可以把WHERE中的条件,放在ON中:


hr@OCM> select EMPLOYEE_ID,FIRST_NAME,DEPARTMENT_NAME from employees e join departments d on e.DEPARTMENT_ID=d.DEPARTMENT_ID and e.FIRST_NAME='Michael';

EMPLOYEE_ID FIRST_NAME           DEPARTMENT_NAME
----------- -------------------- ------------------------------
        201 Michael              Marketing
        134 Michael              Shipping


这条语句的效果和上面的语句一样。

 

三、多表连接
我们前面做过个例子,这个例子的意义,我不再讲了,非SQL99的语句如下,可以参考前面的例子:


hr@OCM> select EMPLOYEE_ID,FIRST_NAME,e.DEPARTMENT_ID,DEPARTMENT_NAME,JOB_TITLE
  2          from EMPLOYEES e,DEPARTMENTS d,JOBS j
  3     where e.DEPARTMENT_ID=d.DEPARTMENT_ID and e.JOB_ID=j.JOB_ID and FIRST_NAME='Karen';

EMPLOYEE_ID FIRST_NAME           DEPARTMENT_ID DEPARTMENT_NAME                JOB_TITLE
----------- -------------------- ------------- ------------------------------ -----------------------------------
        119 Karen                           30 Purchasing                     Purchasing Clerk
        146 Karen                           80 Sales                          Sales Manager


SQL99中的多表连接是:


hr@OCM> select EMPLOYEE_ID,FIRST_NAME,e.DEPARTMENT_ID,DEPARTMENT_NAME,JOB_TITLE
  2          from EMPLOYEES e join DEPARTMENTS d on e.DEPARTMENT_ID=d.DEPARTMENT_ID join JOBS j
  3          on e.JOB_ID=j.JOB_ID and FIRST_NAME='Karen';

EMPLOYEE_ID FIRST_NAME           DEPARTMENT_ID DEPARTMENT_NAME                JOB_TITLE
----------- -------------------- ------------- ------------------------------ -----------------------------------
        119 Karen                           30 Purchasing                     Purchasing Clerk
        146 Karen                           80 Sales                          Sales Manager


也就是e连接到d,条件是 e.DEPARTMENT_ID=d.DEPARTMENT_ID ,然后e、d连接的结果再连接到j,条件是e.JOB_ID=j.JOB_ID。

 

四、不等值连接
 SQL99中不等值连接仍然只是把非SQL99中WHERE后的条件换换位置:


hr@OCM>  select e.EMPLOYEE_ID,e.FIRST_NAME, e.SALARY, s.CLASS_NAME,s.MIN_SALARY,s.MAX_SALARY
  2          from  EMPLOYEES e join SALARY s
  3     on e.SALARY  BETWEEN s.MIN_SALARY and s.MAX_SALARY;


下面是等价的非SQL99的不等值连接,这是我们上面所做过的一个例子。
select e.EMPLOYEE_ID,e.FIRST_NAME, e.SALARY, s.CLASS_NAME,s.MIN_SALARY,s.MAX_SALARY
        from  EMPLOYEES e,SALARY s
 where e.SALARY  BETWEEN s.MIN_SALARY and s.MAX_SALARY;

 

五、外连接
SQL99中的外连接,又分为三种:LEFT(左连接)、RIGHT(右连接)和FULL OUTER(全连接),其中全连接是非SQL99中没有的功能。下面我们先从左、右连接开始
1.LEFT 左连接
 语法形式为:表1  left outer join  表2  on  连接条件。
 我们仍然把非SQL99中的例子调过来,如下的是非SQL99中的外连接


gyj@OCM>select id,name,salary,department_name from t1,d1 where t1.department_id=d1.department_id(+);


下面是等价的SQL99中的左连接


gyj@OCM> select id,name,salary,department_name from t1 left outer join d1 on t1.department_id=d1.department_id;

        ID NAME           SALARY DEPARTMENT_NAME
---------- ---------- ---------- ------------------------------
         1 gyj1            20000 Administration
         4 gyj4            15000 Marketing
         5 gyj5                0 Purchasing
        10 Tom             28000
         9 Joe             22000


左连接中的“左”的意思,就是以left outer join左边的表为准,无论是否满足连接条件,left outer join左边表的行都会被显示。
通常OUTER关键字可以省略,如:select t.id,t.name,t.salary,d.department_name from t1 t left outer join d1 d on t.department_id=d.department_id;
这样意思更明确,t1 t left outer join d1 d on t.department_id=d.department_id;,也就是t左连接到d,条件是t.department_id=d.department_id。

2.RIGHT 右连接
只要将刚才命令中两个表的位置互换一下,很容易构造一个右连接的命令:


gyj@OCM> select id,name,salary,department_name from d1 right outer join t1 on t1.department_id=d1.department_id;

        ID NAME           SALARY DEPARTMENT_NAME
---------- ---------- ---------- ------------------------------
         1 gyj1            20000 Administration
         4 gyj4            15000 Marketing
         5 gyj5                0 Purchasing
        10 Tom             28000
         9 Joe             22000


 d1 right outer join t1 on t1.department_id=d1.department_id; :也就是d1右连接到t1,条件t1.department_id=d1.department_id;。
右连接,就是以right outer join右边的表为主,显示它的全部行。

3.FULL OUTER 全连接
全连接是两个表的所有行都显示。为了演示效果,你删除部门id号为3的员工信息


gyj@OCM> delete from t1 where department_id=3;

3 rows deleted.

gyj@OCM> commit;

Commit complete.


全连接的使用,非常简单:


gyj@OCM> select id,name,salary,department_name from t1 full outer join d1 on t1.department_id=d1.department_id;

        ID NAME           SALARY DEPARTMENT_NAME
---------- ---------- ---------- ------------------------------
         2 gyj2             8000 Marketing
         3 gyj3            10000 Marketing
         4 gyj4            15000 Marketing
         1 gyj1            20000 Administration
         8 gyj8
         9 Joe             22000
        10 Tom             28000
                                 Purchasing


两个表中的行,都被显示出来了。
这样的全连接,是原Oracle中的外连接中,所没有的功能。原Oracle的外连接形式是(+),它有一个使用限制,就是不能在条件的两端都使用。

 

六、自然连接
当两个表中的相关列的列名、数据类型一致,就是T1(雇员)表中的DEPARTMENT_ID列和D1(部门)表的DEPARTMENT_ID列,列名、类型都一致。在以这两列为连接条件,进行等值连接时,可以使用自然连接。自然连接再输入条件 :e.DEPARTMENT_ID=d.DEPARTMENT_ID。
它的语法是:表1  NATURAL JOIN   表2 。
ORACLE自然为以表1和表2中所有列名、数据类型一致的列,作为条件,进行等值连接。注意自然连接,只能进行等值连接。
看如下例子:


gyj@OCM> select id,name,salary,department_name from  t1 NATURAL JOIN d1;

        ID NAME           SALARY DEPARTMENT_NAME
---------- ---------- ---------- ------------------------------
         2 gyj2             8000 Marketing
         3 gyj3            10000 Marketing
         4 gyj4            15000 Marketing
         1 gyj1            20000 Administration


自然连接的限制是,不能在一样的列名前加表名:


gyj@OCM> select t1.department_id,t1.id,t1.name,t1.salary,d1.department_name from  t1 NATURAL JOIN d1;
select t.department_id,t1.id,t1.name,t1.salary,d1.department_name from  t1 NATURAL JOIN d1
       *
ERROR at line 1:
ORA-00904: "T1"."DEPARTMENT_ID": invalid identifier


T1.DEPARTMENT_ID,说明DEPARTMENT_ID列是T1表中DEPARTMENT_ID列。因为两个表中都有DEPARTMENT_ID列,不在列名前用表名作进一步的说明,命令执行将会出错。但这是对其他的连接。对自然连接,可以不用在相同的列前加表名:


gyj@OCM> select department_id,t1.id,t1.name,t1.salary,d1.department_name from  t1 NATURAL JOIN d1;

DEPARTMENT_ID         ID NAME           SALARY DEPARTMENT_NAME
------------- ---------- ---------- ---------- ------------------------------
            2          2 gyj2             8000 Marketing
            2          3 gyj3            10000 Marketing
            2          4 gyj4            15000 Marketing
            1          1 gyj1            20000 Administration


在普能的连接中,两表中名字相同的列,如果不加表名,命令将出错:


gyj@OCM> select department_id,t1.id,t1.name,t1.salary,d1.department_name from  t1  JOIN d1 on t1.department_id=d1.department_id;
select department_id,t1.id,t1.name,t1.salary,d1.department_name from  t1  JOIN d1 on t1.department_id=d1.department_id
       *
ERROR at line 1:
ORA-00918: column ambiguously defined
Oracle不知道该到t1和d1这两个表中的那个表中读取department_id的数据。

 

七、USING连接
USING连接和自然连接基本相同,它以两个表中的同名列为条件,进行等值连接。和自然连接不同的是,它不要求同名列的数据类型相同。它的语法如下:
表1  JOIN  表2  using(同名列);


gyj@OCM> select department_id,id,name,salary,department_name from  t1  JOIN d1 using(department_id);

DEPARTMENT_ID         ID NAME           SALARY DEPARTMENT_NAME
------------- ---------- ---------- ---------- ------------------------------
            2          2 gyj2             8000 Marketing
            2          3 gyj3            10000 Marketing
            2          4 gyj4            15000 Marketing
            1          1 gyj1            20000 Administration


和自然连接一样,列名前不要加表名。

Oracle中的连接就这么多了,连接的目的,是将多个表的列组合起来,输出更全面,更详细的信息。连接我们就讲到这里。





**********本博客所有内容均为原创,如有转载请注明作者和出处!!!**********
Name:    guoyJoe

QQ:        252803295

Email:    oracledba_cn@hotmail.com

Blog:      http://blog.csdn.net/guoyJoe

ITPUB:   http://www.itpub.net/space-uid-28460966.html

OCM:     http://education.oracle.com/education/otn/YGuo.HTM
 _____________________________________________________________
加群验证问题:哪些SGA结构是必需的,哪些是可选的?否则拒绝申请!!!

答案在:http://blog.csdn.net/guoyjoe/article/details/8624392

Oracle@Paradise  总群:127149411

Oracle@Paradise No.1群:177089463(已满)

Oracle@Paradise No.2群:121341761

Oracle@Paradise No.3群:140856036


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值