zoukankan      html  css  js  c++  java
  • Oracle SQL多表查询

    曾经一段时间我对oracle的多表查询搞的云里雾里,究其原因:oracle自己的语法和SQL国际标准语法混用。此文章仅适合oracle 菜鸟,老鸟直接飞过…

    多表连接类型(SQL 1999标准)

    Cross joins

    Natural joins

    USING clause

    Full (or two-sided) outer joins

    Arbitrary join conditions for outer joins

    SQL1999语法:

    SELECT table1.column, table2.column

    FROM table1

    [CROSS JOIN table2] |

    [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];

    语法解释:

    table1.column --指明从中检索数据的表和列

    CROSS JOIN --返回两个表的笛卡尔集

    NATURAL JOIN --根据相同的列名连接两个表

    JOIN table

    USING column_name --根据列名执行等值连接

    JOIN table ON

    table1.column_name --根据ON 子句中的条件执行等值连接

    = table2.column_name

    LEFT/RIGHT/FULL OUTER

    一般来说,从数据显示方式来讲,分为内连接和外连接

    内连接:只返回满足连接条件的数据。

    外连接:除了返回满足连接条的行以外,还返回左(右)表中,不满足条件的行,

    称为左(右)连接

    演示,主要以SQL标准为主,oracle 写法作对比。示例用户为scott、HR

    解锁这两个用户语句:

    alter user scott identified by tiger account unlock;

    alter user hr identified by hr account unlock;

    内连接

    --Oracle的写法

    select empno,ename,sal,dname,loc from emp,dept

    where emp.deptno=dept.deptno;

    -- SQL 99标准的写法

    select empno,ename,job,sal,dept.deptno,dname,loc

    from emp join dept on emp.deptno=dept.deptno;

    或把join改为inner join

    外连接

    左外连接

    Oracle 外连接语法:

    SELECT table1.column, table2.column --右外连接

    FROM table1, table2

    WHERE table1.column(+) = table2.column;

    SELECT table1.column, table2.column --左外连接

    FROM table1, table2

    WHERE table1.column = table2.column(+);

    SQL 1999标准外连接语法见上面SQL1999语法

    --Oracle的写法

    外连接的符号是(+),(+)要放在字段名后。(+)对面的那个表,会全部显示。

    左外连接时,加号在等号的右边

    SQL> select d.dname,e.ename,e.deptno

    from dept d,emp e

    where d.deptno = e.deptno(+)

    order by d.deptno;

    DNAME ENAME DEPTNO

    -------------- ---------- ------

    ACCOUNTING CLARK 10

    ACCOUNTING KING 10

    ACCOUNTING MILLER 10

    RESEARCH JONES 20

    RESEARCH FORD 20

    RESEARCH ADAMS 20

    RESEARCH SMITH 20

    RESEARCH SCOTT 20

    SALES WARD 30

    SALES TURNER 30

    SALES ALLEN 30

    SALES JAMES 30

    SALES BLAKE 30

    SALES MARTIN 30

    OPERATIONS

    15 rows selected

    -- SQL 99标准的写法接

    SQL> select d.dname,e.ename,e.deptno

    from dept d

    left join emp e

    on d.deptno = e.deptno

    order by d.deptno;

    DNAME ENAME DEPTNO

    -------------- ---------- ------

    ACCOUNTING CLARK 10

    ACCOUNTING KING 10

    ACCOUNTING MILLER 10

    RESEARCH JONES 20

    RESEARCH FORD 20

    RESEARCH ADAMS 20

    RESEARCH SMITH 20

    RESEARCH SCOTT 20

    SALES WARD 30

    SALES TURNER 30

    SALES ALLEN 30

    SALES JAMES 30

    SALES BLAKE 30

    SALES MARTIN 30

    OPERATIONS

    15 rows selected

    右外连接

    --oracle的写法

    SQL> select empno, ename, job, sal, dept.deptno, dname, loc

    2 from emp, dept

    3 where emp.deptno(+) = dept.deptno;

    EMPNO ENAME JOB SAL DEPTNO DNAME LOC

    ----- ---------- --------- --------- ------ -------------- -------------

    7782 CLARK MANAGER 2450.00 10 ACCOUNTING NEW YORK

    7839 KING PRESIDENT 5000.00 10 ACCOUNTING NEW YORK

    7934 MILLER CLERK 1300.00 10 ACCOUNTING NEW YORK

    7566 JONES MANAGER 2975.00 20 RESEARCH DALLAS

    7902 FORD ANALYST 3000.00 20 RESEARCH DALLAS

    7876 ADAMS CLERK 1100.00 20 RESEARCH DALLAS

    7369 SMITH CLERK 800.00 20 RESEARCH DALLAS

    7788 SCOTT ANALYST 3000.00 20 RESEARCH DALLAS

    7521 WARD SALESMAN 1250.00 30 SALES CHICAGO

    7844 TURNER SALESMAN 1500.00 30 SALES CHICAGO

    7499 ALLEN SALESMAN 1600.00 30 SALES CHICAGO

    7900 JAMES CLERK 950.00 30 SALES CHICAGO

    7698 BLAKE MANAGER 2850.00 30 SALES CHICAGO

    7654 MARTIN SALESMAN 1250.00 30 SALES CHICAGO

    40 OPERATIONS BOSTON

    15 rows selected

    --SQL1999标准写法

    SQL> select empno, ename, job, sal, dept.deptno, dname, loc

    2 from emp

    3 right join dept

    4 on emp.deptno = dept.deptno;

    EMPNO ENAME JOB SAL DEPTNO DNAME LOC

    ----- ---------- --------- --------- ------ -------------- -------------

    7782 CLARK MANAGER 2450.00 10 ACCOUNTING NEW YORK

    7839 KING PRESIDENT 5000.00 10 ACCOUNTING NEW YORK

    7934 MILLER CLERK 1300.00 10 ACCOUNTING NEW YORK

    7566 JONES MANAGER 2975.00 20 RESEARCH DALLAS

    7902 FORD ANALYST 3000.00 20 RESEARCH DALLAS

    7876 ADAMS CLERK 1100.00 20 RESEARCH DALLAS

    7369 SMITH CLERK 800.00 20 RESEARCH DALLAS

    7788 SCOTT ANALYST 3000.00 20 RESEARCH DALLAS

    7521 WARD SALESMAN 1250.00 30 SALES CHICAGO

    7844 TURNER SALESMAN 1500.00 30 SALES CHICAGO

    7499 ALLEN SALESMAN 1600.00 30 SALES CHICAGO

    7900 JAMES CLERK 950.00 30 SALES CHICAGO

    7698 BLAKE MANAGER 2850.00 30 SALES CHICAGO

    7654 MARTIN SALESMAN 1250.00 30 SALES CHICAGO

    40 OPERATIONS BOSTON

    15 rows selected

    全连接

    --SQL1999标准写法

    SQL> select empno, ename, job, sal, d.deptno, dname, loc

    2 from emp e

    3 full join dept d

    4 on e.deptno = d.deptno;

    EMPNO ENAME JOB SAL DEPTNO DNAME LOC

    ----- ---------- --------- --------- ------ -------------- -------------

    7369 SMITH CLERK 800.00 20 RESEARCH DALLAS

    7499 ALLEN SALESMAN 1600.00 30 SALES CHICAGO

    7521 WARD SALESMAN 1250.00 30 SALES CHICAGO

    7566 JONES MANAGER 2975.00 20 RESEARCH DALLAS

    7654 MARTIN SALESMAN 1250.00 30 SALES CHICAGO

    7698 BLAKE MANAGER 2850.00 30 SALES CHICAGO

    7782 CLARK MANAGER 2450.00 10 ACCOUNTING NEW YORK

    7788 SCOTT ANALYST 3000.00 20 RESEARCH DALLAS

    7839 KING PRESIDENT 5000.00 10 ACCOUNTING NEW YORK

    7844 TURNER SALESMAN 1500.00 30 SALES CHICAGO

    7876 ADAMS CLERK 1100.00 20 RESEARCH DALLAS

    7900 JAMES CLERK 950.00 30 SALES CHICAGO

    7902 FORD ANALYST 3000.00 20 RESEARCH DALLAS

    7934 MILLER CLERK 1300.00 10 ACCOUNTING NEW YORK

    40 OPERATIONS BOSTON

    15 rows selected

    自连接

    把表自身的镜像当成另外一个表

    --oracle 的写法

    SQL> select e.ename || ' works for ' || m.ename

    2 from emp e, emp m

    3 where e.empno = m.mgr;

    E.ENAME||'WORKSFOR'||M.ENAME

    -------------------------------

    JONES works for FORD

    JONES works for SCOTT

    BLAKE works for TURNER

    BLAKE works for ALLEN

    BLAKE works for WARD

    BLAKE works for JAMES

    BLAKE works for MARTIN

    CLARK works for MILLER

    SCOTT works for ADAMS

    KING works for BLAKE

    KING works for JONES

    KING works for CLARK

    FORD works for SMITH

    13 rows selected

    --SQL1999标准的写法

    SQL> select e.ename || ' works for ' || m.ename

    2 from emp e

    3 join emp m

    4 on e.empno = m.mgr;

    E.ENAME||'WORKSFOR'||M.ENAME

    -------------------------------

    JONES works for FORD

    JONES works for SCOTT

    BLAKE works for TURNER

    BLAKE works for ALLEN

    BLAKE works for WARD

    BLAKE works for JAMES

    BLAKE works for MARTIN

    CLARK works for MILLER

    SCOTT works for ADAMS

    KING works for BLAKE

    KING works for JONES

    KING works for CLARK

    FORD works for SMITH

    13 rows selected

    自然连接

    以两个表具有相同的字段的所有列为基础,可采用自然连接(natural join)

    它将选择两个表中那些在所有匹配的列中值相等的行。

    如果列具有相同的名称,但数据类型能够不同,则会报错。

    --SQL1999标准写法

    SQL> select empno, ename, job, sal, deptno, dname, loc

    2 from emp natural

    3 join dept;

    EMPNO ENAME JOB SAL DEPTNO DNAME LOC

    ----- ---------- --------- --------- ------ -------------- -------------

    7782 CLARK MANAGER 2450.00 10 ACCOUNTING NEW YORK

    7839 KING PRESIDENT 5000.00 10 ACCOUNTING NEW YORK

    7934 MILLER CLERK 1300.00 10 ACCOUNTING NEW YORK

    7566 JONES MANAGER 2975.00 20 RESEARCH DALLAS

    7902 FORD ANALYST 3000.00 20 RESEARCH DALLAS

    7876 ADAMS CLERK 1100.00 20 RESEARCH DALLAS

    7369 SMITH CLERK 800.00 20 RESEARCH DALLAS

    7788 SCOTT ANALYST 3000.00 20 RESEARCH DALLAS

    7521 WARD SALESMAN 1250.00 30 SALES CHICAGO

    7844 TURNER SALESMAN 1500.00 30 SALES CHICAGO

    7499 ALLEN SALESMAN 1600.00 30 SALES CHICAGO

    7900 JAMES CLERK 950.00 30 SALES CHICAGO

    7698 BLAKE MANAGER 2850.00 30 SALES CHICAGO

    7654 MARTIN SALESMAN 1250.00 30 SALES CHICAGO

    14 rows selected

    使用using子句创建连接

    如果几个列具有相同的名称,但是数据类型不匹配,那么可以使用using子句来修改natural join子句以指定要用于等值连接的列,在多个列匹配时,使用using 子句只匹配一个列,在引用列中不要使用表名或别名。natural join 和using 子句是互不相容的。

    SELECT l.city, d.department_name

    FROM locations l JOIN departments d USING (location_id)

    WHERE location_id = 1400;

    --下面的语句无效,因为where 子句中限定了location_id为d. location_id

    SELECT l.city, d.department_name

    FROM locations l JOIN departments d USING (location_id)

    WHERE d.location_id = 1400;

    ORA-25154: column part of USING clause cannot have qualifier

    注意:两个表中名称相同的列在使用时不能有任何限定符,这一限制同样适用natural join

    cross join 实现交叉连接

    交叉连接产生的结果集也就是笛卡尔乘积

    --oracle 的写法

    select empno, ename, dname

    from emp,dept;

    在oracle语法中直接from两张表就是cross join

    --SQL1999标准写法

    select empno, ename, dname

    from emp

    cross join dept;

    等值连接时增加条件

    上述的多表连接都是等值连接(最常用),等值连接后面还可以添加限定条件。

    --oracle 的写法

    select e.empno, e.ename, d.dname

    from emp e, dept d

    where d.deptno = e.deptno

    and e.ename = 'SCOTT';

    --SQL1999标准的写法

    select e.empno, e.ename, d.dname

    from emp e

    inner join dept d

    on d.deptno = e.deptno

    and e.ename = 'SCOTT';

    非等值连接

    --oracle的写法

    select ename, sal, grade

    from emp, salgrade

    where sal between losal and hisal

    and emp.deptno = 20;

    --SQL1999标准写法

    select e.ename, e.sal, s.grade

    from emp e

    join salgrade s

    on e.sal between losal and hisal

    and e.deptno = 20;

    总结

    Oracle的语法还是比较人性化的,除了左外连接和右外连接。如果想使代码简单明了,使用oracle的语法,如果想使写出的代码兼容性比较好(可能会移植到DB2等),尽量使用SQL标准语法。

    详细信息请参考oracle 官方文档

    Oracle® Database

    SQL Language Reference

    11g Release 2 (11.2)

    E17118-04

    9 SQL Queries and Subqueries 部分

  • 相关阅读:
    Ubuntu 安装 NTP 服务
    Packer 如何将 JSON 的配置升级为 HCL2
    WinRM 如何设置 TrustedHosts
    Windows 10 如何设置网络属性为私有
    Windows 使用 PowerShell 来管理另外一台 Windows 机器
    Windows PowerShell ISE 是什么和 PowerShell 有什么区别
    Spring事务传播属性和隔离级别
    @SpringBootApplication(exclude={DataSourceAutoConfiguration.class})注解作用
    杂文 | 如何在演讲中讲个好故事
    2.2 思考框架:什么样的代码才是高效的代码
  • 原文地址:https://www.cnblogs.com/AlbertCQY/p/3003471.html
Copyright © 2011-2022 走看看