數據庫比較枯燥,我說的是使用數據庫不是做數據庫。總是用SQL語句那么跑來跑去,想把數據庫講解的十分有趣,著實不是一件容易的事。只是在PLSQL里編寫SQL語句,然后調用、查看結果。雖然數據庫很枯燥,但它在項目中的功用卻是十分重要的。我原未如此的深入使用過數據庫,近兩天一見,其功能也讓我十分興奮,以前自己寫的小東西,走了些彎路!
無論如何還是要搞好數據庫的,尤其是Oracle數據庫。明天是最后一天學習數據庫了,終于要把這塊陣地給解放了!
OK,來看重點內容吧!
常用的分組函數,這個比較重要,在其他數據庫中也有:
1. AVG,求平均值。如果某一記錄為null,則不加入平均值的計算。(不加入被除數)
2. COUNT,求表中所有符合條件的記錄數。如果某一記錄為null,則不計算在內!
3. MAX,求最大值。
4. MIN,求最小值。
5. SUM,求合。
還有一個特殊的函數NVL,將字段值為空的記錄替換為指定的值,AVG(NVL(commission_pct,0)。比如上面的AVG函數將null記錄剔除在外。這樣調用就不會把null值的記錄剔除在外了:NVL(AVG(NVL(commission_pct,0)))。
Group by 子句,是最低級的運算語句,它被放置在語句的最后,對Group by子句分組的記錄進行過濾應使用having語句。Where是用于Group by之前的記錄過濾。在Select列表中出現的字段,如果不是在組函數中,那么它必須也被放置到Group by子句中。
接下來是十分重要的內容:多表連接和子查詢!
首先讓我們來回顧一下“外鍵”字段,比如有一個部門表,有一個員工表。員工表中使用的部門ID就是一個外鍵,這個部門ID就是部門表中的ID。這樣設計有益于節省空間、快速查詢和易于管理等特點。這樣的表查詢的操作比較多,我們應該如何實現便利、快速的查詢呢?難道從員工表中取出部門ID然后再到部門表中查詢這個ID?NO,這樣太麻煩了,訪問量多了,明顯會使速度降下來。所以表連接出現了!表連接就是將多個表,根據表之間的相關字段關系連接起來,就像一張表一樣。對這一大張表的操作十分方便、快捷!
Oracle的語法,使用表連接從多個表中查詢數據:
SELECT table1.column, table2.column
FROM table1, table2
WHERE table1.column1 = table2.column2;
在 WHERE 子句中寫入連接條件。
當多個表中有重名列時,必須在列的名字前加上表名作為前綴。
例,查詢員工的姓名和所在部門:

其中的E和D分別是表EMP和表DEPT的別名,這里不能使用AS。
EMP表中的DEPTNO字段是個外鍵,它指向DEPT表中的DEPTNO。
在Oracle中都有哪些表連接?在Oracle8i之前有:
1. 等值連接 – Equijoin,這是連接操作中最常見的一種。通常在存在主外鍵約束條件的多表上建立的,連接中的兩個字段通過等號建立等值關系。如上面的例子是使用主外鍵對兩個表的連接,還可以對多個表連接,此時可以使用AND增加WHERE子句的連接條件。
2. 非等值連接 -- Non-equijoin。例,通過EMP表和SALGRADE(薪水等級)表,查詢員工薪水所處等級:

語句也可寫成:
SELECT E.ENAME,E.JOB,S.GRADE FROM EMP E,SALGRADE S WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL |
使用JOIN ON語句,更直觀些!它是9i中加入的,可以使用多個JOIN ON語句,連接多個表,它們之間不需要添加任何關鍵字,比如“AND”。
3. 外連接 -- Outer join,外連接可以查詢出不滿足條件的記錄,它分為左外連接和右外連接(繼續關注下面9i中的外連接)。
左外連接:

正是子句中的“(+)”起的作用,這樣將DEPTNO表中的所有記錄都顯示出來了,即使有沒有員工的部門也顯示了。
右外連接:

正是子句中的“(+)”起的作用,將EMP表中的記錄全部顯示出來了,即使沒有部門的員工也顯示了。
4. 自連接 -- Self join,就是連接自己。例,取對員工對應的領導:

因為公司所有職員都在一張表中(包括領導),所以為了查找出對應員工的領導,使用了自連接。自連接就像是為自己創建了一個引用。
到Oracle9i時,新增加的連接(SQL1999適應性連接):
1. 交叉連接 -- Cross joins,產生了一個笛卡爾積,就象是在連接兩個表格時忘記加入一個WHERE子句一樣。相互交叉,返回的記錄數正好是兩個表記錄數的乘積。轉一個兄弟對交叉鏈接的介紹:http://tech.techweb.com.cn/thread-384787-1-1.html

上面的語句與這個功效一樣:
SELECT E.ENAME,E.JOB,D.DNAME FROM EMP E,DEPT D |
2. 自然連接 -- Natural joins,基于兩個表中列名完全相同的多個列產生連接。從兩個表中選出連接列的值相等的所有行,如果兩個列的名稱相同,但是具有不同的數據類型,則查詢會返回一個錯誤。

EMP表與DEPT表中的DEPTNO字段名稱相同,且類型相同。
3. 使用Using子句的連接
如上面(2)的例子,如果兩個字段的名稱相同,但類型不同就會出現錯誤。此時可以在語句后邊加上USING(字段名)子句,來設置用于等值連接,只要值可比,類型不同也可以。
4. 完全外連接或者左右外連接
左外連接:
顯示左邊表中所有行,即使在右邊的表中沒有可對應的列值。這與8i中的右外連接是相同的,但這個更直觀的指向左邊,而不像8i中那樣反著。

右外連接:
顯示右邊表中所有行,即使在左邊的表中沒有可對應的列值。這與8i中的左外連接是相同的,但這個更直觀的指向右邊,而不像8i中那樣反著。

完全外連接:顯示連接表中的所有記錄,包括不存在對應記錄的記錄。全外連接是對兩個表中的記錄都不加限制。

5. 搞不懂里邊的條件語句還有什么用。不加上就語法錯誤!(外連接中可以使用任意的連接條件
)
子查詢:
之前我們學習的都是直接使用某一固定或函數返回值做為限定條件,但這能滿足我們的操作嗎?即使有連接這樣看起來十分強大的功能。當然不能,子查詢解決了更多的問題!
SELECT select_list
FROM table
WHERE expr operator
(SELECT select_list FROM table);
1、子查詢在主查詢前執行一次
2、主查詢使用子查詢的結果
3、子查詢語句中不能使用外部的別名
使用子查詢的注意事項:
1、子查詢要用括號括起來
2、將子查詢放在比較運算符的右邊(增強可讀性)
3、只有在執行Top-N分析時,子查詢中才需要使用Order by子句
4、在Oracle8i之前的版本中,子查詢不能包含Order by子句
5、對單行子查詢使用單行運算符
6、對多行子查詢使用多行運算符
子查詢的種類:
1. 單行單列子查詢:只包含一個字段的查詢,返回的查詢結果也只包含一行數據
2. 多行單列子查詢:只包含了一個字段,但返回的查詢結果可能多行或者零行
3. 多列子查詢:包含多個字段的返回,查詢結構可能是單行或者多行。
單行子查詢所使用的比較運算符:
Operator | Meaning |
= | Equal to |
> | Greater than |
>= | Greater than or equal to |
< | Less than |
<= | Less than or equal to |
<> | Not equal to |
例,查詢薪金小于平均薪金的員工,對他們加強培訓提高工作技能,漲工資:

多行子查詢所使用的比較運算符:
Operator | Meaning |
IN | 與IN列表中任意一個值相等 |
ANY | 與子查詢返回的任意一個值比較,ANY通常與大小寫符號搭配使用,不單獨使用。可以是<ANY 和>ANY : <ANY 小于子查詢數據中的最大值 >ANY 大于子查詢數據中的最小值 |
ALL | 與子查詢返回的每一個值比較,ALL通常與大小寫符號搭配使用,不單獨使用。可以是<ALL 和>ALL : >ALL 指大于子查詢數據中的最大值 <ALL 指小于子查詢數據中的最小值 |
例,查詢出比平均工資高的員工,給他們升職和更多成長的機會:

以上都只是簡單的舉了幾個例子,函數和語句等組合應用,會讓你感到吃驚,功能驚人。當然,我也這只是一個程序員對數據庫的了解。DBA玩的就深一些,那里有更強大的功能,主要是對表優化的。先不深入了,這些夠用了,明天講解Oracle觸發器、存儲過程、視圖等!
下面例出三個今日老馮給我們做的練習:
1. 查詢各個管理者的編號及其手下員工的最低工資,其中最低工資不能低于1200,沒有管理者的員工不計算在內。

2. 查詢所有部門的名稱,loc,員工數量和工資平均值。

3. 查詢在loc為紐約的部門工作的員工的員工號,ename,deptno,job(使用連接查詢,子查詢兩種查詢方式)

OK,歡迎明天的到來,數據庫這塊算是完了!
加油!