文章目錄
所有操作均在 Oracle 數據庫上進行
第三章 - 關係數據庫標準語言 SQL
3.1 SQL 概述
3.1.1 結構化查詢語言 SQL
SQL 是一種介於關係代數與關係演算之間的語言,
功能包括 查詢、操縱、定義和控制四個方面。
3.1.2 SQL 體系結構
1. 外模式 - 視圖和部分基本表
2. 模式 - 基本表,元組稱爲行,屬性稱爲列
3. 內模式 - 存儲文件
3.1.3 SQL 的組成
1. 數據操作語言 - 刪插改查 行
2. 數據定義語言 - 增刪改 表 ;增刪 索引、視圖
3. 數據控制語言 - 控制管理用戶對數據庫對象的訪問
4. 觸發器和高級完整性約束
5. 嵌入式和動態 SQL - 嵌套在高級語言中,允許在運行時構建查詢
6. 客戶 - 服務器執行和遠程數據庫提取
7. 事物管理 - 顯式控制事務執行
3.1.3 SQL 的特點
1. 綜合統一: 集數據定義、操縱、控制語言於一體(DDL、DML、DCL);獨立完成數據庫生命週期的全部活動,隨時修改,數據操作符統一。
2. 高度非過程化: SQL 只需提出”做什麼“,無需瞭解存取路徑。
3. 面向集合的操作方式: 面向記錄操作,結果、對象可以是元組的集合。
4. 以同一種語法結構提供多種使用方式: 聯機交互,嵌入式。
5. 語言簡潔:
3.2 數據定義
3.2.1 基本表的操作
1. 定義基本表
CREATE TABLE 表名(
列名 數據類型 完整性約束,
列名 數據類型 完整性約束,
表級完整性約束(列名)
)
完整性約束:存入系統的數據字典中,DMBS自動檢查
完整性約束條件
1.重名名約束條件:constraint 約束名字 約束
2.主碼約束:primary key
3.外碼約束:
行級:references 表名(列名)
表級:foreign key (列名) references 表名(列名)
4.check約束:check(條件)
5.NOT NULL約束:
6.UNIQUE約束:
7.DEFAULT約束:default('值')
2. 修改基本表
ALTER TABLE 表名 操作 列
1.添加列:ALTER TABEL 表名 ADD 列名 數據類型 完整性約束
ALTER TABEL 表名 ADD(
列名 數據類型 完整性約束,
列名 數據類型 完整性約束)
2.刪除列:ALTER TABEL 表名 DROP COLUMN 列名
ALTER TABEL 表名 DROP (列名, 列名)
3.修改列:ALTER TABEL 表名 MODIFY 列名 數據類型 完整性約束
4.刪除約束:ALTER TABLE 表名 DROP CONSTRAINT 約束名
ALTER TABLE 表名 DROP 約束(列名) ---Oracle不支持---
刪除 UNIQUE 或 PRIMARY KEY 約束可能導致由其生成的索引被刪除
3. 刪除基本表
DROP TABLE 表名
3.2.2 索引的操作
1. 建立索引
CREATE 選項 INDEX 索引名 ON 表名(列名 次序, 列名 次序)
選項:
UNIQUE 表明每一個索引值只對應唯一的數據記錄
CLUSTER 表明建立聚簇索引
在 Oracle 中,不能對主鍵建立唯一索引,創建約束時系統自動創建
聚簇索引指表中記錄的物理順序與索引相同的索引組織,只能建立一個
在 Oracle 中,只能在定義表的同時定義
在常用的查詢列上定義索引可以提高查詢效率
對於經常更新的表不宜建立聚簇索引
次序:
ASC 升序
DESC 降序
默認值爲升序
2. 刪除索引
DROP INDEX 索引名
索引建立後由系統維護,建立索引可以檢查查詢時間,但若數據增刪頻繁,系統會花費大量時間維護
3.3 基本數據查詢
SELECT [ALL/DISTINCT] 目標列表達式,目標列表達式
FROM 表/視圖, 表/視圖
[WHERE 條件]
[GROUP BY 列名 [HAVING 條件] ]
[ORDER BY 列名 [次序] ]
3.3.1 SELECT 子句
SELECT [ALL/DISTINCT] 目標列表達式,目標列表達式
1. 關鍵字 DISTINCT
從 SELECT 語句的結果中去除重複的行(針對後面的所有列,即針對元組),默認值爲 ALL
2. 目標列表達式
目標表達式可以爲算術表達式,字符串常量,函數,列別名
1. 查詢指定列:列名
2. 查詢全部列:*
3. 算術表達式:數值 運算符 列名
4. 指定別名:列名 別名
列表達式 "別名"
5. 指定列的默認值:'字符串' 列名
6. 函數:LOWER(列名), UPPER(列名) 將列中所有值設置爲小/大寫。
3.3.2 WHERE 子句
[WHERE 條件]
查詢結果爲指定條件的元組
1. 比較
比較數值或 字符ascii 碼大小
2. 確定範圍
選出兩個值及其之間的數據,可以是日期,數字,文字
3. 確定集合
IN(值,值)
4. 字符匹配
LIKE 通配字符串 [ESCAPE '轉義符']
1. 通配字符串:
% 任意或多個字符
_ 單個字符
2. 設置轉義符:
對於字符串本來存在 % 和 _ 的情況,需要設置轉義符轉義
5. 空值查詢
空值和其他值沒有可比性,不能用 = 代替 IS
列名 IS NOT NULL
6. 多重條件
AND 優先級高於 OR,但可用括號改變
3.2.3 ORDER BY 子句
[ORDER BY 列名 [次序] ]
指定按照一個或多個屬性列進行升降序排列結果,NULL 被視爲最大值
3.2.4 聚集函數
COUNT([DISTINCT/ALL] *) 統計元組個數
COUNT([DISTINCT/ALL] 列名) 統計一列中值的個數
SUM([DISTINCT/ALL] 列名) 列總和,必須爲數值型的列
AVG([DISTINCT/ALL] 列名) 列平均,必須爲數值型
MAX([DISTINCT/ALL] 列名) 最大值
MIN([DISTINCT/ALL] 列名) 最小值
默認統計重複值
除指定了 * ,函數只處理非空值
WHERE 子句不能使用聚集函數
示例:
SELECT AVG(Sage)
FROM Student;
非法查詢方式
SELECT Sname,MAX(Sage)
FROM Student;
合法查詢方式
SELECT Sname,Sage
FROM Student
WHERE Sage=(SELECT MAX(Sage) FROM Student);
3.2.5 GROUP BY 和 HAVING 子句
GROUPBY 必須是集合操作(聚集函數),不能進行元組操作
[GROUP BY 列名 [HAVING 條件] ]
GROUP BY 可以將查詢結果的各行按一列或多列取值相等的原則進行分組
在用聚集函數時一般都要用到GROUP BY進行分組,再用函數計算
計算完可以用HAVING子句進行判斷
示例:
查詢每個學生選修的課程數。
SELECT Sno, COUNT(Cno)
FROM SC
GROUP BY Sno;
查詢平均分在80分以上的學生的學號及其選課數。
SELECT Sno,Count(Cno)
FROM SC
GROUP BY Sno
HAVING AVG(Grade)>80;
3.4 連接查詢
一個查詢需要對多個表進行操作,稱爲連接查詢。
3.4.1 WHERE 子句連接
1. 等值與非等值連接
SELECT 目標表達式
FROM 表1,表2
WHERE 表1.列名 比較符 表2.列名
或者
WHERE 表1.列名 BETWEEN 表2.列名 AND 表3.列名
2. 笛卡兒積連接
SELECT *
FROM 表1,表2
3. 自然連接
按照表中相同的屬性進行等值連接,並去掉目標列中重複的屬性列
SELECT 不重複的屬性列表
FROM 表1,表2
WHERE 表1.列名 = 表2.列名
4. 自身連接
一個表與自己進行連接
查詢每一門課的間接先修課,即先修課的先修課。
SELECT FIRST.Cno, SECOND. Cpno
FROM Course FIRST, Course SECOND
WHERE FIRST. Cpno =SECOND.Cno;
5. 外連接
以Student表爲主體列出每個學生的基本情況及其選課情況。
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student, SC
WHERE Student.Sno=SC.Sno(+);
6. 複合條件連接
查詢選修2號課程且成績在90分以上的所有學生。
SELECT Student.Sno, Sname
FROM Student, SC
WHERE Student.Sno=SC.Sno AND SC.Cno=2 AND SC.Grade>90;
3.4.2 FROM 子句連接
SELECT 目標表達式
FROM 表1 連接類型 表2
ON 條件
連接類型:
1.內連接:[INNER] JOIN - 等值、不等值、自然連接
2.外連接:LEFT [OUTER] JOIN - 左外連接
RIGHT [OUTER] JOIN - 右外連接
FULL [OUTER] JOIN - 全外連接
3.交叉連接:CROSS JOIN - 笛卡兒積連接
3.5 嵌套查詢
將一個查詢嵌套在另一個查詢裏,子查詢本身也可以是嵌套查詢
子查詢通常出現在 WHERE 子句,有時也出現在 FROM 子句,有時也出現在 HAVING 短語中
子查詢的 SELECT 語句不能使用 ORDER BY ,只能對最終結果 ORDER BY
不相關與相關子查詢
不相關子查詢:子查詢都在父查詢處理前求解,子查詢只執行依次
相關子查詢:子查詢依賴於父查詢的某個條件。
先取外層查詢中的第一個元組,根據其與內層查詢相關的屬性值處理內層查詢。
若 WHERE 子句返回值爲真,則取此元組放入結果表。
重複此過程,直至外層表全部檢查完成。
3.5.1 比較運算符子查詢
---不相關子查詢---
利用子查詢完成
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept =(
SELECT Sdept
FROM Student
WHERE Sname= '劉晨'
);
用自身連接完成
SELECT S1.Sno,S1.Sname,S1.Sdept
FROM Student S1,Student S2
WHERE S1.Sdept = S2.Sdept AND S2.Sname = '劉晨'
---相關子查詢---
找出每個學生超過他選修課程平均成績的課程號。
SELECT Sno, Cno
FROM SC x
WHERE Grade >= (SELECT AVG(Grade)
FROM SC y
WHERE y.Sno=x.Sno
);
3.5.2 IN 子查詢
查詢所有選修了1號課程的學生的學號、姓名
SELECT Sno,Sname
FROM Student
WHERE Sno IN (
SELECT Sno
FROM SC
WHERE Cno=1
);
利用連接查詢來實現
SELECT Student.Sno, Sname
FROM Student, SC
WHERE Student.Sno=SC.Sno AND Cno=1;
3.5.3 BETWEEN AND 子查詢
查找從19歲到 Student 表中年齡最大之間的學生學號和姓名
SELECT Sno,Sname
FROM Student
WHERE Sage BETWEEN 19 AND (
SELECT MAX(Sage)
FROM Student
);
3.5.4 ALL 和 ANY 子查詢
ALL 要求所有,ANY 只要有一個就行
查詢年齡比數學系最小的學生還小的學生學號和姓名。
SELECT Sno,Sname FROM Student
WHERE Sage < ALL(
SELECT Sage FROM Student
WHERE Sdept=‘MA’
);
比任何一個學生小就行,不是最小
SELECT Sno,Sname FROM Student
WHERE Sage < ANY(
SELECT Sage FROM Student
WHERE Sdept=‘MA’
);
3.5.5 EXISTS 子查詢
EXISTS 子查詢只返回邏輯值 true 和 false,結果非空爲 true,結果空爲 false
NOT EXISTS 相反
一些帶EXISTS或NOT EXISTS謂詞的子查詢不能被其他形式的子查詢等價替換
所有帶IN謂詞、比較運算符、ANY和ALL謂詞的子查詢都能用帶EXISTS謂詞的子查詢等價替換
1. 存在量詞 - 反 E
查詢所有選修了1號課程的學生姓名
---相關子查詢---
SELECT Sname
FROM Student
WHERE EXISTS (
SELECT *
90 FROM SC
WHERE Sno=Student.Sno AND Cno=1
);
其它實現方法
---不相關子查詢---
SELECT Sname
FROM Student
WHERE Sno IN (
SELECT Sno
FROM SC
WHERE Cno=1
);
SELECT Sname
FROM Student
WHERE Sno=ANY (
SELECT Sno
FROM SC
WHERE Cno=1
);
2. 全稱量詞 - 倒 A
---相關子查詢---
查詢選修了全部課程的學生姓名
SELECT Sname
FROM Student ---選擇了一個學生---
WHERE NOT EXISTS( ---一個學生未選集合判空---
SELECT *
FROM Course ---選擇了一門課程---
WHERE NOT EXISTS( ---生成一個學生未選課程集合---
SELECT * ---從 SC 表中找對應記錄---
FROM SC
WHERE Sno= Student.Sno
AND Cno= Course.Cno
)
);
查詢至少選修了學生200215122選修的全部課程的學生號碼
SELECT DISTINCT Sno
FROM SC SCX ---選擇了一條記錄 X ---
WHERE NOT EXISTS( ---一個 X 集合判空---
SELECT *
FROM SC SCY ---選擇指定的 Y ---
WHERE SCY.Sno = '200215122'
AND NOT EXISTS ( ---一個 X 找不到 Y 課程的集合---
SELECT *
FROM SC SCZ ---尋找一條記錄 ---
WHERE SCZ.Sno=SCX.Sno ---匹配選中的 X ---
AND SCZ.Cno=SCY.Cno ---檢查是否包含 Y 的課程 ---
)
);
3.6 集合查詢
SQL 查詢的結果是多行的集合
SQL 提供了三種集合操作,並操作 UNION,交操作 INTERSECT,差操作 EXCEPT,其中 ORACLE 中差操作用 MINUS 表示
3.6.1 並操作 UNION
UNION 可將多個查詢結果合併起來,形成一個完整的查詢結果,系統會去點重複的元組。
參加 UNION 操作的各數據項的數目及數據類型必須相同。
查詢選修1號課程或者選修2號課程的學生學號
SELECT Sno
FROM SC
WHERE Cno=1
UNION
SELECT Sno
FROM SC
WHERE Cno=2
3.6.2 交操作 INTERSECT
查詢選修1號課程和2號課程的學生姓名
SELECT Sname
FROM SC,Student
WHERE Cno=1 AND Student.Sno=SC.Sno
INTERSECT
SELECT Sname
FROM SC,Student
WHERE Cno=2 AND Student.Sno=SC.Sno
3.6.3 差操作 EXCEPT / MINUS
查詢選修1號課程但是沒有選修2號課程的學生學號
SELECT Sno
FROM SC
WHERE Cno=1
MINUS
SELECT Sno
FROM SC
WHERE Cno=2
3.7 數據更新
3.7.1 插入數據
若某些屬性列在 INTO
中沒有出現,則新記錄中該列去取空值。
若定義表時某屬性列設置了 NOT NULL
,不能爲空值。
若 INTO
子句沒有指明列名,則新插入的記錄必須在某個屬性列上均有值。
1. 插入元組
INSERT
INTO 表名(列名, 列名)
VALUES (常量、常量);
示例:
INSERT
INTO Course
VALUES (10, '網絡技術', 5, 2);
INSERT
INTO SC(Sno, Cno)
VALUES (1001, 10);
2. 與子查詢結合
INSERT
INTO 表名(列名, 列名)、
(子查詢)
示例:
對每門課程,求學生的平均分數,並把結果存入數據庫
INSERT
INTO AvgGrade(Cno, AvgGrade)
(SELECT Cno, AVG(Grade)
FROM SC GROUP BY Cno);
3.7.2 修改數據
更新表中數據,必須提供表名及 SET
表達式,可加 WHERE
限制更新的記錄範圍。
1. 修改元組
UPDATE 表名
SET 列名=表達式, 列名=表達式
[WHERE 條件]
示例:
將學號爲1001的學生的年齡改爲20歲
UPDATE Student
SET Sage=20
WHERE Sno=1001;
將所有學生的年齡增加1歲。
UPDATE Student
SET Sage=Sage+1;
2. 與子查詢結合
語句執行時,將修改使子查詢爲真的所有元組。
UPDATE 表名
SET 列名=表達式, 列名=表達式
[WHERE 子查詢條件表達式]
示例:
將數學系有成績學生的分數更新爲原分數的1.2倍
UPDATE SC
SET Grade = Grade * 1.2
WHERE Sno IN
(SELECT Sno
FROM Student
WHERE Sdept = 'MA')
3.7.3 刪除數據
刪除指定表中滿足 WHERE
子句條件的所有元組,如果省略 WHERE
子句,表示刪除表中全部元組,但表的定義仍存在與數據字典中。即刪除的是表中數據,而不是表的定義。
1. 刪除元組
DELETE
FROM 表名
[WHERE 條件]
示例:
刪除性別是男的學生記錄。
DELETE
FROM Student
WHERE Ssex='男';
刪除的學生選課記錄。
DELETE
FROM SC;
2. 與子查詢結合
DELETE
FROM 表名
[WHERE 子查詢條件表達式]
示例:
刪除數學系選課學生的選課記錄。
DELETE Sc
WHERE Sno IN
(SELECT Sno
FROM Student
WHERE Sdept= 'MA');
或者
DELETE
FROM SC
WHERE 'MA'=
(SELETE Sdept
FROM Student
WHERE Student.Sno=SC.Sno);
3.8 視圖
視圖是一個基於一個表或多個表或視圖的邏輯表,視圖基於的表稱爲虛表
視圖只存儲視圖的定義,沒有存儲對應的數據,只是一個虛表
視圖在打開的瞬間通過定義從基表中搜集數據,並展現給用戶
通過視圖可以對錶裏的數據進行查詢和修改
3.8.1 視圖的優點
- 簡單性:分割數據,簡化觀點,把用戶注意力集中到所關心的數據列,簡化瀏覽數據的工作。
- **邏輯數據獨立性:**爲數據提供一定的邏輯獨立。基本表的內容發生改變,不會影響視圖定義所得到的數據。
- **安全性:**提供給自動的安全保護功能,視圖能像基本表一樣授予或者撤銷訪問許可。
- 試圖可以間接對錶進行更新,視圖的更新就是表的更新。
3.8.2 創建視圖
CREATE VIEW 視圖名(列名, 列名)
AS 子查詢
[WITH CHECK OPTION]
子查詢可以是任意複雜的 SELECT
語句,但通常不允許含有 ORDER BY
和DISTINCT
短語。
WITH CHECK OPTION
表示對視圖進行 UPDATE
INSERT
DELETE
操作時要保證進行操作的行滿足視圖定義中的謂詞條件,即子查詢中的條件表達式。
若 CREATE VIEW
僅指定了視圖名,則隱含該屬性由子查詢中的 SELECT
子句目標列中的字段組成。以下三種情況必須指定視圖的所有列名:
- 其中某個目標列不是單純的屬性名,而是聚集函數或列表達式
- 多表連接時選出了幾個同名列作爲視圖的字段
- 需要在視圖中爲某個列啓用別名
組成視圖的屬性列名必須按照上面的原則全部省略或全部指定
建立數學系學生的視圖。
CREATE VIEW MA_Student
AS
SELECT Sno, Sname, Sage
FROM Student
WHERE Sdept='MA';
DBMS
執行 CREATE VIEW
語句的結果只是把對視圖的定義存入數據字典,並不執行其中的 SELECT
語句。在對視圖進行查詢時,才按視圖的定義從基本表中將數據查出。
建立數學系學生的視圖,並要求進行修改和插入操作時仍需要保證該視圖只有數學系的學生。
CREATE VIEW MA_Student
AS
SELECT Sno, Sname, Sage ,sdept
FROM Student
WHERE Sdept='MA'
WITH CHECK OPTION;
視圖不僅可以建立在單個基本表上,也可以建立在多個基本表上,也可以建立在一個或多個已定義好的視圖上,或同時建立在基本表與視圖上。
建立數學系選修了1號課程的學生的視圖
CREATE VIEW MA_S1(Sno, Sname, Grade)
AS
SELECT Student.Sno, Sname, Grade
FROM Student, SC
WHERE Sdept='MA' AND
Student.Sno=SC.Sno AND
SC.Cno=1;
建立數學系選修了1號課程且成績在90分以上的學生的視圖
CREATE VIEW MA_S2
AS
SELECT Sno, Sname, Grade
FROM MA_S1
WHERE Grade>=90;
視圖中的出生年份是一個表達式,定義視圖時必須明確定義視圖的各屬性列名。
定義一個反映學生出生年份的視圖
CREATE VIEW BT_S(Sno, Sname, Sbirth)
AS SELECT Sno, Sname, 2013-Sage
FROM Student;
利用帶有 集合函數
和 GROUP BY
子句的查詢來定義的視圖稱爲分組視圖。
將學生的學號及他的平均成績定義爲一個視圖。
CREAT VIEW S_G(Sno, Gavg)
AS SELECT Sno, AVG(Grade)
FROM SC
GROUP BY Sno;
將Student表中所有女生記錄定義爲一個視圖。
CREATE VIEW F_Student(Sno,name,sex,age,dept)
AS SELECT *
FROM Student
WHERE Ssex='女';
3.8.3 刪除視圖
一個視圖被刪除後,由此視圖導出的其他視圖也將失效,應一一刪除。
DROP VIEW 視圖名;
3.8.4 查詢視圖
用戶可以像對基本表一樣對視圖進行查詢。
DBMS
執行對錶的查詢時,首先進行有效性檢查,若存在則從數據字典中取出涉及的視圖定義,把定義中的子查詢和用戶對視圖的查詢結合起來,轉換成對基本表的查詢。
將對視圖的查詢轉換爲對基本表的查詢的過程稱爲視圖的消解。
在數學系學生的視圖中找出年齡小於20歲的學生。
SELECT Sno, Sage
FROM MA_Student
WHERE Sage<20;
查詢數學系選修了1號課程的學生。
SELECT Sno, Sname
FROM MA_Student, SC
WHERE MA_Student.Sno=SC.Sno AND SC.Cno=1;
3.8.5 更新視圖
更新視圖包括 INSERT
DELETE
UPDATE
三類
由於視圖是不實際存儲數據的虛表,因此對視圖的更新最終要轉換爲對基本表的更新。
爲防止用戶通過視圖對數據進行增刪改時無意或故意操作不屬於視圖範圍內的基本表數據,可在定義視圖時加上 WITH CHECK OPTION
。
將數學系學生視圖MA_Student中學號爲20070001的學生姓名改爲“劉玲”。
UPDATE MA_Student
SET Sname='劉玲'
WHERE Sno=20070001;
向數學系學生視圖MA_Student中插入一個新的學生記錄,其中學號爲20070007,姓名爲趙新,年齡爲20歲。
INSERT
INTO MA_Student
VALUES(2007007, '趙新', 20);
刪除數學系學生視圖MA_Student中學號爲20070001。
DELETE
FROM MA_Student
WHERE Sno=20070001