實驗2 SQL語言—SELECT查詢操作
實驗目的要求
- 掌握SQL程序設計基本規范,熟練運用SQL語言實現數據基本查詢,包括單表查詢、分組統計查詢和連接查詢。
- 掌握SQL嵌套查詢和集合查詢等各種高級查詢的設計方法等。
- 要求學生掌握SQL Server查詢分析器和T-SQL語言的使用方法,熟練掌握和使用簡單表的數據查詢﹑數據排序和數據連接查詢﹑嵌套查詢等操作方法。
實驗儀器設備
- 學生每個一台PC機
- 已安裝SQL Server環境
實驗主要內容
- 針對SQL Server數據庫設計各種單表查詢語句、分組統計查詢語句;設計單個表針對自身的連接查詢,設計多個表的連接查詢。理解和掌握SQL查詢語句各個子句的特點和作用,按照SQL程序設計規范寫出具體的SQL查詢語句,並調試通過。
- 針對SQL Server數據庫,正確分析用戶查詢要求,設計各種嵌套查詢和集合查詢。
本次實驗基於圖書發行數據庫系統,進行實驗
實驗原理
單表查詢
單表查詢是指僅涉及一個表的查詢
SELECT子句后面不僅可以是表中的屬性列,還可以是表達式、字符串常量、函數
DISTINCT
:取消取值重復的行|SELECT DISTINCT LNO
保留取值重復的行將DISTINCT換成ALL,不加則默認ALL
換碼、通配符
%_
和ESCAPE
對一個或多個屬性列進行排序,
ORDER BY
子句|ORDER BY [屬性列名] ASC|DESC
|ASC升序,DESC降序聚集函數(放在SELECT后面)
COUNT(*) --統計元組個數 COUNT([DISTINCT|ALL]<列名>) --統計一列中值的個數 SUM(DISTINCT|ALL]<列名>) --統計一列值的總和(必須是數值型) AVG([DISTINCT|ALL]<列名>) --統計一列值的平均值(必須是數值型) MAX([DISTINCT|ALL]<列名>) --統計一列值的最大值 MIN([DISTINCT|ALL]<列名>) --統計一列值的最小值
GROUP BY子句:
GROUP BY
將查詢結果按某一列或多列的值進行分組,值相等的為一組
HAVING
:作用於組,從中選擇滿足條件的組查詢選修了三門以上課程的學生的學號 SELECT SNO FROM SC GROUP BY SNO HAVING COUNT(*)>3
連接查詢
一個查詢同時涉及兩個及以上表的稱為連接查詢,屬性列名前面加上表名,即SC.Sno
等值連接查詢
連接運算符為=時稱為等值連接
非等值連接查詢
連接運算符不是=時稱為非等值連接
自然連接
若在等值連接中把目標列中重復的屬性列去掉則為自然連接
單個表的自身連接查詢
查詢每一門課的間接選修課
SELECT FIRST.Cno,SECOND.Cpno
FROM Course FIRST,Course SECOND
WHERE FIRST.Cpno=SECOND.Cno;
多表連接
查詢每個學生的學號、姓名、選秀的課程名及成績(涉及三個表的查詢)、
SELECT Student.Sno,Sname,Cname,Grade
FROM Student,SC,Course
WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno
嵌套查詢
將一個查詢塊嵌套在另一個查詢塊的WHERE子句或者HAVING短語的條件中的查詢稱為嵌套查詢
子查詢
- 帶有IN謂詞的子查詢
- 帶有比較運算符的子查詢
- 帶有ANY(SOME)或ALL謂詞的子查詢
- 帶有EXIST謂詞的子查詢
集合查詢
集合操作主要包括並操作UNION、交操作INTERSECT和差操作EXCEPT
實驗記錄
檢索L1從書店S1購買的圖書的書號及其冊數;
SELECT BNO,QTY
FROM 圖書發行
WHERE LNO='L1'AND SNO='S1';

檢索館址在“上海”的圖書館及其電話號碼;
SELECT LNAME,TEL
FROM 圖書館
WHERE CITY='上海';
檢索L4收藏圖書的書名;
SELECT 圖書.BNAME
FROM 圖書,圖書發行
WHERE 圖書發行.LNO='L4'AND 圖書發行.BNO=圖書.BNO;
檢索S3發行的圖書書名及數量;
SELECT 圖書.BNAME,圖書發行.QTY
FROM 圖書,圖書發行
WHERE 圖書發行.SNO='S3'AND 圖書發行.BNO=圖書.BNO;
檢索收藏圖書“數據庫設計”的館名;
SELECT 圖書館.LNAME
FROM 圖書館,圖書發行,圖書
WHERE 圖書.BNAME='數據庫設計'AND 圖書.BNO=圖書發行.BNO
AND 圖書館.LNO=圖書發行.LNO;
檢索沒有購買上海新華書店出售的圖書的圖書館號LNO;
SELECT LNO,LNAME
FROM 圖書館
WHERE LNO NOT IN (SELECT 圖書發行.LNO
FROM 圖書發行,書店
WHERE 圖書發行.SNO=書店.SNO AND
書店.SNAME='上海新華書店');
思考題
-
如何提高數據查詢和連接速度。
1.對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。
2.應盡量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num is null
可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢:
select id from t where num=0
3.應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。
4.應盡量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num=10 or num=20
可以這樣查詢:
select id from t where num=10
union all
select id from t where num=20
5.in 和 not in 也要慎用,否則會導致全表掃描,如:
select id from t where num in(1,2,3)
對於連續的數值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6.下面的查詢也將導致全表掃描:
select id from t where name like '%abc%'
若要提高效率,可以考慮全文檢索。
7.如果在 where 子句中使用參數,也會導致全表掃描。因為SQL只有在運行時才會解析局部變量,但優化程序不能將訪問計划的選擇推遲到運行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計划,變量的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:
select id from t where num=@num
可以改為強制查詢使用索引:
select id from t with(index(索引名)) where num=@num
8.應盡量避免在 where 子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where num/2=100
應改為:
select id from t where num=1002
9.應盡量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where substring(name,1,3)='abc'--name以abc開頭的id
select id from t where datediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id
應改為:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'
10.不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
11.在使用索引字段作為條件時,如果該索引是復合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應盡可能的讓字段順序與索引順序相一致。
12.不要寫一些沒有意義的查詢,如需要生成一個空表結構:
select col1,col2 into #t from t where 1=0
這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:
create table #t(...)
13.很多時候用 exists 代替 in 是一個好的選擇:
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists(select 1 from b where num=a.num)
14.並不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重復時,SQL查詢可能不會去利用索引,如一表中有字段sex,male、female幾乎各一半,那么即使在sex上建了索引也對查詢效率起不了作用。
15.索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。
16.應盡可能的避免更新 clustered 索引數據列,因為 clustered 索引數據列的順序就是表記錄的物理存儲順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引數據列,那么需要考慮是否應將該索引建為 clustered 索引。
17.盡量使用數字型字段,若只含數值信息的字段盡量不要設計為字符型,這會降低查詢和連接的性能,並會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對於數字型而言只需要比較一次就夠了。
18.盡可能的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長字段存儲空間小,可以節省存儲空間,其次對於查詢來說,在一個相對較小的字段內搜索效率顯然要高些。
19.任何地方都不要使用 select * from t ,用具體的字段列表代替“”,不要返回用不到的任何字段。
20.盡量使用表變量來代替臨時表。如果表變量包含大量數據,請注意索引非常有限(只有主鍵索引)。
21.避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。
22.臨時表並不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重復引用大型表或常用表中的某個數據集時。但是,對於一次性事件,最好使用導出表。
23.在新建臨時表時,如果一次性插入數據量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數據量不大,為了緩和系統表的資源,應先create table,然后insert。
24.如果使用到了臨時表,在存儲過程的最后務必將所有的臨時表顯式刪除,先 truncate table ,然后 drop table ,這樣可以避免系統表的較長時間鎖定。
25.盡量避免使用游標,因為游標的效率較差,如果游標操作的數據超過1萬行,那么就應該考慮改寫。
26.使用基於游標的方法或臨時表方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。
27.與臨時表一樣,游標並不是不可使用。對小型數據集使用 FAST_FORWARD 游標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。在結果集中包括“合計”的例程通常要比使用游標執行的速度快。如果開發時間允許,基於游標的方法和基於集的方法都可以嘗試一下,看哪一種方法的效果更好。
28.在所有的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF 。無需在執行存儲過程和觸發器的每個語句后向客戶端發送 DONE_IN_PROC 消息。
29.盡量避免大事務操作,提高系統並發能力。
30.盡量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。 -
試比較連接查詢和嵌套查詢
1、意義上的差異
嵌套查詢是包含一個或多個子查詢或子查詢的另一個術語的select語句。在外部查詢中包含內部查詢的另一個子查詢是SQL語句的擴展。
連接查詢是關系數據庫中最重要的查詢。在關系數據庫管理系統中,數據之間的關系不需要確定表的建立時間,實體的所有信息通常都存儲在表中。檢索數據時,通過連接操作查詢存儲在多個表中的不同實體的信息。
2、特征上的差異
嵌套查詢的主要特點是sql允許從內到外進行多層嵌套分析,並將子查詢的結果作為主查詢的查詢條件。連接是關系數據庫模型的主要特征。多表查詢可以通過連接運算符實現。連接操作給用戶帶來極大的靈活性,可以隨時添加新的數據類型。
基本表數據
圖書館 L.DBF
LNO | LNAME | CITY | TEL |
---|---|---|---|
L1 | 上海圖書館 | 上海 | 205800 |
L2 | 上海外文書店 | 上海 | 310310 |
L3 | 北京圖書館 | 北京 | 282471 |
L4 | 武漢圖書館 | 武漢 | 812712 |
L5 | 南京圖書館 | 南京 | 328173 |
圖書 B.DBF
BNO | BNAME | PRICE |
---|---|---|
B1 | 數據庫原理 | 9.80 |
B2 | 系統分析與設計 | 8.50 |
B3 | 數據庫設計 | 7.10 |
B4 | 計算機原理 | 9.60 |
B5 | 操作系統 | 11.20 |
書店 S.DBF
SNO | SNAME | ADDRESS |
---|---|---|
S1 | 北京新華書店 | 北京 |
S2 | 上海新華書店 | 上海 |
S3 | 上海外文書店 | 上海 |
S4 | 湖北新華書店 | 武漢 |
S5 | 江蘇新華書店 | 南京 |
圖書發行 LBS.DBF
LNO | BNO | SNO | QTY |
---|---|---|---|
L1 | B1 | S2 | 10 |
L1 | B2 | S1 | 5 |
L1 | B3 | S3 | 5 |
L1 | B4 | S5 | 20 |
L2 | B1 | S3 | 10 |
L2 | B4 | S5 | 20 |
L2 | B5 | S4 | 15 |
L4 | B4 | S4 | 20 |
L4 | B5 | S4 | 30 |
L5 | B1 | S2 | 10 |
L5 | B2 | S5 | 20 |
L5 | B4 | S5 | 30 |