ORACLE百例試煉二

   Oracle系列《二》:多表複雜查詢和事務處理



多表查詢應該注意去除笛卡爾積,一般多個表時會爲表起個別名

【1】要求查詢僱員的編號、姓名、部門編號、部門名稱及部門位置 

SQL> SELECT   e.empno,e.ename,d.deptno,d.dname,d.loc FROM emp e,dept d 

WHERE e.deptno = d.deptno;


【2】要求查詢每個僱員的姓名、工作、僱員的直接上級領導的姓名(表自關聯) 

SQL> SELECT e.ename,e.job,m.ename FROM emp e,emp m 

WHERE e.mgr = m.empno;


【3】對【2】進行擴充,將僱員所在部門名稱同時列出

 SQL> SELECT e.ename,e.job,m.ename,d.dname FROM emp e,emp m,dept d 

WHERE e.mgr = m.empno AND e.deptno=d.deptno;


【4】查詢每個僱員的姓名、工資、部門名稱,工資在公司的等級(salgrade),及其領導的姓名所在公司的等級 

<1>先確定工資等級表的內容 

SQL> SELECT * FROM salgrade;


<2>查詢每個僱員的姓名、工資、部門名稱和工資在公司的等級 

SQL> SELECT e.ename,e.sal,d.dname,s.grade FROM emp e,dept d,salgrade s 

WHERE e.deptno=d.deptno AND e.sal BETWEEN s.losal AND s.hisal;


<3>查詢其領導姓名及工資所在公司的等級 

SQL> SELECT 

e.ename,e.sal,d.dname,s.grade,m.ename,m.sal,ms.grade  FROM emp e,dept d,salgrade s,emp m,salgrade ms 

WHERE e.deptno = d.deptno 

AND e.sal BETWEEN s.losal AND s.hisal 

AND e.mgr = m.empno 

AND m.sal BETWEEN ms.losal AND ms.hisal;


【5】左連接與右連接的概念,"+"在等號左邊表示右連接,反之,左連接

查詢僱員的編號、姓名及其領導的編號、姓名 

SQL> SELECT e.empno,e.ename,m.empno,m.ename FROM emp e,emp m 

WHERE e.mgr = m.empno(+); 就發現將KING的那條記錄也連過來了







SQL1999語法中有如下幾種連接(瞭解) 

1、交叉連接CROSS JOIN,產生笛卡爾積 

SQL> SELECT * FROM emp CROSS JOIN dept;

 

2、自然連接NATURAL JOIN,自動進行關聯字段的匹配 

SQL> SELECT * FROM emp NATURAL JOIN dept;


3、使用USING子句,直接關聯操作列 

SQL> SELECT * FROM emp JOIN dept USING(deptno) WHERE deptno=30;

 

4、使用ON子句,用戶自己編寫的條件 

SQL> SELECT * FORM emp JOIN dept ON(emp.deptno = dept.deptno) WHERE deptno=30; 


5、左連接(左外連接、LEFT (OUTER) JOIN)、右連接(右外連接、RIGHT (OUTER) JOIN)








組函數及分組統計 

1、COUNT():求出全部記錄數 

2、MAX():求出一組中最大值

3、MIN():求出最小值 

4、AVG():求出平均值 

5、SUM():求和


【1】求出每個部門的僱員數量 

SQL> SELECT deptno,count(empno) FROM emp 

GROUP BY deptno;


【2】按部門分組,並顯示部門的名稱,及每個部門的員工數 

SQL> SELECT d.dname,COUNT(e.empno) FROM emp e,dept d 

WHERE e.deptno=d.deptno GROUP BY d.dname;


【3】要求顯示平均工資大於2000的部門編號和平均工資

 SQL> SELECT deptno,AVG(sal) FROM emp 

WHERE AVG(sal)>2000 GROUP BY deptno;

 

出錯,WHERE子句中不能出現分組函數的條件,要使用HAVING子句 上述語句應該改爲如下 


SQL> SELECT deptno,AVG(sal) FROM emp 

GROUP BY deptno 

HAVING AVG(sal)>2000


【4】顯示非銷售人員工作名稱以及從事同一工作僱員的月工資總和,

並且要求從事同一工作的僱員月工資合計大於$5000, 輸出結果按月工資的合計升序排序

<1>按工作分組,求出非銷售人員的月工資總和 

SQL> SELECT job,SUM(sal) FROM emp 

WHERE job<>'SALESMAN' GROUP BY job; 


<2>對分組條件進行限制,然後進行排序,HAVING子句不能使用別名 

SQL> SELECT job,SUM(sal)  totalSal  FROM emp 

WHERE job<>'SALESMAN' GROUP BY job 

HAVING SUM(sal) > 5000 ORDER BY totalSal;


【5】分組函數可以嵌套使用,但是在SELECT列中就不能再出現該分組條件的列名了 

SQL> SELECT deptno,MAX(AVG(sal)) FROM emp 

GROUP BY deptno; 


出錯!修改如下

 

SQL> SELECT MAX(AVG(sal)) FROM emp 

GROUP BY deptno;


【6】查詢出比7654工資要高的全部僱員的信息 

<1>首先要查詢僱員編號7654的工資 

SQL> SELECT sal FROM emp WHERE empno=7654;


<2>以上述條件的結果最後後續查詢的依據 

SQL> SELECT * FROM emp 

WHERE sal>(SELECT sal FROM emp WHERE empno=7654);








子查詢在操作中分爲以下三類: 

1、單列子查詢:返回的結果是一列的內容 

2、單行子查詢:返回多個列,也可能是一條記錄 

3、多行子查詢:返回多個記錄



【1】要求查詢工資比7654高,同時與7788從事相同工作的全部僱員 

SQL> SELECT * FROM emp 

WHERE sal>(SELECT sal FROM emp WHERE empno=7654) 

AND job=(SELECT job FROM emp WHERE empno=7788);



【2】要求查詢 部門名稱、部門員工數、部門平均工資,部門的最低收入僱員的姓名 

<1>查詢部門員工數、部門平均工資 

SQL> SELECT deptno,COUNT(empno),AVG(sal) FROM emp 

GROUP BY deptno; 


<2>查詢部門的名稱,及最低收入僱員姓名,要進行表關聯(子查詢)

SQL> SELECT d.dname,ed.c,ed.a,e.ename FROM dept d,( 

 SELECT deptno,COUNT(empno) c,AVG(sal) a,MIN(sal) min  FROM emp 

 GROUP BY deptno) ed, emp e 

WHERE d.deptno=ed.deptno AND e.sal = ed.min;


若上述存在兩個最低工資的情況,則會出錯,在子查詢中存在以下3種查詢的操作符號 

IN:指定一個查詢範圍,例如查詢每個部門的最低工資(返回值有多個)

 SQL> SELECT * FROM emp 

WHERE sal IN (SELECT MIN(sal) FROM emp GROUP BY deptno);


ANY:=ANY(與IN操作一樣)、>ANY(比最小大)、<ANY(比最大小) 

SQL> SELECT * FROM emp 

WHERE sal <ANY(SELECT MIN(sal) FROM emp GROUP BY deptno);


ALL: >ALL(比最大要大)、<ALL(比最小的小),SQL語句類似上面


多行子查詢

顯示和10號部門從事相同崗位的僱員信息

SQL>select *  from emp where job in (select  job  from emp  where  deptno=10);








數據庫更新操作INSERT、UPDATE、DELETE 


【1】複製一張表,例如複製EMP表爲MYEMP 

SQL> CREATE TABLE MYTEMP AS SELECT * FROM emp;  


【2】將編號爲7899的僱員的領導取消 

SQL> UPDATE myemp SET mgr=null WHERE empno=7899;

  

【3】更新時,一定要注意不能批量更新(加上WHERE子句),多列更新例子如下

SQL> UPDATE myemp SET mgr=null,comm=null WHERE empno IN(7369,8899);

  

【4】刪除掉全部領取獎金的僱員 

SQL> DELECT FROM emp WHERE comm is NOT NULL;


事務處理 ACID 

A:Atomicity   原子性:事務中的操作或者都完成,或者都取消 

C:Consistency 一致性:事務中的操作保證數據庫中的數據不會出現邏輯上不一致的情況 

I:Isolation   隔離性:當前的事務與其他未完成的事務是隔離的 

D:Durability  持久性:在COMMIT之後,數據永久保存在數據庫中,在此之前,事務的操作都可以回滾


驗證事務過程: 

<1>創建一張臨時表,只包含部門10 

SQL> CREATE TABLE emp10 AS SELECT * FROM emp WHERE empno=10; 


<2>刪除emp10中的7782僱員 

SQL> DELETE FROM emp10 WHERE empno=7782; 

再打開另一個窗口,發現數據還存在,此時如果可以使用以下的兩種命令進行事務處理


COMMIT 和 ROLLBACK 提交事務和回滾事務







SQL查詢練習


【1】列出至少一個員工的所有部門 

SQL> SELECT d.*,ed.cou FROM dept d,( 

                                         SELECT deptno,COUNT(empno) cou FROM emp  GROUP BY deptno 

                                                  HAVING COUNT(empno) > 1

                                                        ) ed 

WHERE d.deptno=ed.deptno;



【2】列出部門名稱和這些部門的員工信息,同時列出那些沒有員工的部門

SQL> SELECT d.deptno,d.dname,e.empno,e.ename 

FROM dept d,emp e  WHERE d.deptno = e.deptno(+);



【3】列出所有"CLERK"(辦事員)的姓名及其部門名稱,部門的人數 

<1>關聯dept表 

SQL> SELECT e.ename,d.dname FROM emp e,dept d 

WHERE e.deptno=d.deptno and e.job='CLERK'; 


<2>使用GROUP BY 完成部門分組人數 

SQL> SELECT e.ename,d.dname,ed.cou FROM emp e,dept d,

(  SELECT deptno,COUNT(empno) cou FROM emp  GROUP BY deptno) ed 

WHERE job='CLERK' AND e.deptno=d.deptno AND ed.deptno=e.deptno;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章