PL/SQL学习五

18. 连接查询
   连接查询是指基于多个表或视图的查询。
   当使用多个表进行连接查询的时候:
   1.需要在FROM后面指定两个或两个以上的表
   2.在SELECT时,列名需要加上表名作为前缀
   3.需要在WHERE内指定两表或多表的连接条件,如不指定则视为笛卡尔积(A表记录条数xB表记录条数)
   示例:

SQL> SELECT e.ename,e.sal,d.dname
  2  FROM emp e,dept d
  3  WHERE e.deptno=d.deptno
  4  AND e.deptno=10;

ENAME             SAL DNAME
---------- ---------- ------------
CLARK            2450 ACCOUNTING
KING             5000 ACCOUNTING
MILLER           1300 ACCOUNTING


 

--使用BETWEEN...AND,emp表的sal在b的losal和hisal范围内

SQL> SELECT e.ename,e.sal,b.grade
  2  FROM emp e,salgrade b
  3  WHERE e.sal BETWEEN b.losal AND b.hisal;

ENAME             SAL      GRADE
---------- ---------- ----------
SMITH             800          1
JAMES             950          1
ADAMS            1100          1
MARTIN           1250          2
WARD             1250          2
MILLER           1300          2
TURNER           1500          3
ALLEN            1600          3
CLARK            2450          4
BLAKE            2850          4
JONES            2975          4
FORD             3000          4
SCOTT            3200          5
KING             5000          5

 

   --自连接(自己连接自己,注意表一定要用别名),显示BLAKE的上级领导
SQL> SELECT manager.ename FROM emp manager,emp worker
  2  WHERE manager.empno=worker.mgr
  3  AND worker.ename='BLAKE';

ENAME
----------
KING


   18.1 内、外连接查询
      内连接查询只返回满足连接条件的记录;而外连接不仅会返回满足连接条件的所有记录,还返回不满足连接条件的
      记录。在oracle 9i之前,连接语法都在WHERE中指定,9i之后,可以在FROM子句中指定连接语法。
      INNER JOIN:内连接
      内连接返回满足连接条件的所有记录。默认的=连接就是属于内连接。

SQL> SELECT a.dname, b.ename FROM dept a,emp b
  2  WHERE a.deptno=b.deptno AND a.deptno=30;
 
DNAME          ENAME
-------------- ----------
SALES          ALLEN
SALES          WARD
SALES          MARTIN
SALES          BLAKE
SALES          TURNER
SALES          JAMES
 
6 rows selected

-- 改写为INNER JOIN形式如下:
SQL> SELECT a.dname,b.ename FROM dept a
  2  INNER JOIN emp b
  3  ON a.deptno=b.deptno AND a.deptno=30;
 
DNAME          ENAME
-------------- ----------
SALES          ALLEN
SALES          WARD
SALES          MARTIN
SALES          BLAKE
SALES          TURNER
SALES          JAMES


      LEFT JOIN: 左外连接
      左外连接,不仅可以返回满足连接条件的所有记录,而且还会返回不满足连接条件的连接操作符左边表
      的其他行,如:

--请对比上面的内连接
SQL> SELECT a.dname,b.ename 
  2  FROM dept a
  3  LEFT JOIN emp b
  4  ON a.deptno=b.deptno AND a.deptno=30;
 
DNAME          ENAME
-------------- ----------
SALES          ALLEN
SALES          WARD
SALES          MARTIN
SALES          BLAKE
SALES          TURNER
SALES          JAMES
OPERATIONS     
RESEARCH       
ACCOUNTING     
 
9 rows selected



      RIGHT JOIN:右外连接
      右外连接不仅可以返回满足连接条件的所有记录,而且还会返回不满足连接条件的连接操作符右边表
      的其他行,如:

SQL> SELECT a.dname,b.ename
  2  FROM dept a
  3  RIGHT JOIN emp b
  4  ON a.deptno=b.deptno AND a.deptno=30;
 
DNAME          ENAME
-------------- ----------
SALES          JAMES
SALES          TURNER
SALES          BLAKE
SALES          MARTIN
SALES          WARD
SALES          ALLEN
               MILLER
               KING
               CLARK
               JONES
               SMITH
               SCOTT
               ADAMS
               FORD
 
14 rows selected



      FULL JOIN: 全连接
      完全连接是指不仅会返回满足连接条件的所有行,还会返回不满足连接条件的所有其他行,如:

SQL> SELECT a.dname,b.ename
  2  FROM dept a
  3  FULL JOIN emp b
  4  ON a.deptno=b.deptno AND a.deptno=30;
 
DNAME          ENAME
-------------- ----------
               FORD
               ADAMS
               SCOTT
               SMITH
SALES          ALLEN
SALES          WARD
               JONES
SALES          MARTIN
SALES          BLAKE
               CLARK
               KING
SALES          TURNER
SALES          JAMES
               MILLER
OPERATIONS     
RESEARCH       
ACCOUNTING     
 
17 rows selected


   18.2 使用(+)操作符
      在oracle 9i之前,执行外连接的时候,都是使用(+)来完成的。虽然现在仍旧可以使用
      操作符(+)执行外连接操作,但oracle开始建议使用OUTER JOIN执行外连接,以使得和标准SQL兼容。
      注意1:(+)只能出现在WHERE子句中,并且不能与OUTER JOIN(也就是LEFT JOIN和RIGHT JOIN)同时使用。
      注意2:如果在WHERE子句中包含有多个条件,则必须所有条件都包含(+)操作符号。
      注意3:(+)只适用于列,而不能用在表达式。
      注意4:(+)不能与OR、IN操作符一起使用。
      注意5:(+)不能用于实现全连接(FULL JOIN).

--使用(+)执行左外连接,与LEFT JOIN完全一样
SQL> SELECT a.dname,b.ename
  2  FROM dept a,emp b
  3  WHERE a.deptno=b.deptno(+)
  4  AND b.deptno(+)=30;
 
DNAME          ENAME
-------------- ----------
ACCOUNTING     
RESEARCH       
SALES          ALLEN
SALES          WARD
SALES          JAMES
SALES          BLAKE
SALES          TURNER
SALES          MARTIN
OPERATIONS     
 
9 rows selected  
      
--使用(+)执行右外连接,与RIGHT JOIN完全一样
SQL> SELECT a.dname,b.ename
  2  FROM dept a,emp b
  3  WHERE a.deptno(+)=b.deptno
  4  AND a.deptno(+)=30;
 
DNAME          ENAME
-------------- ----------
SALES          JAMES
SALES          TURNER
SALES          BLAKE
SALES          MARTIN
SALES          WARD
SALES          ALLEN
               MILLER
               KING
               CLARK
               JONES
               SMITH
               SCOTT
               ADAMS
               FORD
 
14 rows selected



19. 子查询
   子查询又称嵌套查询,是指嵌入在其他SQL语句中的SELECT语句。注意在DDL语句中引用子查询的时候,可以带ORDER BY;
   但在WHERE中、SET中引用子查询时,不能带ORDER BY。
   通过INSERT或CREATE TABLE使用子查询,可以将源表数据插入到目标表中。
   在CREATE VIEW或CREATE MATERIALIZED VIEW(物化视图)中使用子查询,可以定义视图或实体化视图所对应的SELECT语句。
   通过UPDATE语句中使用子查询可以修改一列或多列数据。
   根据返回结果的不同,分为单行子查询、多行子查询、多列子查询。
  
       19.1 单行子查询
       单行子查询是指只返回一行数据的子查询,如:

SQL> SELECT ename,sal,deptno FROM emp
  2  WHERE deptno=(SELECT deptno FROM emp WHERE ename='SCOTT');
 
ENAME            SAL DEPTNO
---------- --------- ------
FORD         3000.00     20
ADAMS        1100.00     20
SCOTT        3200.00     20
SMITH         800.00     20
JONES        2975.00     20


       
       19.2 多行子查询
       当在WHERE中使用多行子查询的时候,必须要使用多行比较符号,如IN、ALL、ANY等。
       IN:匹配子查询结果集中任一个值

SQL> SELECT ename,job,sal,deptno 
  2  FROM emp WHERE job IN
  3  (SELECT job FROM emp WHERE deptno=10);
 
ENAME      JOB             SAL DEPTNO
---------- --------- --------- ------
CLARK      MANAGER     2450.00     10
BLAKE      MANAGER     2850.00     30
JONES      MANAGER     2975.00     20
KING       PRESIDENT   5000.00     10
MILLER     CLERK       1300.00     10
JAMES      CLERK        950.00     30
SMITH      CLERK        800.00     20
SCOTT      CLERK       3200.00     20
ADAMS      CLERK       1100.00     20
 
9 rows selected



       ALL:必须要符合子查询结果集中的所有值

SQL> SELECT ename,sal,deptno 
  2  FROM emp WHERE sal>ALL
  3  (SELECT sal FROM emp WHERE deptno=30);
 
ENAME            SAL DEPTNO
---------- --------- ------
JONES        2975.00     20
FORD         3000.00     20
SCOTT        3200.00     20
KING         5000.00     10



       ANY:只要符合子查询结果集中的任一个值即可

SQL> SELECT ename,sal,deptno
  2  FROM emp WHERE sal>ANY
  3  (SELECT sal FROM emp WHERE deptno=30);
 
ENAME            SAL DEPTNO
---------- --------- ------
KING         5000.00     10
SCOTT        3200.00     20
FORD         3000.00     20
JONES        2975.00     20
BLAKE        2850.00     30
CLARK        2450.00     10
ALLEN        1600.00     30
TURNER       1500.00     30
MILLER       1300.00     10
MARTIN       1250.00     30
WARD         1250.00     30
ADAMS        1100.00     20
 
12 rows selected


       
       19.3 多列子查询
       单行或多行子查询都是针对单列而言的,一个是返回单列单行数据,一个是返回单列多行数据。
       而多列子查询是指返回多列数据的查询,如:

--获得与SMITH部门号和职位一样的员工的姓名、职位、工资、部门信息
SQL> SELECT ename,job,sal,deptno
  2  FROM emp WHERE (deptno,job)=
  3  (SELECT deptno,job FROM emp WHERE ename='SMITH' );
 
ENAME      JOB             SAL DEPTNO
---------- --------- --------- ------
ADAMS      CLERK       1100.00     20
SCOTT      CLERK       3200.00     20
SMITH      CLERK        800.00     20     


   
       19.4 其他子查询
       除了可以使用单行子查询、多行子查询以及多列子查询外,还可以使用相关子查询。

--使用EXIST谓词实现相关子查询,显示在'NEW YORK'工作的所有雇员
SQL> SELECT ename,job,sal,deptno FROM emp WHERE
  2  EXISTS
  3  (SELECT 1 FROM dept WHERE dept.deptno=emp.deptno AND dept.loc='NEW YORK');
 
ENAME      JOB             SAL DEPTNO
---------- --------- --------- ------
MILLER     CLERK       1300.00     10
CLARK      MANAGER     2450.00     10
KING       PRESIDENT   5000.00     10


      在FROM子句中使用子查询的时候(注意一定要给子查询起别名),该子查询会被作为视图对待,因此也称为内嵌视图。

--FROM中使用子查询
SQL> SELECT ename,job,sal FROM emp,
  2  (SELECT deptno,avg(sal) avgsal FROM emp GROUP BY deptno) dept
  3  WHERE emp.deptno=dept.deptno AND sal>dept.avgsal;
 
ENAME      JOB             SAL
---------- --------- ---------
FORD       ANALYST     3000.00
SCOTT      CLERK       3200.00
ALLEN      SALESMAN    1600.00
JONES      MANAGER     2975.00
BLAKE      MANAGER     2850.00
KING       PRESIDENT   5000.00
 
6 rows selected      


       
       在DML中使用子查询

--INSERT中使用子查询
SQL> INSERT INTO employee(EMPNO,ENAME,JOB,SAL)
  2  SELECT empno,ename,job,sal FROM emp;
 
14 rows inserted

--UPDATE中使用子查询
SQL> UPDATE emp SET (sal,comm)=
  2  (SELECT sal,comm FROM emp WHERE ename='SMITH')
  3  WHERE job=(SELECT job FROM emp WHERE ename='SMITH');
 
5 rows updated

--DELETE中使用子查询
SQL> DELETE FROM emp WHERE deptno=
  2  (SELECT deptno FROM dept WHERE dname='SALES');
 
6 rows deleted


   
       19.5 在DDL中使用子查询

--CREATE TABLE中使用子查询
SQL> CREATE TABLE EMP_TEST AS (SELECT * FROM emp WHERE ROWNUM<4);
 
Table created

--CREATE VIEW中使用子查询
SQL> CREATE OR REPLACE VIEW dept_test AS
  2  SELECT empno,ename,job,sal FROM emp
  3  WHERE deptno=30 ORDER BY empno;
  
--CREATE MATERIALIZED VIEW中使用子查询
SQL> CREATE MATERIALIZED VIEW sum_emp AS
  2  SELECT deptno,job,avg(sal) avgsal,sum(sal) sumsal
  3  FROM emp GROUP BY cube(deptno,job);
  
Materialized view created


 

你可能感兴趣的:(JOIN,oracle,sql,manager,table,insert)