關系數據庫標准語言 - SQL(Structed Query Language)
SQL在1974年提出
成功=正確的方法+努力+少說廢話 - 以夢為🐎,不負韶華 =》 Wangzz(2021年3月24日 22點52分)
SQL特點
- 在關系模型中實體和實體間的聯系均用關系表示。
- SQL是一種高度非過程化的語言,SQL在進行數據操作的時候,只要向數據庫引擎提出“做什么 - what to do"而不用指出“怎么做 - how to do”,因此無須了解存取路徑。存取路徑的選擇以及SQL的操作過程由系統自動完成。(極大提供數據獨立性)
- 面向集合的操作方式
非關系模型采用的是面向記錄的操作方式,操作對象是一條記錄。
SQL采用集合操作方式,不僅操作對象、查找結果可以是元組的集合,而且一次插入、刪除、更新操作的對象也可以是元組的集合。
SQL的9大動詞
SQL功能 | 動詞 |
---|---|
數據查詢(data query) | SELECT |
數據定義(data definition) | CREATE、ALTER、DROP |
數據操縱(data manipulation) | INSERT、UPDATE、DELETE |
數據控制(data control) | GRANT、REVOKE |
SQL基本概念(basic conception)
數據定義(Data definition)
- 一個關系DBMS的實例(instance)中可以創建多個數據庫(databases)
- 一個數據庫(database)可以建立多個模式(schemas)
- 一個模式(schema)可以建立多個表(table)、視圖(view)、索引(index)
基本表的定義、刪除與修改
數據類型 - 域(domain): 一組具有相同數據類型的值的集合
每一個屬性都是來自一個域,它的取值必須是域中的值。
數據類型 | 含義 |
---|---|
CHAR(n),CHARACTER(n) | 長度為n的定長字符串 |
VARCHAR(n),CHARACTERVARYING(n) | 長度為n的變長字符串 |
CLOB | 字符串大對象 |
BLOB | 二進制大對象 |
INT、INTEGER | 長整數(4 Byte) |
SMALLINT | 短整數(2 Byte) |
BIGINT | 大整數(8 Byte) |
NUMERIC(p, d) | 定點數,p位數字(不包括符合、小數點)組成,小數點后有d位數字 |
DECIMAL(p, d) | 與NUMERIC一樣 |
FLOAT(n) | 精度至少為n位數字 |
BOOLEAN | 邏輯布爾量 |
DATE | 日期,年、月、日,格式為YYYY-MM-DD |
TIME | 時間, 時、分、秒、格式為HH:MM:SS |
TIMESTAMP | 時間戳類型 |
INTERVAL | 時間間隔類型 |
定義表
CREATE TABLE SC
(
Sno CHAR(9),
Cno CHAR(4),
Grade SMALLINT,
PRIMARY KEY(Sno,Cno), /*主碼由兩個屬性構成,必須作為表級完整性進行定義*/
FOREIGN KEY(Sno) REFERENCES Student(Sno), /*表級完整性約束條件,Sno是外碼,被參照表是Student*/
FOREIGN KEY(Cno) REFERENCES Course(Cno) /*表級完整性約束條件,Cno是外碼,被參照表是Course*/
);
修改表
修改模板
ALTER TABLE <表名>
ADD COLUMN <新列名> <數據類型> [完整性約束]
ADD <表級別完整性約束>
DROP COLUMN <列名> [CASCADE|RESTRICT]
DROP CONSTRAINT <完整性約束名> [RESTRICT|CASCADE]
ALTER COLUMN <列名><數據類型>
DROP COLUMN <列名> [CASCADE | RESTRICT]區別:
DROP COLUMN <列名> CASCADE
自動刪除引用了改列的其他對象。
DROP COLUMN <列名> RESTRICT
如果該列被其他對象引用,DBMS則拒絕刪除該列。
SQL Server之中沒有 CASCADE和RESTRICT選項
索引的建立與刪除 - 索引是加快查詢速度的有效手段。
常見索引: B+樹索引(動態平衡)、散列索引(查找速度快)、位圖索引以及順序文件上的索引。
索引是RDBMS的內部實現技術(內模式)
索引加速數據的查詢但占用一定的存儲空間,當基本表更新的時候,索引進行相應的維護增加數據庫的負擔(按需創建索引)
建立索引
語句如下:
CREATE [UNIQUE][CLUSTER] INDEX <索引名>
ON
<表名> (<列名>[<次序>], <列名>[<次序>] ...);
次序: ASC升序或DESC降序
eg:
CREATE UNIQUE INDEX Stusno_indexes ON Student(Sno);
CREATE UNIQUE INDEX Coucno ON Course(Sno);
CREATE UNIQUE INDEX SCno ON SC(Sno ASC, Cno DESC);
UNIQUE和CLUSTER索引區別
MySQL的唯一限制和主鍵限制都是通過索引實現的。
- UNIQUE唯一索引:此索引的每一個索引值只對應唯一的數據記錄。
- CLUSTER聚簇索引: 是一種對磁盤上實際數據重新組織以按指定的一個或多個列的值排序。由於聚簇索引的索引頁面指針指向數據頁面,所以使用聚簇索引查找數據幾乎總是比使用非聚簇索引快。每張表只能建一個聚簇索引,並且建聚簇索引需要至少相當該,每張表只能建一個聚簇索引,並且建聚簇索引需要至少相當該表120%的附加空間,以存放該表的副本和索引中間頁。
修改索引名稱
ALTER INDEX <old_index_name> RENAME TO <new_index_name>
刪除索引
DROP INDEX <index_name>
數據字典(Data dictionary)
數據字典是RDBMS中的一組系統表,記錄數據庫中所有定義信息,包括關系模式定義、視圖定義、索引定義、各類用戶對數據庫的操作權限等
數據查詢
SELECT [ALL|DISTINCT] <目標列表達式>
FROM <表名或視圖名> [AS] <別名>
WHERE <條件表達式>
GROUP BY <列名1> HAVING <條件表達式>
ORDER BY <列名2> [ASC|DESC];
含義如下:
從FROM子句指定的基本表、視圖或派生表中找出滿足WHERE條件的元組
按SELECT子句中的目標列表達式選出元組中的屬性值形成結果表
如果有GROUP BY子句,將結果按<列名1>的值進行分組,該屬性列值相等
的元組為一個組。在每組中作用聚集函數。如果GROUP BY子句帶有HAVING短語
則滿足指定條件的組才予以輸出。
查詢滿足條件的元組
查詢條件 | 謂詞 |
---|---|
比較 | =,>,<,>=,<=,!=,<>,!>,!< |
確定范圍 | BETWEEN AND, NOT BETWEEN AND |
確定集合 | IN, NOT IN |
字符匹配 | LIKE, NOT LIKE |
空值 | IS NULL, IS NOT NULL |
多重條件(邏輯運算) | AND, OR, NOT |
- 查詢年齡在20~23歲之間(包括20歲和23歲)之間的學生的姓名、系別和年齡。
SELECT Sname, Sdept, Sage
FROM Student
WHERE Sage BETWEEN 20 AND 23;
- 查詢院系為CS、MA和IS學生的姓名和性別
SELECT Sname, Ssex
FROM Student
WHERE Sdept IN ('CS','MA','IS');
- 字符匹配
%: 匹配任意字符
_: 匹配一個字符
聚集函數
函數名稱 | 函數功能 |
---|---|
COUNT(*) | 統計元組個數 |
COUNT [DISTINCT | ALL] <列名> |
SUM [DISTINCT | ALL] <列名> |
AVG [DISTINCT | ALL] <列名> |
MAX [DISTINCT | ALL] <列名> |
MIN [DISTINCT | ALL] <列名> |
當聚集函數遇到空值的時候,除了COUNT(*)之外,都跳過空值而只處理非空值。
COUNT對元組計數,某個元組的一個或部分列為空值不影響COUNT的統計結果
聚集函數只能使用在SELECT子句和GROUP BY的HAVING子句之中
- 查詢選修了三門以上課程的學生學號
mysql> SELECT * FROM sc;
+-----------+-----+-------+
| sno | cno | grade |
+-----------+-----+-------+
| 201215121 | 1 | 92 |
| 201215121 | 2 | 85 |
| 201215121 | 3 | 88 |
| 201215122 | 2 | 90 |
| 201215122 | 3 | 80 |
+-----------+-----+-------+
5 rows in set (0.00 sec)
mysql> SELECT sno
-> FROM sc
-> GROUP BY sno
-> HAVING COUNT(*) >= 3;
+-----------+
| sno |
+-----------+
| 201215121 |
+-----------+
1 row in set (0.00 sec)
- WHERE子句與HAVING短語的區別
a. WHERE子句作用域基本表或視圖從中選擇滿足條件的分組。
b. HAVING短語作用域組(即只能和GROUP BY 子句一起使用從中選擇滿足條件的組)。
連接查詢🔗
連接查詢分類:
- 等值連接查詢(保留重復列)
- 自然連接查詢(去除重復列)
- 非等值連接查詢
- 自身連接查詢
- 外連接查詢
- 復合條件連接查詢
等值連接查詢 - 連接運算符為 = 時
連接字段的要求是各連接字段類型必須是可比的但名字不必相同。
mysql> SELECT Student.*, SC.*
-> FROM Student, SC
-> WHERE Student.Sno = SC.Sno;
+-----------+-------+------+------+-------+-----------+-----+-------+
| sno | sname | ssex | sage | sdept | sno | cno | grade |
+-----------+-------+------+------+-------+-----------+-----+-------+
| 201215121 | 李勇 | 男 | 20 | CS | 201215121 | 1 | 92 |
| 201215121 | 李勇 | 男 | 20 | CS | 201215121 | 2 | 85 |
| 201215121 | 李勇 | 男 | 20 | CS | 201215121 | 3 | 88 |
| 201215122 | 劉晨 | 女 | 19 | CS | 201215122 | 2 | 90 |
| 201215122 | 劉晨 | 女 | 19 | CS | 201215122 | 3 | 80 |
+-----------+-------+------+------+-------+-----------+-----+-------+
執行該連接操作的過程是在Student中選取一個元組在通過SC表依次選取元組進行字段比對
如果比對成功則進行Student中元組與SC表中元組拼接形成結果表中的一個元組,全部查找玩之后
再找Student中第二個元組。
自然連接查詢 - 即去掉在等值連接中出現重復性屬性列
mysql> SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
-> FROM Student, SC
-> WHERE Student.Sno = SC.Sno;
+-----------+-------+------+------+-------+-----+-------+
| Sno | Sname | Ssex | Sage | Sdept | Cno | Grade |
+-----------+-------+------+------+-------+-----+-------+
| 201215121 | 李勇 | 男 | 20 | CS | 1 | 92 |
| 201215121 | 李勇 | 男 | 20 | CS | 2 | 85 |
| 201215121 | 李勇 | 男 | 20 | CS | 3 | 88 |
| 201215122 | 劉晨 | 女 | 19 | CS | 2 | 90 |
| 201215122 | 劉晨 | 女 | 19 | CS | 3 | 80 |
+-----------+-------+------+------+-------+-----+-------+
5 rows in set (0.00 sec)
- 查詢選修2號課程且成績在90分以上的所有學生的學號和姓名
mysql> SELECT Student.Sno, Student.Sname
-> FROM Student, SC
-> WHERE Student.Sno = SC.Sno
-> AND
-> SC.Cno = 2
-> AND
-> SC.Grade >= 90;
+-----------+-------+
| Sno | Sname |
+-----------+-------+
| 201215122 | 劉晨 |
+-----------+-------+
1 row in set (0.03 sec)
mysql> SELECT *
-> FROM SC;
+-----------+-----+-------+
| sno | cno | grade |
+-----------+-----+-------+
| 201215121 | 1 | 92 |
| 201215121 | 2 | 85 |
| 201215121 | 3 | 88 |
| 201215122 | 2 | 90 |
| 201215122 | 3 | 80 |
+-----------+-----+-------+
5 rows in set (0.00 sec)
WHERE Student.Sno = SC.Sno AND SC.Cno = '2' AND SC.Grade > 90;
一種優化(高效)的執行過程,先從SC中挑選出Cno='2'並且Grade>90的元組形成一個中間關系。再和Student中滿足條件的元組連接得到最終的結果關系。
自身連接
表連接的操作不僅可以在表之間進行也可以表與自身進行連接;
mysql> SELECT *
-> FROM Course;
+-----+------------+------+---------+
| cno | cname | cpno | ccredit |
+-----+------------+------+---------+
| 1 | 數據庫 | 5 | 4 |
| 2 | 數學 | NULL | 2 |
| 3 | 信息系統 | 1 | 4 |
| 4 | 操作系統 | 6 | 3 |
| 5 | 數據結構 | 7 | 4 |
| 6 | 數據處理 | NULL | NULL |
| 7 | PASCAL語言 | 6 | 4 |
+-----+------------+------+---------+
7 rows in set (0.00 sec)
mysql> SELECT first.cname, '間接選修課為: ', second.cname
-> FROM Course first, Course second
-> WHERE first.cpno = second.cno;
+------------+----------------+------------+
| cname | 間接選修課為: | cname |
+------------+----------------+------------+
| 數據庫 | 間接選修課為: | 數據結構 |
| 信息系統 | 間接選修課為: | 數據庫 |
| 操作系統 | 間接選修課為: | 數據處理 |
| 數據結構 | 間接選修課為: | PASCAL語言 |
| PASCAL語言 | 間接選修課為: | 數據處理 |
+------------+----------------+------------+
外連接 (outer join)
左外連接
若某個學生沒有選課,仍然把Student的懸浮元組保存在結果關系中,而在SC表的屬性上填空值NULL
mysql> SELECT Student.Sno, Sname, Ssex, Sage, Cno, Grade
-> FROM Student LEFT OUTER JOIN SC
-> ON Student.Sno = SC.Sno;
+-----------+-------+------+------+------+-------+
| Sno | Sname | Ssex | Sage | Cno | Grade |
+-----------+-------+------+------+------+-------+
| 201215121 | 李勇 | 男 | 20 | 1 | 92 |
| 201215121 | 李勇 | 男 | 20 | 2 | 85 |
| 201215121 | 李勇 | 男 | 20 | 3 | 88 |
| 201215122 | 劉晨 | 女 | 19 | 2 | 90 |
| 201215122 | 劉晨 | 女 | 19 | 3 | 80 |
| 201215123 | 王敏 | 女 | 18 | NULL | NULL |
| 201215125 | 張立 | 男 | 19 | NULL | NULL |
+-----------+-------+------+------+------+-------+
7 rows in set (0.00 sec)
右外連接
mysql> SELECT Student.Sno, Sname, Ssex, Sage, Cno, Grade
-> FROM Student RIGHT OUTER JOIN SC
-> ON Student.Sno = SC.Sno;
+-----------+-------+------+------+-----+-------+
| Sno | Sname | Ssex | Sage | Cno | Grade |
+-----------+-------+------+------+-----+-------+
| 201215121 | 李勇 | 男 | 20 | 1 | 92 |
| 201215121 | 李勇 | 男 | 20 | 2 | 85 |
| 201215121 | 李勇 | 男 | 20 | 3 | 88 |
| 201215122 | 劉晨 | 女 | 19 | 2 | 90 |
| 201215122 | 劉晨 | 女 | 19 | 3 | 80 |
+-----------+-------+------+------+-----+-------+
5 rows in set (0.00 sec)
嵌套查詢 - (SELECT - FROM - WHERE (SELECT - FROM - WHERE))
將一個查詢快嵌套在另一個查詢快的WHERE子句或HAVING短語的條件中的查詢稱為嵌套查詢(nested query)
mysql> SELECT Sno, Sname, Ssex, Sage
-> FROM Student
-> WHERE Sno
-> IN
-> (SELECT Sno
-> FROM Course);
+-----------+-------+------+------+
| Sno | Sname | Ssex | Sage |
+-----------+-------+------+------+
| 201215121 | 李勇 | 男 | 20 |
| 201215122 | 劉晨 | 女 | 19 |
| 201215123 | 王敏 | 女 | 18 |
| 201215125 | 張立 | 男 | 19 |
+-----------+-------+------+------+
子查詢中不能使用order by子句(子查詢只是為父查詢提供可選條件order by的使用也沒有意義當然也是不能使用的!)
ORDER BY子句只能對最終查詢結果排序。
ANY(SOME)、ALL謂詞與聚集函數、IN謂詞的等價轉換關系
= | <>或!= | < | <= | > | >= | |
---|---|---|---|---|---|---|
ANY | IN | -- | <MAX | <=MAX | >MIN | >=MIN |
ALL | -- | NOT IN | <MIN | <=MIN | >MAX | >=MAX |
集合查詢
SELECT查詢結果是元組的集合,多個SELECT語句可以進行集合操作。集合操作包括:【並-UNION】【差-EXCEPT】【交-INTERSECT】.
參加集合操作的各查詢結果的列數必須相同;對應項的數據類型也必須相同。
視圖
🍎視圖是一個或幾個基本表導出的表(虛表)。(是對基本表中的數據查詢的過程和結果數據組織的定義)
視圖定義模板
CREATE VIEW <視圖名> [<列名1><列名2><列名3>...]
AS
<子查詢>
[WITH CHECK OPTION]
WITH CHECK OPION表示對視圖進行DML(INSERT、UPDATE、DELETE)等操作的時候要保證插入、更新和刪除的行滿足視圖定義中的謂詞條件(子查詢中條件表達式)
CREATE VIEW結果是把視圖的定義存入數據字典並不執行其中的SELECT語句。只是在對視圖查詢的時候才按視圖的定義從基本表中將數據檢索出來。
示例
CREATE VIEW IS_Student
AS
SELECT Sno, Sname, Sage
FROM Student
WHERE Sdept = 'IS'
WITH CHECK OPTION;
由於添加了WITH CHECK OPTION當進行增、刪、改的時候保證數據符合WHERE中的條件表達式即自動添加【Sdept = 'IS'】.
WHERE子句是不能用聚集函數作為條件表達式的,因此執行此修正后的查詢將會出現語法錯誤!
錯誤的寫法❌
SELECT Sno, AVG(Grade)
FROM SC
WHERE AVG(Grade) >= 90
GROUP BY Sno;
正確的寫法✔
SELECT Sno, AVG(Grade)
FROM SC
GROUP BY Sno
HAVING AVG(Grade) >= 90;
視圖一旦定義,則永久保存在【數據字典】之中,之后的所有查詢都是直接引用該視圖。
派生表只是在語句執行的時候臨時定義,語句執行完畢后立即被刪除!
eg:
SELECT *
FROM
(SELECT Sno, AVG(Grade)
FROM SC
GROUP BY Sno) AS S_G(Sno, Gavg) /* 子查詢生成一個派生表 S_G*/
WHERE Gavg >= 90;
更新視圖
更新視圖通過對視圖來插入(INSERT)、刪除(DELETE)和修改(UPDATE)數據。
視圖不是實際存儲數據的實表,所有對視圖的更新都會轉換為對基本表的更新。
一般不推薦通過視圖對基本表中的數據進行更新。
視圖的作用
視圖最終定義在基本表之上,對視圖的一切操作最終要轉換為對基本表的操作。
好處如下:
- 視圖能夠簡化用戶的操作
- 視圖讓用戶以多種角度看待同一數據
- 視圖對重構數據庫提供一定程序的邏輯獨立性
- 視圖能夠對機密數據提供安全保護
- 適當利用視圖能夠清晰地表達查詢
習題
1. SQL語言特點:
② 高度非過程化。SQL語言進行數據操作,只要提出做什么而不用指明怎么做。
③ 面向集合的操作方式。SQL語言采用集合的操作方式,不僅操作對象、查找結果是元素的集合而且一次插入、刪除、更新操作的對象也可以是元組的集合。
④ 同一種語法結構提供兩種使用方式。 SQL語言是自含式語言也是嵌入式語言。
SQL作為自含式語言能夠獨立地用於聯機交互的使用方式
SQL作為嵌入式語言能夠嵌入到其他高級語言程序中
⑤ 語言簡潔,易學易用。
2.
① SELECT * FROM S WHERE A = 10;
② SELECT A, B FROM S;
③ SELECT A,B,T.C,T.D,E,F FROM S, T WHERE S.C = T.C AND S.D = T.D;
④ SELECT * FROM S, T WHERE S.C = T.C;
⑤ SELECT * FROM S, T WHERE S.A < T.E;
⑥ SELECT S.A,S.D, T.* FROM S,T;
3.
1. 找出所有供應商的姓名和所在城市;
SELECT SNAME, CITY FROM S;
2. 找出所有零件的名稱、顏色、重量;
SELECT PNAME, COLOR, WEIGHT FROM P;
3. 找出使用供應商S1所供應零件的工程號碼;
SELECT PNO FROM SPJ WHERE SNO = 'S1';
4. 找出工程項目J2使用的各種零件的名稱以及數量;
SELECT P.Pname, COUNT(Pno)
FROM SPJ
INNER JOIN P ON P.PNO = SPJ.PNO
WHERE JNO = 'J2'
GROUP BY PNO;
5. 找出上海廠商供應的所有零件號碼;
SELECT P.PNO
FROM P
INNER JOIN SPJ ON P.PNO = SPJ.PNO
INNER JOIN S ON S.SNO = SPJ.SNO
WHERE S.CITY = '上海';
6. 找出使用上海產的零件的工程名稱;
SELECT J.JNAME
FROM J
INNER JOIN SPJ ON J.JNO = SPJ.JNO
INNER JOIN S ON S.SNO = SPJ.SNO
WHERE S.CITY = '上海';
7. 找出沒有使用天津產的零件的工程名稱;
SELECT J.JNAME
FROM J
INNER JOIN SPJ ON J.JNO = SPJ.JNO
INNER JOIN S ON S.SNO = SPJ.SNO
WHERE S.CITY != '天津';
8. 把全部紅色零件的顏色改成藍色;
UPDATE P
SET COLOR = '藍'
WHERE COLOR = '紅';
9. 由S5供給J4零件的P6改成由S3供應;
UPDATE SPJ
SET SNO = 'S3'
WHERE SNO = 'S5' AND JNO = 'J4' AND PNO = 'P6';
10. 從供應商關系中刪除S2的記錄,並從供應情況關系中刪除相應的記錄;
A、DELETE FROM S WHERE SNO = 'S2';
B、DELETE FROM SPJ WHERE SNO = 'S2';
11. 將(S2, J6, P4, 200)插入供應情況表;
INSERT INTO SPJ(SNO, PNO, JNO, QTY)
VALUES('S2', 'J6', 'P4', 200);
4. 什么是基本表?什么是視圖?兩者的區別和練習是什么?
視圖:從一個或幾個基本表或視圖導出的表。視圖本身不獨立存儲在數據庫中,是一個虛表。
即數據庫中只存放視圖的定義而不存放視圖對應的數據,這些數據仍然存放在視圖的基本表中。
5. 數據庫內外連接的區別?
外連接:連接結果不僅包含符合連接條件的行同時也包含自身不符合條件的行。包括左外連接、右外連接和全外連接。
- 左外連接就是以左表為准,去匹配右表,左表有多少條數據,結果就是多少條數據
- 右外連接就是與左外連接反之,以右表為准,去匹配左表,右表有多少條數據,結果就是多少條數據
- 全外連接數據條數不一定,相當與是左外連接 和右外連接 的綜合