11. TRUY VẤN DỮ LIỆU VÀ CẬP NHẬT DỮ LIỆU
11.2.4. Mệnh đề where
Mệnh đề WHERE đƣợc dùng để thiết lập điều kiện truy xuất.
Để truy xuất dữ liệu trong bảng theo các điều kiện nào đó, một mệnh đề WHERE có thể đƣợc thêm vào câu lệnh SELECT.
a) Cú pháp
Cú pháp mệnh đề WHERE trong câu lệnh SELECT nhƣ sau:
SELECT tên_cột[,…] FROM tên_bảng[,…]
WHERE tên_cột phép_toán giá_trị[and/or …]
Phép toán Mô tả = So sánh bằng <> So sánh không bằng > Lớn hơn < Nhỏ hơn >= Lớn hơn hoặc bằng <= Nhỏ hơn hoặc bằng
BETWEEN Nằm giữa một khoảng LIKE So sánh mẫu chuỗi
Lƣu ý: Trong một số phiên bản của SQL, phép toán <> có thể đƣợc viết dƣới dạng != b) Sử dụng mệnh đề WHERE
Để lấy danh sách những ngƣời sống ở thành phố Sandnes, ta sử dụng mệnh đề WHERE trong câu lệnh SELECT nhƣ sau:
SELECT * FROM Persons
WHERE City = 'Sandnes' Bảng Persons:
LastName FirstName Address City Year
Hansen Ola Timoteivn 10 Sandnes 851
Svendson Tove Borgvn 23 Sandnes 878
Svendson Stale Kaivn 18 Sandnes 880
Pettersen Kari Storgt 20 Stavanger 860
Kết quả trả về:
LastName FirstName Address City Year
Hansen Ola Timoteivn 10 Sandnes 851
Svendson Tove Borgvn 23 Sandnes 878
Svendson Stale Kaivn 18 Sandnes 880
c) Sử dụng dấu nháy
Lƣu ý rằng ở ví dụ trên ta đã sử dụng hai dấu nháy đơn (') bao quanh giá trị điều kiện 'Sandnes'.
SQL sử dụng dấu nháy đơn bao quanh các giá trị ở dạng chuỗi văn bản (text). Nhiều hệ CSDL còn cho phép sử dụng dấu nháy kép ("). Các giá trị ở dạng số không dùng dấu nháy để bao quanh.
Với dữ liệu dạng chuỗi văn bản: Câu lệnh đúng:
SELECT * FROM Persons WHERE FirstName = 'Tove' Câu lệnh sai:
SELECT * FROM Persons WHERE FirstName = Tove Với dữ liệu dạng số:
Câu lệnh đúng:
SELECT * FROM Persons WHERE Year > 865 Câu lệnh sai:
SELECT * FROM Persons WHERE Year > '865'
d) Toán tử Like
Toán tử like đƣợc sử dụng trong trƣờng hợp so sánh gần đúng, có thể sử dụng các toán tử đại diện (wildcard operators) trong bảng dƣới đây
Wildcard Mô tả Ví dụ
„_‟ Một ký tự Select Ten_nv From
NHAN_VIEN Where ten_nv Like „C_‟
% Nhiều ký tự Select Ten_nv From
NHAN_VIEN Where ten_nv Like „'AL%'‟
[] Một ký tự thuộc khoảng đặt trong ngoặc vuông
Select Ten_nv From
NHAN_VIEN Where ten_nv Like 'Sem[a-e]'
[^] Một ký tự mà không thuộc khoảng đặt trong ngoặc vuông
Select Ten_nv From
NHAN_VIEN Where ten_nv Like 'Sem[^a-e]' 11.2.5. Mệnh đề order by Mệnh đề ORDER BY đƣợc sử dụng để sắp xếp kết quả trả về. Sắp xếp các dòng Mệnh đề ORDER BY đƣợc dùng để sắp xếp các dòng. Ví dụ bảng Orders: Company OrderNumber Sega 3412 ABC Shop 5678 W3Schools 2312 W3Schools 6798 Ví dụ:
Để lấy danh sách các công ty theo thứ tự chữ cái (tăng dần):
SELECT Company, OrderNumber FROM Orders
ORDER BY Company
Kết quả trả về:
Company OrderNumber
Sega 3412
W3Schools 6798
W3Schools 2312
Ví dụ:
Lấy danh sách các công ty theo thứ tự chữ cái (tăng dần) và hoá đơn đặt hàng theo thứ tự số tăng dần:
SELECT Company, OrderNumber FROM Orders
ORDER BY Company, OrderNumber
Kết quả trả về: Company OrderNumber ABC Shop 5678 Sega 3412 W3Schools 2312 W3Schools 6798 Ví dụ:
Lấy danh sách các công ty theo thứ tự giảm dần:
SELECT Company, OrderNumber FROM Orders
ORDER BY Company DESC
Kết quả trả về: Company OrderNumber W3Schools 6798 W3Schools 2312 Sega 3412 ABC Shop 5678 11.2.6. Kết nối bảng
Trong quá trình truy vấn, dữ liệu có thể đƣợc lấy từ một hoặc nhiều bảng trong CSDL, nếu số lƣợng bảng từ 2 trở lên chúng ta phải thực hiện việc kết nối giữa các bảng, biểu thức kết nối ta sẽ đặt trong mệnh đề where (ở đây chúng ta đang đề cập đến kết nối bằng)
Quay trở lại với CSDL quản lý vật tƣ trong bài 10, giả sử muốn hiển thị tên nhân viên đã xuất vật tƣ trong ngày „12/07/2008‟, chúng ta sẽ thiết kế câu truy vấn nhƣ sau:
Câu truy vấn trên thực hiện trên hai bảng là NHAN_VIEN và PHIEU_XUAT, điều kiện kết nối giữa hai bảng là MA_NV = MANV_XUAT.
SELECT TEN_NV
FROM NHAN_VIEN, PHIEU_XUAT
11.3. Các bài tập về truy vấn cơ bản
Cho các bảng trong cơ sở dữ liệu quản lý vật tƣ ( hình vẽ ở dƣới )
Hãy viết các câu truy vấn để trả lời các câu hỏi sau
1) Hiển thị tên và ngày sinh của những nhân viên sinh năm 880
2) Hiển thị thông tin bao gồm mã, tên và ngày sinh của những nhân viên đã xuất vật tƣ trong tháng 6 năm 2008.
3) Hiển thị mã vật tƣ và số lƣợng đã xuất trong ngày 12 tháng 8 năm 2008 4) Hiển thị tên và đơn giá của tất cả vật tƣ sắp xếp theo chiều tăng của đơn giá 5) Hiển thị tên vật tƣ và số tiền tƣơng ứng của những vật tƣ đã đƣợc xuất trong
phiếu có số phiếu xuất là „001‟
12. CÁC PHÉP TOÁN TẬP HỢP VÀ TRUY VẤN LỒNG 12.1. Các phép toán tập hợp 12.1. Các phép toán tập hợp
12.1.1. Toán tử UNION
Toán tử UNION cho phép ta hợp các kết quả của hai hay nhiều truy vấn thành một tập kết quả duy nhất. Cú pháp của phép hợp nhƣ sau:
Trong đó Query_1 có dạng nhƣ sau: SELECT select_list [INTO clause] [FROM clause] [WHERE clause] [GROUP BY clause] [HAVING clause] Và Query_i (i = 2,..,N) có dạng SELECT select_list [FROM clause] [WHERE clause] [GROUP BY clause] Query_1
[UNION [ALL] Query_2 ] ...
[UNION [ALL] Query_N ] [ORDER BY clause]
Giả sử chúng ta có hai bảng nhƣ sau: Khi đó phép hợp SELECT A, C FROM R UNION SELECT * FROM S Sẽ có kết quả là (b¶ng kÕt qu¶)
Theo mặc định, phép toán UNION sẽ loại bỏ những dòng giống nhau trong kết quả. Nếu ta sử dụng tùy chọn ALL thì các dòng giống nhau sẽ không bị loại bỏ. Ta có thể sử dụng các dấu ngoặc để xác định thứ tự tính toán trong phép hợp.
Các nguyên tắc khi sử dụng toán tử UNION
Khi xây dựng các câu lệnh UNION, ta cần chú ý các nguyên tắc sau:
+ Tất cả các danh sách chọn trong câu lệnh UNION phải có cùng số biểu thức (các tên cột, các biểu thức số học, các hàm gộp,...)
+ Các cột tƣơng ứng trong tất cả các bảng, hoặc tập con bất kỳ các cột đƣợc sử dụng trong bản thân mỗi truy vấn phải cùng kiểu dữ liệu.
+ Các cột tƣơng ứng trong bản thân từng truy vấn của một câu lệnh UNION phải xuất hiện theo thứ tự nhƣ nhau. Nguyên nhân là do phép hợp so sánh các
cột từng cột một theo thứ tự đƣợc cho trong mỗi truy vấn.
+ Khi các kiểu dữ liệu khác nhau đƣợc kết hợp với nhau trong câu lệnh UNION, chúng sẽ đƣợc chuyển sang kiểu dữ liệu cao hơn (nếu có thể đƣợc). + Tiêu đề cột trong kết quả của phép hợp sẽ là tiêu đề cột đƣợc chỉ định trong truy vấn đầu tiên.
12.1.2. Toán tử EXCEPT và INTERSECT
12.2. Truy vấn lồng
Cú pháp của câu truy vấn lồng Bảng R A B C A1 B1 1 A2 B1 2 A3 B2 3 A4 B2 4 Kết quả E F A1 1 A2 2 A3 3 A4 4 A5 5 Bảng S E F A3 3 A4 4 A5 5 SELECT <danh sách các cột> FROM <danh sách các bảng> WHERE <so sánh tập hợp> ( SELECT <danh sách các cột> FROM <danh sách các bảng>
WHERE <điều kiện>) Câu truy vấn cha
(Outer query)
Câu truy vấn con (Subquery)
Ví dụ: trong cơ sở dữ liệu quản lý vật tƣ, hiển thị mã và tên vật không đƣợc xuất trong năm 2007, chúng ta sẽ thiết kế câu truy vấn nhƣ sau:
SELECT MA_VTU, TEN_VTU FROM VAT_TU
WHERE MA_VTU NOT IN (SELECT MA_VTU
FROM PHIEU_XUAT AS PX, DONG_XUAT AS DX WHERE PX.SO_PXUAT =DX.SO_PXUAT AND
NGAY_XUAT BETWEEN '1/1/2007' AND '12/31/2007' ) Các câu lệnh SELECT có thể lồng nhau ở nhiều mức. Câu truy vấn con thƣờng trả về một tập các giá trị.
Các câu truy vấn con trong cùng một mẹnh đề WHERE đƣợc kết hợp bằng phép nối logic.
Mệnh đề WHERE của câu truy vấn cha
- <biểu thức><so sánh tập hợp><truy vấn con> - So sánh tập hợp thƣờng đi cùng một số toán tử
IN, NOT IN ALL
ANY hoặc SOME - Kiểm tra sự tồn tại
EXISTS NOT EXISTS
12.2.1. Truy vấn lồng phân cấp
+ Mệnh đề WHERE của truy cập con không tham chiếu đến thuộc tính của các quan hệ trong mệnh đề FORM ở truy vấn cha.
+ Khi thực hiện, câu truy vấn con sẽ đƣợc thực hiện trƣớc.
12.2.2. Truy vấn lồng tương quan
+ Mệnh đề WHERE của truy vấn con tham chiếu ít nhất một thuộc tính của các quan hệ trong mệnh đề FROM ở truy vấn cha
+ Khi thực hiện, câu truy vấn con sẽ đƣợc thực hiện nhiều lần, mỗi lần tƣơng ứng với một bộ của truy vấn cha
IN
- <tên cột>IN<câu truy vấn con>
- Thuộc tính ở mệnh đề SELECT của truy vấn con phải có cùng dữ liệu với thuộc tính ở mệnh đề WHERE của truy vấn cha.
EXISTS
- Không cần có thuộc tính, hằng số hay biểu thức nào khác đứng trƣớc. - Không nhất thiết liệt kê thuộc tính ở mệnh đề SELECT của truy vấn con. - Những câu lệnh truy vấn có ANY hay IN đều có thể chuyển thành câu
truy vấn có EXISTS
12.3. Bài tập liên quan đến các phép toán tập hợp và truy vấn lồng
Xét cơ sở dữ liệu “Quản lý vật tƣ” nhƣ vẽ dƣới đây
Hãy sử dụng ngôn ngữ truy vấn (SQL) để trả lời các câu hỏi sau:
Câu 1: Hiển thị tên nhân viên, ngày sinh của những nhân viên đã xuất vật tƣ trong tháng 8 năm 2008.
Câu 2: Hiển thị tên nhân viên, ngày sinh của những nhân viên đã xuất vật tƣ có tên là „Màn hình máy tính‟
Câu 3: Hiển thị mã, tên vật tƣ đã đƣợc xuất với khối lƣợng lớn nhất.
13. THỰC HÀNH RBTV 14. THỰC HÀNH VỀ CẬP NHẬT DỮ LIỆU 14. THỰC HÀNH VỀ CẬP NHẬT DỮ LIỆU 15. THỰC HÀNH VỀ TRUY VẤN CƠ BẢN 16. THỰC HÀNH VỀ CÁC PHÉP TOÁN TẬP HỢP và TRUY VẤN LỒNG 17. HÀM KẾT HỢP VÀ GOM NHÓM, MỘT SỐ TRUY VẤN KHÁC 17.1. Hàm kết hợp
Cú pháp của hàm COUNT:
SELECT COUNT (tên_cột) FROM tên_bảng
Hàm COUNT (*): Hàm COUNT (*) trả về số lƣợng các dòng đƣợc chọn ở trong bảng. Ví dụ ta có bảng Persons nhƣ sau: Name Age Hansen, Ola 34 Svendson, Tove 45 Pettersen, Kari 8
Câu lệnh sau sẽ trả về số lƣợng các dòng trong bảng:
SELECT COUNT (*) FROM Persons và kết quả trả về sẽ là:3
Câu lệnh sau sẽ trả về số lƣợng những ngƣời lớn hơn 20 tuổi:
SELECT COUNT (*) FROM Persons WHERE Age > 20 kết quả trả về sẽ là: 2
Hàm COUNT (column):
Hàm COUNT (column) sẽ trả về số lƣợng các dòng có giá trị khác NULL ở cột đƣợc chỉ định. Ví dụ ta có bảng Persons nhƣ sau: Name Age Hansen, Ola 34 Svendson, Tove 45 Pettersen, Kari
Câu lệnh sau sẽ trả về số lƣợng những ngƣời mà cột Age trong bảng không rỗng:
SELECT COUNT (Age) FROM Persons và kết quả trả về sẽ là: 2
Mệnh đề COUNT DISTINCT
Lƣu ý: Các ví dụ dƣới đây chỉ hoạt động với CSDL Oracle và MS SQL Server, không hoạt động trên MS Access (chƣa thử nhiệm với các hệ CSDL khác!)
Từ khoá DISTINCT và COUNT có thể đƣợc dùng cùng với nhau để đếm số lƣợng các kết quả không trùng nhau.
Cú pháp nhƣ sau:
SELECT COUNT (DISTINCT column(s)) FROM table Ví dụ ta có bảng Orders nhƣ sau:
Company OrderNumber
Sega 3412
W3Schools 2312
W3Schools 6798 Câu lệnh SQL sau:
SELECT COUNT (DISTINCT Company) FROM Orders sẽ trả về kết quả là: 3
SQL có sẵn khá nhiều hàm để thực hiện đếm và tính toán. Cú pháp:
Cú pháp để gọi hàm trong câu lệnh SQL nhƣ sau:
SELECT function (tên_cột) FROM tên_bảng
Bảng dữ liệu chúng ta sẽ dùng trong các ví dụ tiếp theo:
Name Age
Hansen, Ola 34
Svendson, Tove 45
Pettersen, Kari 8
Hàm AVG (column)
Hàm AVG trả về giá trị trung bình tính theo cột đƣợc chỉ định của các dòng đƣợc chọn. Các giá trị NULL sẽ không đƣợc xét đến khi tính giá trị trung bình.
Ví dụ:
Câu lệnh sau sẽ tính số tuổi trung bình của những ngƣời có tuổi trên 20:
SELECT AVG (Age) FROM Persons WHERE Age > 20 kết quả trả về sẽ là:39.5
Hàm MAX (column)
Hàm MAX trả về giá trị lớn nhất trong cột. Các giá trị NULL sẽ không đƣợc xét đến.
Ví dụ:
SELECT MAX (Age) FROM Persons kết quả trả về: 45
Hàm MIN (column)
Hàm MAX trả về giá trị nhỏ nhất trong cột. Các giá trị NULL sẽ không đƣợc xét đến.
Ví dụ:
SELECT MIN (Age) FROM Persons kết quả trả về: 8
Lƣu ý: Hàm MIN và MAX cũng có thể áp dụng cho các cột có dữ liệu là chuỗi văn bản. Dữ liệu trong cột sẽ đƣợc so sánh theo thứ tự tăng dần của từ điển
Hàm SUM(column)
Hàm SUM trả về tổng giá trị của cột. Các giá trị NULL sẽ không đƣợc xét đến.
Ví dụ:
Tìm tổng số tuổi của tất cả những ngƣời có trong bảng:
SELECT SUM(Age) FROM Persons kết quả trả về: 98
SELECT SUM(Age) FROM Persons WHERE Age > 20 kết quả trả về: 79
17.2. Gom nhóm
17.2.1. Cú pháp
Các hàm tập hợp (ví dụ nhƣ SUM) thông thƣờng cần thêm chức năng của mệnh đề GROUP BY.
GROUP BY...
Mệnh đề GROUP BY...đƣợc thêm vào SQL bởi vì các hàm tập hợp (nhƣ SUM) trả về một tập hợp của các giá trị trong cột mỗi khi chúng đƣợc gọi, và nếu không có GROUP BY ta không thể nào tính đƣợc tổng của các giá trị theo từng nhóm riêng lẻ trong cột.
Cú pháp của GROUP BY nhƣ sau:
SELECT tên_cột, SUM (tên_cột) FROM tên_bảng GROUP BY tên_cột
Ví dụ sử dụng GROUP BY:
Giả sử ta có bảng Sales nhƣ sau:
Company Amount
W3Schools 5500
IBM 4500
W3Schools 7100
Câu lệnh SQL sau:
SELECT Company, SUM (Amount) FROM Sales
Sẽ gây lỗi cú pháp. Ta thêm mệnh đề GROUP BY vào trong câu lệnh SQL:
SELECT Company, SUM (Amount) FROM Sales GROUP BY Company
và kết quả trả về lần này sẽ là:
Company SUM(Amount)
W3Schools 12600
IBM 4500
Kết quả này đúng nhƣ ta mong muốn.
17.2.2. Điều kiện trên nhóm
HAVING...
Mệnh đề HAVING...đƣợc thêm vào SQL vì mệnh đề WHERE không áp dụng đƣợc đối với các hàm tập hợp (nhƣ SUM). Nếu không có HAVING, ta không thể nào kiểm tra đƣợc điều kiện với các hàm tập hợp.
Cú pháp của HAVING nhƣ sau:
SELECT tên_cột, SUM (tên_cột) FROM tên_bảng GROUP BY tên_cột
HAVING SUM (tên_cột) điều_kiện giá_trị
SELECT Company, SUM (Amount) FROM Sales GROUP BY Company
HAVING SUM (Amount) > 10000 sẽ trả về kết quả:
Company SUM(Amount)
W3Schools 12600
Với SQL, bí danh có thể đƣợc sử dụng cho tên của cột và tên của bảng. Bí danh cột:
Cú pháp bí danh cột nhƣ sau:
SELECT tên_cột AS bí_danh_cột FROM tên_bảng
Bí danh bảng:
Bí danh bảng có cú pháp nhƣ sau:
SELECT tên_cột FROM tên_bảng AS bí_danh_bảng
Ví dụ sử dụng bí danh cột:
Ta có bảng Persons nhƣ sau:
LastName FirstName Address City
Hansen Ola Timoteivn 10 Sandnes
Svendson Tove Borgvn 23 Sandnes
Pettersen Kari Storgt 20 Stavanger
Câu lệnh SQL sau:
SELECT LastName AS Họ, FirstName AS Tên
FROM Persons Sẽ trả về kết quả: Họ Tên Hansen Ola Svendson Tove Pettersen Kari
Mệnh đề GROUP BY
Các thuộc tính trong mệnh đề SELECT (trừ những thuộc tính trong những hàm kết hợp) phải xuất hiện trong mệnh đề GROUP BY
Mệnh đề HAVING
- Sử dụng các hàm kết hợp trong mệnh đề SELECT để kiểm tra một số điều kiện nào đó.
- Chỉ kiểm tra điều kiện trên nhóm, không là điều kiện lọc trên từng bộ. - Sau khi gom nhóm điều kiện trên nhóm mới đƣợc thực hiện.
Thứ tự thực hiện câu truy vấn só mệnh đề GROUP BY và HAVING - (1) Chọn ra những dòng thỏa điều kiện trong mện đề WHERE.
- (2) Những dòng này sẽ đƣợc gom thành nhiều nhóm tƣơng ứng với mệnh đề GROUP BY.
- (3) Áp dụng các hàm kết hợp cho mỗi nhóm.
- (4) Bỏ qua những nhóm không thỏa mãn điều kiện trong mệnh đề HAVING
- (5) Rút trích các giá trị của các cột và hàm kết hợp trong mệnh đề SELECT.
17.4. Bài tập liên quan đến hàm kết hợp và gom nhóm 17.5. Một số dạng truy vấn khác 17.5. Một số dạng truy vấn khác
17.5.1. Truy vấn con ở mệnh đề From
Ví dụ: trong cơ sở dữ liệu quản lý vật tƣ, chúng ta muốn hiển thị tên những nhân viên đã xuất vật tƣ trong ngày „12/08/2008‟, câu lệnh truy vấn sau sẽ thực hiện yêu cầu trên.