關係數據庫標準語言SQL
3.1 SQL概述
3.1.2 SQL的特點
-
高度非過程化
-
功能完並且一體化
-
統一的語法結構
-
語言簡潔,易學易用
數據查詢:
SELECT
數據定義:
CREATE
,DROP
數據操作:
INSERT
,UPDATE
,DELETE
數據控制:
GRANT
,REVOKE
3.2 SQL的定義功能
3.2.1基本表的定義
1.表結構的定義
CREATE TABLE<表名>
(<列名><數據類型>[列表完整性約束條件]
[,<列名><數據類型>[列表完整性約束條件]···]
[,<表級完整性約束條件>]
);
- 表名是所要定義的基本表的名字,表可以由一個或多個屬性(列)組成
- 定義表的各個列時需要指明其數據類型及長度
類型 | 數據類型舉例及縮寫 | 說明 |
---|---|---|
Binary | BLOB | 以十六進制格式存儲二進制字符串的值 |
BitString | BIT(n) BIT VARYING(n) |
這兩種數據類型可以存儲二進制和十六進制數據 |
Boolean | BOOLEAN | true、false或unknow |
Character | CHAR(n) VARCHAR(n) |
存儲適宜的字符集中的任意字符組合 |
Numeric | INTEGER SMALLINT DECIMAL(i,j) FLOAT(p,s) REAL DOUBLE PERCISION |
這些數據類型存儲數據的準確值(整數或小數)或近似值 |
Temporal | DATE TIME TIMESTAMP INTERVAL |
這些數據類型處理時間的值 |
- 完整性約束條件:
Primary Key
Foreign Key
【例3-1】
CREATE TABLE 學生
(學號 char(8) NOT NULL UNIQUE,
姓名 char(8),
性別 char(2),
出生年份 SMALLINT,
籍貫 char(8),
學院 char(15));
2.主關鍵詞的定義
(1)在列出關係模型的屬性時,在屬性及其類型後加上保留字PRIMARY KEY
(2)在列出關係模型的所有屬性後,再附加一個聲明:
PRIMARY KEY(<屬性1>[,<屬性2>,···])
【例3-2】
- 方法一
CREATE TABLE 學生
(學號 char(8) PRIMARY KEY,
姓名 char(8),
性別 char(2),
出生年份 SMALLINT,
籍貫 char(8),
學院 char(15));
- 方法二
CREATE TABLE 學生
(學號 char(8),
姓名 char(8),
性別 char(2),
出生年份 SMALLINT,
籍貫 char(8),
學院 char(15)
PRIMARY KEY(學號));
【例3-3】
CREATE TABLE 課程
(課程號 SMALLINT NOT NULL UNIQUE,
課程名 char(15),
學時 SMALLINT,
開課學期 char(4),
課程性質 char(15),
primary key(課程號));
【例3-4】
CREATE TABLE 學習
(學號 char(8),
課程號 char(8),
成績 smallint,
primary key(學習,課程號));
3. 外部關鍵字的定義
(1)如果外部關鍵詞只有一個屬性,可以在它的屬性名和類型後面直接用REFERENCES
說明它參照了某個表的某些屬性(必須是PRIMARY KEY
)
REFERENCES <表名> (<屬性>)
(2) 在屬性列後面添加
FOREIGN KEY(<屬性 1>REFERENCES<表名>(<屬性2>))
【例3-5】
CREATE TABLE 學習
(學號 char(8),
課程號 char(8),
成績 smallint,
primary key(學習,課程號)
FOREIGN KEY(學號 references 學生(學號))
FOREIGN KEY(課程號 references 課程(課程號));
4.默認值的定義
性別 char(2) default '男';
年齡 smallint default 19;
3.2.2 基本表的修改和刪除
ALTER TABLE 學生 ADD COLUMN 年齡 SMALLINT;
ALTER TABLE 課程 ALTER COLUMN 課程名 CHAR(20);
ALTER TABLE 學生 DROP COLUMN 年齡;
DROP TABLE <表名>
3.2.3 索引的建立和刪除
3.3 數據查詢
SELECT [ALL|DISTINCT]<屬性列表>
FROM <表名或視圖名>[,[表名或視圖名]]···
[WHERE <條件表達式>]
[GROUP BY <列名>]
[HAVING <條件表達式>]
[ORDER by<列名>[]];
3.3.1 單表查詢
- 選擇表中的若干列(投影)
- 選擇表中的若干元組(選擇)
- 對查詢進行分組
- 使用集函數
- 對查詢結果排序
1.SQL中的投影
【例3-12】
SELECT 姓名,籍貫
FROM 學生;
【例3-13】
SELECT DISTINCT 籍貫
FROM 學生;
【例3-14】
SELECT *
FROM 學生;
【例3-15】
查詢學生學號和年齡
select 學號,year(now())-出生年份
from 學生;
【例3-16】
給列表別名
select 學號,year(now())-出生年份 as 年齡
from 學生;
2. SQL中的選擇運算
查 詢 條 件 | 謂 詞 |
---|---|
比較 | =, <>, >, <, >=, <= |
算數運算 | +,-,*,/ |
確定範圍 | BETWEEN AND, NOT BETWEEN AND |
確定集合 | IN, NOT IN |
字符匹配 | LIKE, NOT LIKE |
空值 | IS NULL, IS NOT NULL |
多重條件 | AND,OR |
1)比較運算
【例3-17】
查詢所有不及格課程的學生的學號,課程號及成績
select 學號,課程號,成績
from 學習
where 成績<60;
【例3-18】
查詢有不及格課程的學生的學號
select distinct 學號
from 學習
where 成績<60;
2)多重運算和算術運算
【例3-19】
在學生表中找出信電學院2000年後出生的學生的記錄
select *
from 學生
where 學院='信電' and 出生年份>2000;
3)確定範圍
【例3-20】
select 姓名,性別,學院,出生年份
from 學生
where 出生年份 between 1996 and 1998;
4)確定集合
【例3-21】
select 學號,姓名,出生年份
from 學生
where 學院 in ('信電','理學院','計算機');
5)字符匹配
[not] like '<匹配串>' [ESCAPE'<轉碼字符>']
6)空值
3.對查詢結果進行分組
select 課程號,count(學號) as 選課人數
from 學習
group by 課程號;
【例3-27】
select 學號,count(課程號) as 選修課程數
from 學習
where 學號 between '091501' and '091506'
group by 學號
having 選修課程數>3;
4.使用集函數
COUNT([DISTINCT|ALL]*) #統計原則個數
COUNT([DISTINCT|ALL]<列名>)#統計一列中值的個數
SUM([DISTINCT|ALL]<列名>)#計算一列值的總和
AVG([DISTINCT|ALL]<列名>)#平均值
MAX([DISTINCT|ALL]<列名>)#最大值
MIN([DISTINCT|ALL]<列名>)#最小值
#查詢學生總人數
select count(*)
from 學生;
#查詢計算機學院學生的平均年齡
select avg(year(now())-出生年份) as 平均年齡 #別忘了別名
from 學生
where 學院='計算機';
#查詢學習180101號課程的學生最高分數
select max(成績) as 最高分
from 學習
where 課程號='180101'
5.對查詢結果排序
select 學號,成績
from 學習
where 課程='180102'
order by 成績 desc;
查詢全體學生情況,查詢結果按所在學院的名稱升序排列,對同一學院中給的學生按年齡降序排列
select *
from 學生
order by 學院 asc, year(now())-出生年份 desc;
3.3.2 連接查詢
- 等值連接和非等值連接
- 自身連接查詢
- 外連接查詢
- 複合條件連接查詢
- 集合運算查詢
(1)ANSI 方式
【例3-33】
#查詢每個學生及其選修課程的情況
select 學生.*,學習.*
from 學生 INNER JOIN 學生.學號=學習.學號;
(2) theta方式
select 學生.*,學習.*
from 學生,學習
where 學生.學號=學習.學號;
1.等值與非等值連接查詢
[<表名1>.]<列名1><比較運算符>[<表名2>.]<列名> #比較運算符爲=時爲等值連接
#自然連接“學生表”和“學習表”
select 學生.學號,姓名,性別,出生年份,學院,課程號,成績
from 學生,學習
where 學生.學號=學習.學號
2.自身連接查詢
#求一門課程的間接先修課
select first.課程號 as 課程號,first.課程名 as 課程名,second.課程名 as 間接選修課
from 課程 as first,課程 as second
where first.先修課課程號=second.課程號;
3. 外連接查詢
1)左外連接
規定所有記錄都應該從連接語句左側的表中返回。當右側表中沒有匹配的記錄時,左表中該記錄依然會返回,而右側表中的列值將自動填充NULL 值
#查詢所有學生的姓名以及他們選修課程的課程號和成績
select 姓名,課程號,成績
from 學生,學習
where 學生.學號(+)=學習.學號;
2) 右外連接
規定所有記錄都應該從連接語句右側的表中返回。當右側表中沒有匹配的記錄時,左表中該記錄依然會返回,而右側表中的列值將自動填充NULL 值
4.複合條件連接查詢
#查詢選修180101號課程且成績在90分以上的學生學號,姓名以及成績
select 學生.學號,姓名,成績
from 學生,學習
where 學生.學號=學習.學號
and 課程號='180101'
and 成績>90;
#ANSI
select 學生.學號,姓名,成績
from 學生 JOIN on 學生.學號=學習.學號
and 課程號='180101'
and 成績>90;
#查詢每個學生及其選修的課程名及其成績
select 學生.學號,姓名,課程名,成績
from 學生,課程,學習
where 學生.學號=學習.學號
and 學習.課程號=課程.課程號;
#ANSI
select 學生.學號,姓名,課程名,成績
from 學生
JOIN 學習 on 學生.學號=學習.學號
JOIN 課程 on 學習.課程號=課程.課程號;
5.集合運算連接查詢
- 並:
UNION
- 交:
INTERSECT
- 差:
EXCEPT
#查詢選修了180101號或180102號課程或二者都選修了的學生學號、課程號和成績
(select 學生.學號,課程號,成績
from 學生,學習
where 學生.學號=學習.學號 and 課程號='180101')
union
(select 學生.學號,課程號,成績
from 學生,學習
where 學生.學號=學習.學號 and 課程號='180102')
3.3.3 嵌套查詢
- 相關子查詢
- 不相關子查詢
1. 帶有IN謂詞的子查詢
#查詢選修了“數據庫原理”課程的學生學號和姓名
select 學號,姓名
from 學生
where 學號 in
(select 學號
from 學習
where 課程號 in
(select 課程號
from 課程
where 課程名='數據庫原理'));
#用IN來實現交運算,大部分DBMS不支持INTERSECT
SELECT 學號,課程號,成績
from 學習
where 課程號='180101' and 學號 in
(select 學號
from 學習
where 課程號='180102' )
#NOT IN 差運算
SELECT 學號,課程號,成績
from 學習
where 課程號='180101' and 學號 not in
(select 學號
from 學習
where 課程號='180102' )
2.帶有比較運算符的查詢
3.帶有ANY或ALL謂詞的子查詢
#查詢其他學院比計算機學院某個學生年齡小的學生名單
select 姓名
from 學生
where year(now())-出生年份 < ANY
(select year(now())-出生年份
from 學生
where 學院='計算機')
and 學院!='計算機'
order by year(now())-出生年份 desc;
4.帶有EXISTS謂詞的子查詢
#EXISTS實現交運算
SELECT s1.學號,s1.課程號,s1.成績
from 學習 as s1
where s1.課程號='180101' and exists
(select *
from 學習 as s2
where s2.課程號='180102' and s1.學號=s1.學號);
#EXISTS實現差運算
SELECT s1.學號,s1.課程號,s1.成績
from 學習 as s1
where s1.課程號='180101' and not exists
(select *
from 學習 as s2
where s2.課程號='180102' and s1.學號=s1.學號);
#選修過全部課程的學生的學號和姓名
select 學號,姓名
from 學生
where not exists
(select *
from 課程
where not exists
(select *
from 學習
where 學習.學號=學生.學號 and 學習.課程號=課程.課程號 )
)
#查詢至少選修了091501號學生選修的全部課程的學生學號
select 學號
from 學生
where not exists
(select *
from 學習 as First
where First.學號='091501' and not exists
(select *
from 學習 as Second
where Second.學號=學生.學號 and Second.課程號=First.課程號))
3.4 數據更新
- 插入
- 刪除
- 修改
3.4.1 插入數據
1.插入單個元組
INSERT
INTO <表名> [<屬性列>]
Values (<常量1>[,<常量2>···])
INSERT INTO 學習(學號,課程號)
VALUES('091530','080102')
2.插入子查詢結果
INSERT
INTO <表名> [<屬性列>]
子查詢;
#統計每門課的平均分
CREATE TABLE 課程平均分
(課程號 CHAR(8)
課程名 CHAR(15)
平均分 DOUBLE);
INSERT
INTO 課程平均分(課程號,課程名,平均分)
SELECT 課程號,課程名,AVG(成績)
FROM 課程,學習
WHERE 課程.課程號=學習.課程號
GROUP BY 課程號,課程名;
3.4.3修改數據
UPDATE <表名>
SET <列名>=<表達式>
[WHERE <條件>];
1.更改表中一個元組
UPDATE 學生
SET 籍貫='江蘇'
WHERE 學號='091611';
2.更新表中多個元組的數據
#將180101號課程的成績增加一分
UPDATE 學習
SET 成績=成績+1
WHERE 課程號='180101';
3.帶子查詢的修改
UPDATE 學習
SET 成績=0
WHERE 學號 IN
(SELECT 學號
FROM 學生
WHERE 學院='計算機');
3.5 視圖
3.5.1 建立視圖
create view <視圖名>[(<列名>)]
as <子查詢>
[WITH CHECK OPTION];
WITH CHECK OPTION
表示對視圖進行插入、刪除和更新操作時要保證發生變動的行慢則視圖定義中的謂詞條件(即子查詢中的條件)
#建立計算機學院選修了“數據庫原理”這門課的學生的視圖
CREATE VIEW DB_S1
AS
SELECT 學生,學號,姓名,籍貫,學院,成績
FROM 學習,學生,課程
WHERE 學院='計算機'AND學生.學號=學習.學號 AND 學習.課程號=課程.課程號 and 課程名='數據庫原理'
#定義一個反映學生年齡的視圖
CREATE VIEW BT_S(學號,姓名,年齡)
as
SELECT 學號,姓名,year(now())-出生年份 AS 年齡
FROM 學生