Truy vấn, Ràng buộc, Trigger Truy vấn, Ràng buộc, Trigger Bởi: Ths. Phạm Hoàng Nhung SQL (Structured Query Language) là ngôn ngữ truy vấn cấu trúc đượ

Tài liệu tương tự
Thực hành hàm kết hợp và gom nhóm Thực hành hàm kết hợp và gom nhóm Bởi: Khoa CNTT ĐHSP KT Hưng Yên Nhắc lại lý thuyết Hàm kết hợp Hàm count(), min(),

Tìm hiểu ngôn ngữ lập trình Visual Basic Tìm hiểu ngôn ngữ lập trình Visual Basic Bởi: Khuyet Danh Tìm hiểu ngôn ngữ lập trình Visual Basic Tổng quan

HỌC VIỆN KỸ THUẬT QUÂN SỰ KHOA CÔNG NGHỆ THÔNG TIN CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM Độc lập Tự do Hạnh phúc ĐỀ CƯƠNG CHI TIẾT HỌC PHẦN CÔNG NGHỆ CLI

Chương 1:

Co s? d? li?u (Database)

Kỹ thuật phần mềm ứng dụng

Microsoft Word - Co so du lieu phan tan - cap nhat

The Total Economic Impact™ Of IBM Security Guardium

Nhập môn Công Nghệ Thông Tin 1

Microsoft Word - Co so du lieu - cap nhat

Stored Procedures Stored Procedures Bởi: Khoa CNTT ĐHSP KT Hưng Yên Trong những bài học trước đây khi dùng Query Analyzer chúng ta có thể đặt tên và s

Phân tích cách nhìn hiện thực cuộc sống của Nguyễn Minh Châu trong tác phẩm Chiếc thuyển ngoài xa

ĐỀ CƯƠNG MÔN HỌC NHẬP MÔN TIN HỌC

(Microsoft Word - 4_Vuong NC-T\ doc)

PowerPoint Template

Chương II - KIẾN TRÚC HỆ ĐIỀU HÀNH

SQL SQL Bởi: phamgiatien phamthephi SQL MỤC ĐÍCH Giới thiệu một hệ CSDL chuẩn, SQL, các thành phần cơ bản của của nó. YÊU CẦU Hiểu các thành phần cơ b

NGÔN NGƯ LÂ P TRIǸH Biên tập bởi: nguyenvanlinh

Quy tắc Ứng xử của chúng tôi Sống theo giá trị của chúng tôi

TRƯỜNG Đ CK Joel Murach lay Harris TÜ SACH BẢN QUYỄN FPT Polytechnic P H P v ä MySQL Murach's PHP and MySQL Khởi động nhanh với PHP & MySQL

Đề cương chương trình đại học

Chương trình dịch

ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ BÙI TRUNG HIẾU NGHIÊN CỨU MỘT SỐ VẤN ĐỀ VỀ CƠ SỞ DỮ LIỆU VÀ ỨNG DỤNG TRONG BÀI TOÁN QUẢN LÝ DÂN CƯ LU

SỞ GDĐT TỈNH BÌNH DƯƠNG XÂY DỰNG VĂN HÓA PHÁP LÝ, ỨNG XỬ VĂN MINH Số 08 - Thứ Hai,

Những khái niệm cơ bản của hệ điều hành mạng Windows Những khái niệm cơ bản của hệ điều hành mạng Windows Bởi: unknown Giới thiệu tổng quan về Windows

Nhúng mã-cách khai báo biến Nhúng mã-cách khai báo biến Bởi: Khoa CNTT ĐHSP KT Hưng Yên Nhúng mã javascript trong trang HTML Bạn có thể nhúng JavaScri

TCVN T I Ê U C H U Ẩ N Q U Ố C G I A TCVN :2014 ISO/IEC :2013 Xuất bản lần 1 KỸ THUẬT PHẦN MỀM VÀ HỆ THỐNG ĐẢM BẢO PHẦN MỀM VÀ HỆ THỐNG

Bình giảng tác phẩm “Chiếc thuyền ngoài xa” của Nguyễn Minh Châu

TRƯỜNG ĐẠI HỌC SƯ PHẠM TP. HỒ CHÍ MINH KHOA HÓA HỌC KHÓA LUẬN TỐT NGHIỆP Tên đề tài: SỬ DỤNG MOODLE THIẾT KẾ WEBSITE HỖ TRỢ VIỆC TỰ HỌC CHƯƠNG HIDROCA

Xã hội học số 2(54) 1996

Tác giả: Giáo sư Andreas Thalassinos (Trưởng phòng Đào tạo của FXTM)

Biên dịch & Hiệu đính: Phạm Trang Nhung #231 10/12/2014 LÝ QUANG DIỆU VIẾT VỀ CHIẾN LƯỢC THAO QUANG DƯỠNG HỐI CỦA TRUNG QUỐC Nguồn: Lee Kuan Yew (2013

1

7. CÁC CHỦ ĐỀ VÀ BÀI HỌC TỪ ĐỔI MỚI CÔNG TÁC QUẢN TRỊ NHÀ NƯỚC Những tiến bộ to lớn của Việt Nam trong việc duy trì tốc độ tăng trưởng kinh tế cao, gi

Microsoft Word - QCHV 2013_ChinhThuc_2.doc

LUẬN VĂN: Áp dụng quản lý rủi ro vào qui trình thủ tục hải quan đối với hàng hóa xuất, nhập khẩu

BỘ GIÁO DỤC VÀ ĐÀO TẠO TRƯỜNG ĐẠI HỌC MỞ THÀNH PHỐ HỒ CHÍ MINH ĐỀ CƯƠNG MÔN HỌC 1. THÔNG TIN VỀ MÔN HỌC 1.1. Tên môn học: QUẢN TRỊ HỆ CƠ SỞ DỮ LIỆU 1.

50 n¨m h¶i qu©n nh©n d©n viÖt nam anh hïng

Trường Đại học Văn Hiến TÀI LIỆU MÔN HỌC KỸ NĂNG MỀM (Lưu hành nội bộ) KỸ NĂNG GIẢI QUYẾT VẤN ĐỀ VÀ RA QUYẾT ĐỊNH Biên soạn: ThS. Nguyễn Đông Triều

Microsoft Word - su_dung_sqlite_voi_php.docx

Document

Microsoft Word - thuong-mai-dien-tu-va-kiem-tien-online.docx

M¤ §UN 6: GI¸o dôc hoµ nhËp cÊp tiÓu häc cho häc sinh tù kû

Microsoft Word - Tailieu win2003.doc

HỘI THI TIN HỌC TRẺ TỈNH AN GIANG ĐỀ CHÍNH THỨC ĐỀ THI LÝ THUYẾT BẢNG A - KHỐI TIỂU HỌC Khóa ngày: Thời gian : 20 phút (không kể thời gian

ĐỀ cương chương trình đẠi hỌc

HỌC VIỆN NÔNG NGHIỆP VIỆT NAM SỔ TAY SINH VIÊN (Dùng cho sinh viên khóa 63) Sinh viên : Mã sinh viên :..

J

BỘ GIÁO DỤC VÀ ĐÀO TẠO

Giới thiệu về ADO.NET Giới thiệu về ADO.NET Bởi: phamvanviet truonglapvy Trong thực tế, có rất nhiều ứng dụng cần tương tác với cơ sở dữ liệu..net Fra

Tướng Đỗ Cao Trí

ĐỀ CƯƠNG MÔN HỌC NHẬP MÔN TIN HỌC

Trường Tiểu học Trung Lập Thượng Khối 1 Giáo viên: Nguyễn Thanh Quang Ngày dạy: thứ, ngày tháng năm 201 Môn Mỹ thuật tuần 19 Chủ đề EM VÀ NHỮNG VẬT NU

Microsoft Word - cu_phap_sqlite.docx

CHƯƠNG 10

2018 Nhận xét, phân tích, góp ý cho Chương trình môn Tin học trong Chương trình Giáo dục Phổ thông mới

Chương 4: Tìm kiếm DL ĐPT P4: Dữ liệu ĐPT

Microsoft Word - Huong dan su dung Mailchimp.docx

TRUNG TÂM CON NGƯỜI VÀ THIÊN NHIÊN NÔNG NGHIỆP TÂY BẮC: NHẬN DIỆN THÁCH THỨC VÀ ĐỊNH HƯỚNG PHÁT TRIỂN TRONG BỐI CẢNH BIẾN ĐỔI KHÍ HẬU Nhà xuất bản Tha

SỔ TAY NHÂN VIÊN SỔ TAY NHÂN VIÊN

LỜI GIỚI THIỆU Chia sẽ ebook : Tham gia cộng đồng chia sẽ sách : Fanpage : C

Lập trình cấu trúc trong Visual Basic Lập trình cấu trúc trong Visual Basic Bởi: Nguyễn Sơn Học xong chương này, sinh viên phải nắm bắt được các vấn đ

(Tái bản lần thứ hai)

Hãy để mọi chuyện đơn giản - Tolly Burkan

Kiểu dữ liệu văn bản Kiểu dữ liệu văn bản Bởi: PGS. TS. NGƯT Phạm Văn Huấn Ngoài những dữ liệu số như các số nguyên, số thực, máy tính còn có thể lưu

thacmacveTL_2019MAY06_mon

TRƢỜNG ĐẠI HỌC DUY TÂN TRUNG TÂM TIN HỌC DUY TÂN ĐỀ CƢƠNG KHẢO SÁT TIN HỌC DÀNH CHO KHỐI KHÔNG CHUYÊN TIN TOÀN TRƢỜNG ÁP DỤNG CHUẨN ỨNG DỤNG KỸ NĂNG C

Microsoft Word - 2- Giai phap han che su phu thuoc kinh te vao Trung Quoc.doc

PowerPoint Presentation

Microsoft Word - Day_lop_4_P1.doc

Thứ Số 320 (7.303) Sáu, ngày 16/11/ XUẤT BẢN TỪ NĂM 1985 Thủ

000.FF50VI. Trang bia 1 - bia ngoai

CÔNG TY TNHH GIẢI PHÁP TRỰC TUYẾN TOTAL 60 Đường 18, Phường Hiệp Bình Chánh, Quận Thủ Đức, TP.HCM MST:

MỘT CÁCH NHÌN VỀ MƯỜI BA NĂM VĂN CHƯƠNG VIỆT NGOÀI NƯỚC ( ) (*) Bùi Vĩnh Phúc Có hay không một dòng văn học Việt ngoài nước? Bài nhận định dướ

Bản tin ISSN CHÍNH SÁCH Tài nguyên Môi trường Phát triển bền vững TRUNG TÂM CON NGƯỜI VÀ THIÊN NHIÊN Số 17 Quý I/2015 HƯỚNG ĐẾN NHỮNG VẬN ĐỘ

10 Vạn Câu Hỏi Vì Sao - Tin Học

Kiểm soát truy suất Kiểm soát truy suất Bởi: Khoa CNTT ĐHSP KT Hưng Yên Khái niệm Bảo mật thực chất là kiểm soát truy xuất [1]. Mục đích của bảo mật m

C ách đây 43 năm cuộc tổng tiến công và nổi dậy mùa Xuân năm 1975 mà đỉnh cao là chiến dịch Hồ Chí Minh lịch sử đã giành thắng lợi hoàn toàn. Ngày 30

Trung tâm WTO và Hội nhập Phòng Thương mại và Công nghiệp Việt Nam NGHIÊN CỨU CHÍNH SÁCH RỦI RO ĐỐI VỚI NGÀNH BÁN LẺ VIỆT NAM TRONG BỐI CẢNH HỘI NHẬP

Phong cách học tập BÁO CÁO CỦA Sample Report Phong cách học tập Bản đánh giá Phong cách học tập Của: Sample Report Ngày: 09/07/2019 Copyright

Số 49 (7.397) Thứ Hai ngày 18/2/2019 XUẤT BẢN TỪ NĂM

Microsoft Word - thuat-ngu-thuong-mai-dien-tu.docx

Microsoft Word - Hmong_Cultural_Changes_Research_Report_2009_Final_Edit.doc

000.Bia

Tình Thương Nhân Loại 1 Điển Mẹ Diêu Trì Rằm tháng sáu Nhâm Thìn, 2012 Nước Việt Nam một miền linh địa Có rồng vàng thánh địa mai sau Nước Nam hơn cả

BỘ GIÁO DỤC VÀ ĐÀO TẠO

Đề cương chương trình đại học

HEADING 1: PHẦN 1: QUẢN LÝ VÀ DUY TRÌ HỆ ĐIỀU HÀNH

PHẦN II

PHẦN I

LỜI NÓI ĐẦU Mục lục CHƯƠNG 1: ĐƯA KHOA HỌC VÀO TRƯỜNG HỌC Chúng ta cần đánh thức từ trong sâu thẳm tâm hồn những người làm công tác giáo dục lòng nhiệ

1

Hướng dẫn Bắt đầu Nhanh Microsoft Publisher 2013 trông khác với các phiên bản trước, vì vậy chúng tôi tạo ra hướng dẫn này để giúp bạn dê dàng nắm bắt

Cái ngày thay đổi cuộc đời tôi Lời nói đầu Sau khi bước sang tuổi 25 không bao lâu, tôi gặp một người đàn ông tên là Earl Shoaff. Thực sự, tôi đã khôn

ThemeGallery PowerTemplate

Mục Lục Tiền ảo thuận nhân vì mục đích nhân văn đầu tiên-blood... 2 Bối cảnh... 2 Tác giả... 2 Bloodland... 2 Công nghệ đặc trưng của Bloodland... 3 G

HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIỄN THÔNG BÀI GIẢNG MÔN QUẢN TRỊ BÁN HÀNG Giảng viên: Th.S. Trần Thị Thập Điện thoại/ Bộ môn:

EuroCham Letter & Fax

Số 164 (7.512) Thứ Năm ngày 13/6/2019 XUẤT BẢN TỪ NĂM http:

mySQL - Part 1 - Installation

Bản ghi:

Truy vấn, Ràng buộc, Trigger Bởi: Ths. Phạm Hoàng Nhung SQL (Structured Query Language) là ngôn ngữ truy vấn cấu trúc được sử dụng rộng rãi trong cơ sở dữ liệu quan hệ. Đầu tiên, nó được IBM đề xuất trong dự án SEQUEL- XRM và System-R(1974-1977). Dường như ngay lập tức, những nhà sản xuất khác đã giới thiệu sản phẩm DBMS của mình dựa trên SQL, và bây giờ nó đã được chuẩn hoá chính thức. SQL tiếp tục phát triển đáp ứng những thay đổi trong lĩnh vực cơ sở dữ liệu. Chuẩn ANSI/ISO hiện tại của SQL được gọi là SQL-1999. Trong khi không phải tất cả sản phẩm DBMS đều hỗ trợ SQL-1999 đầy đủ, những nhà sản xuất vẫn đang tiếp tục làm việc để đạt đến điều này và hiện nay hầu hết các sản phẩm DBMS đều hỗ trợ những đặc trưng cơ bản của SQL-1999. Làm thích hợp các chuẩn của SQL: SQL:1999 có tập hợp các tính năng gọi là Core SQL mà các nhà sản xuất phải thực hiện để thích hợp với chuẩn SQL-1999. Những đặc trưng còn lại được tổ chức trong các gói hỗ trợ. Ví dụ, các gói được tổ chức như sau (các chương liên quan nằm trong dấu ngoặc đơn): kiểu ngày tháng nâng cao (enhanced date and time), quản lý ràng buộc nâng cao (enhanced integrity management) và các cơ sở dữ liệu hoạt động (active databases) (chương này), các giao diện ngôn ngữ phía ngoài (external language interfaces) (Chương 6), Xử lý các phân tích trực tuyến (OLAP) (Chương 25) và các đặc tính hướng đối tượng (object features) (Chương 23). Chuẩn SQL/MM thực hiện SQL-1999 bằng việc định nghĩa các gói bổ sung hỗ trợ Khai phá dữ liệu (data mining) (Chương 26), dữ liệu không gian (spatial data) (Chương 28) và văn bản (text documents) (Chương 27), hỗ trợ dữ liệu XML và các truy vấn tương lai. Tổng quan Ngôn ngữ SQL có một số khía cạnh: Ngôn ngữ thực hiện dữ liệu - The Data Manipulation Language (DML): Là tập hợp các lệnh của SQL cho phép người dùng đưa ra các truy vấn, thêm, sửa và xóa các dòng dữ liệu trong bảng. Những truy vấn sẽ được tập trung trình bày 1/46

trong chương này. Chúng ta đã khám phá DML để thêm, sửa, xóa dữ liệu trong Chương 3. Ngôn ngữ định nghĩa dữ liệu - The Data Defination Language (DDL): Là tập hợp các câu lệnh của SQL hỗ trợ để tạo, xóa và sửa định nghĩa các bảng và các khung nhìn. Các ràng buộc tham chiếu có thể định nghĩa trên bảng, hoặc có thể định nghĩa sau khi bảng được tạo ra. Chúng ta đã khám phá các đặc trưng DDL trong chương 3. Mặc dù chuẩn SQL không đề cập tới các chỉ số, nhưng các thực hiện của DBMS thương mại cũng cung cấp lệnh để tạo và xóa các chỉ số. Trigger và Các ràng buộc toàn vẹn nâng cao (Triggers and Advanced Integrity Constraints): Chuẩn SQL:1999 mới có những hỗ trợ cho thực hiện triggers, đó là tập những thao tác được DBMS thực hiện khi có bất kỳ sự thay đổi nào trong cơ sở dữ liệu. Chúng ta sẽ khám phá trigger và các ràng buộc trong chương này. SQL nhúng và động (Embedded và dynamic SQL):Các đặc trưng của Embedded SQL cho phép mã lệnh SQL được gọi từ một ngôn ngữ lập trình như C và COBOL. Các đặc trưng của Dynamic SQL cho phép một truy vấn được xây dựng và thực hiện run-time. Truy vấn cơ sở dữ liệu từ xa và các thực hiện Client-Server (Client-Server Execution and Remote Database Access): Những lệnh này điều khiển cách thức các chương trình ứng dụng trên Client kết nối với cơ sở dữ liệu trên Server, hoặc truy cập dữ liệu trong cơ sở dữ liệu trên mạng. Chúng ta sẽ khám phá những lệnh này trong Chương 7. Quản lý giao dịch (Transaction Management): Một loạt các lệnh cho phép người dùng điều khiển các giao dịch. Bảo mật (Security): SQL cung cấp cơ chế để điều khiển các truy cập của người dùng tới các đối tượng dữ liệu như các bảng và các khung nhìn. Các đặc trưng nâng cao (Advanced features): Chuẩn SQL:1999 bao gồm các tính năng hướng đối tượng (Chương 23), các truy vấn lồng nhau (Chương 24), truy vấn hỗ trợ quyết định (Chương 25), khai phá dữ liệu (Chương 26), dữ liệu không gian (Chương 28) và quản lý dữ liệu XML và văn bản (Chương 27). Tổ chức chương Các phần của chương được tổ chức như sau. Phần 2 trình bày về các truy vấn SQL cơ bản và Phần 3 giới thiệu các phép toán tập hợp. Phần 4 trình bày về các truy vấn lồng nhau. Phần 5.5 khám phá các phép toán nhóm. Chúng ta bàn tới các giá trị null trong Phần 6. Phần 7 xem xét các lệnh SQL được nhúng trong ngôn ngữ lập trình và trong Phần 8 bàn tới các bộ giá trị trong quan hệ được truy cập như thế nào bằng con trỏ. Phần 9 trình bày như thế nào truy vấn được xây dựng sử dụng dynamic SQL, và trong Phần 10 bàn về hai chuẩn kết nối tới DBMS là ODBC và JDBC. Phần 11 bàn về các ràng buộc toàn vẹn phức tạp được thực hiện trong SQL DDL, phần tiếp theo của những phần đã trình bày trong Chương 3; những ràng buộc mới cho phép chúng ta tận dụng đầy đủ khả năng của ngôn ngữ truy vấn SQL. 2/46

Cuối cùng, Phần 12 và 13 trình bày về khái niệm cơ sở dữ liệu hoạt động. Một cơ sở dữ liệu hoạt động có một tập các triggers do các DBA định nghĩa. DBMS điều khiển các cơ sở dữ liệu, phát hiện tình trạng hiện tại của cơ sở dữ liệu và gọi đến các trigger. Các ví dụ: Chúng ta sẽ xem xét một số ví dụ truy vấn sử dụng các bảng được định nghĩa sau: Sailors(sid: integer, sname: string, rating: integer, age: real) Boats(bid: integer, bname: string, color: string) Reserves(sid: integer, bid: integer, day: date) Chúng ta sẽ cung cấp cho mỗi truy vấn một mã duy nhất, và sử dụng tiếp các truy vấn trong Chương 4. Truy vấn mới đầu tiên của chương này có mã số Q15. Truy vấn từ Q1 đến Q14 được định nghĩa trong Chương 4. Chúng ta sử dụng minh họa quan hệ S3 của Sailors, R2 của Reserves, và B1 của Boats giới thiệu trong Chương 4, hình 1, 2 và 3 để làm dữ liệu ví dụ cho các truy vấn. Tất cả các bảng và truy vấn trong chương này có thể được tìm thấy trong Website: http://www.cs.wisc.edu/~dbbook Những vấn đề được chỉ ra bao gồm cách thức thực hiện câu lệnh SQL trong Oracle, IBM DB2, Microsoft SQL Server, và MySQL, và các scripts để tạo các bảng và các truy vấn ví dụ. Dạng đơn giản của truy vấn SQL Phần này trình bày cú pháp của truy vấn SQL đơn giản và giải thích ý nghĩa của nó thông qua chiếnlược thực hiện truy vấn ở mức khái niệm. Chiến lược thực hiện truy vấn ở mức khái niệm là cách để thực hiện truy vấn theo chiều hướng dễ hiểu, không tập trung vào hiệu năng. DBMS sẽ thực hiện truy vấn có thể theo một cách khác hiệu quả hơn cách người dùng định nghĩa. Dạng đơn giản của truy vấn SQL như sau: Tất cả các truy vấn phải có mệnh đề SELECT, chỉ ra những cột nào được đưa ra trong kết quả, và mệnh đề FROM xác định bảng chứa những cột liên quan trong câu lệnh. Mệnh đề WHERE xác định điều kiện chọn. Chúng ta đã biết rằng một truy vấn liên quan tới các biểu thức trong đại số quan hệ, bao gồm phép chọn, phép chiếu, phép nhân chéo. Quan hệ chặt chẽ giữa đại số quan hệ và 3/46

SQL là nền tảng để tối ưu hóa truy vấn trong DBMS quan hệ, chúng ta sẽ xem trong Chương 12 và 15. Kế hoạch thực hiện truy vấn SQL được biểu diễn sử dụng hàng loạt các biểu thức đại số quan hệ (Phần 15.1). Minh họa S3 của Sailors Minh họa R2 của Reserves (Q15) Đưa ra tên và tuổi của tất cả các thủy thủ. SELECT DISTINCT S.sname, S.age FROM Sailors S Hình 3 Minh họa B1 của Boats Minh họa B1 của Boats 4/46

Kết quả của truy vấn này trong trường hợp có và không có từ khóa DISTINCT dựa trên minh họa của Sailors chỉ ra trong Hình 4 và 5. Chỉ có sự khác nhau trong hai kết quả này là sự xuất hiện hay không xuất hiện của bộ giá trị có tên là Horatio và tuổi là 35. Truy vấn tiếp theo có sử dụng đến phép chọn trong đại số quan hệ. Kết quả của Q15 Kết quả của Q15 bỏ DISTINCT SELECT S.sid, S.sname, S.rating, S.age FROM Sailors AS S WHERE S.rating > 7 Như hai ví dụ minh họa ở trên, mệnh đề SELECT được sử dụng để thực hiện phép chiếu, trong khi phép chọn trong đại số quan hệ được biểu diễn sau mệnh đề WHERE! Chúng ta sẽ đề cập chi tiết đến các cú pháp của truy vấn SQL đơn giản: Cụm from-list sau mệnh đề FROM là danh sách tên các bảng. Tên bảng có thể được thay bằng một biến miền, biến miền hữu ích khi cùng một tên bảng xuất hiện nhiều hơn một lần trong from-list. Cụm select-list là danh sách tên các cột của bảng trong from-list. Các tên cột có thể có tiền tố là các biến miền. 5/46

Qualification trong mệnh đề WHERE là một tổ hợp logic (tức là, biểu thức sử dụng kết nối logic AND, OR, NOT) của các điều kiện theo dạng Biểu_thứcopBiểu_thức, trong đó op là một trong những toán tử logic?>, <, >=, <=, =?. Một biểu thức là tên cột, hằng số, hoặc một biểu thức (toán học hoặc xâu ký tự). Từ khóa DISTINCT là từ khóa lựa chọn. Nó chỉ ra rằng bảng kết quả của truy vấn có nên chứa bộ giá trị trùng nhau không. Mặc định, những bộ giá trị trùng nhau không được phép loại bỏ. Mặc dù, những quy tắc phía trên biểu diễn cú pháp của truy vấn SQL cơ bản, nhưng chúng không nói cho chúng ta biết ý nghĩa của một truy vấn. Kết quả của một truy vấn là một quan hệ bao gồm một tập các dòng! - những nội dung này có thể được hiểu bằng việc xem xét chiến lược thực hiện truy vấn ở mức khái niệm sau: 1. Tìm kết quả của phép nhân chéo trên các bảng trong from-list. 2. Xoá các dòng trong kết quả của phép nhân chéo không thoả mãn các điều kiện trong qualification. 3. Xoá tất cả các cột không xuất hiện trong select-list. 4. Nếu có từ khoá DISTINCT, kết quả của truy vấn sẽ bỏ đi những dòng trùng nhau. Chiến lược thực hiện truy vấn ở mức khái niệm nói trên làm chúng ta nhìn thấy rõ ràng những dòng nào cần được xuất hiện trong kết quả. Tuy nhiên, nó dường như là không thực sự hiệu quả (tốc độ thực hiện truy vấn chậm). Chúng ta sẽ xem xét chi tiết về cách thực hiện một truy vấn như thế nào trong Chương 12 và 13; bây giờ, mục đích của chúng ta chỉ đơn giản là giải thích ý nghĩa của truy vấn. Chúng ta sử dụng truy vấn sau để minh hoạ chiến lược thực hiện truy vấn ở mức khái niệm: (Q1) Tìm tên các thuỷ thủ đã phục vụ trên tàu mã số 103. Câu lệnh SQL như sau: SELECT S.sname FROM Sailors S, Reserves R WHERE S.sid = R.sid AND R.bid=103 Bước đầu tiên là xây dựng phép nhân chéo S4 R3, kết quả chỉ ra trong Hình 8. Bước thứ hai là áp dụng điều kiện S.sid=R.sid AND R.bid=103 (Ghi nhớ rằng phép so sánh đầu tiên là yêu cầu của phép nối). Bước này loại bỏ tất cả trừ dòng cuối cùng trong minh hoạ chỉ ra trong Hình 5.8. Bước thứ 3 là loại bỏ những cột không cần thiết, chỉ sname xuất hiện trong mệnh đề SELECT là cần được giữ lại. Bước này đưa chúng ta đến kết quả trong Hình 9, bảng chỉ có một cột và một dòng. 6/46

Hình 6. Minh hoạ R3 của Reserves Minh hoạ R3 của Reserves Minh hoạ S4 của Sailors S4 R3 Kết quả của truy vấn Q1 trên R3 v S4 Bây giờ, chúng tôi trình bày một số ví dụ truy vấn, rất nhiều trong số này đã được trình bày trong phần đại số quan hệ và các phép toán logic (Chương 4). Ví dụ đầu tiên minh hoạ cách sử dụng các biến miền là biến không bắt buộc. Truy vấn Q1 bàn đến trong phần trước có thể được viết như sau: SELECT sname FROM Sailors S, Reserves R WHERE S.sid = R.sid AND bid=103 SELECT sname FROM Sailors, Reserves WHERE Sailors.sid = Reserves.sid AND bid=103 (Q16) Tìm các sid của thuỷ thủ đã phục vụ trên tàu màu 'red'. SELECT R.sid FROM Boats B, Reserves R WHERE B.bid = R.bid AND B.color = 'red' (Q2) Tìm tên các thuỷ thủ đã phục vụ trên tàu màu 'red'. 7/46

FROM Sailors S, Reserves R, Boats B WHERE S.sid = R.sid AND R.bid = B.bid AND B.color = 'red' Truy vấn này chứa phép nối giữa ba bảng, tiếp đến là điều kiện chọn màu của tàu. Kết nối với Sailors cho phép chúng ta tìm tên các thuỷ thủ. (Q3) Tìm màu của các tàu đã được Lubber phục vụ. SELECT B.color FROM Sailors S, Reserves R, Boats B WHERE S.sid = R.sid AND R.bid = B.bid AND S.sname = 'Lubber' (Q4) Tìm tên các thuỷ thủ đã phục vụ trên ít nhất một tàu. SELECT S.sname FROM Sailors S, Reserves R WHERE S.sid = R.sid SQL hỗ trợ một phiên bản chung của select-list, trong đó không chỉ có danh sách các cột. Mỗi mục trong select-list có thể có dạng biểu-thức AS tên-cột, trong đó biểu-thức là một biểu thức toán hoặc một xâu ký tự của các cột (tiền tố có thể là một biến miền) và các hằng số. Nó có thể chứa hàm nhóm như sum và count, phần này chúng ta sẽ bàn trong Phần 5. Chuẩn SQL cũng hỗ trợ các biểu thức dạng ngày và tháng, phần này chúng ta sẽ không bàn ở đây. Mặc dù không phải là một thành phần của chuẩn SQL, rất nhiều các hệ thống thực thi cũng hỗ trợ sử dụng các hàm hỗ trợ như sqrt, sin và mod. Biểu thức thông thường trong SQL: Phản ảnh tầm quan trọng của dữ liệu dạng ký tự, SQL: 1999 bao gồm một toán tử mạnh LIKE, còn gọi là SIMILAR. Toán tử này hỗ trợ mạnh mẽ việc tìm kiếm ký tự. Những biểu thức thông thường cũng được hệ điều hành Unix hỗ trợ phục vụ cho tìm kiếm xâu ký tự, mặc dù cú pháp có khác nhau một chút. Đại số quan hệ và SQL: Tập các phép toán trong SQL có thể thực thi trong đại số quan hệ. (Q17) Tăng rating lên 1 cho những người đã phục vụ trên hai tàu khác nhau trong một ngày. SELECT S.sname, S.rating+1 AS rating FROM Sailors S, Reserves R1, Reserves R2 WHERE S.sid = R1.sid AND S.sid = R2.sid AND R1.day = R2.day AND R1.bid <> R2.bid SELECT S1.sname AS name1, S2.sname AS name2 FROM Sailors S1, Sailors S2 WHERE 2*S1.rating = S2.rating-1 Thêm vào đó, SQL cung cấp khả năng so sánh mẫu thông qua toán tử LIKE, cùng với việc sử dụng ký hiệu % (thay thế cho số không hoặc nhiều ký tự bất kỳ) và _ (thay thế 8/46

cho chính xác một ký tự bất kỳ). Vì thế '_AB%' là một mẫu phù hợp với tất cả các xâu có chứa ít nhất 3 ký tự, trong đó ký tự thứ 2 và thứ 3 là A và B tương ứng. Ghi nhớ rằng, không như những toán tử so sánh khác, ký tự trống cũng quan trọng trong toán tử LIKE. Vì thế, 'Jept' ='Jept ' là đúng, trong khi 'Jept' LIKE 'Jept' là sai. Một ví dụ sử dụng LIKE trong truy vấn như sau: (Q18) Tìm tuổi các thuỷ thủ có tên bắt đầu và kết thúc bằng ký tự B và có ít nhất 3 ký tự. SELECT S.age FROM Sailors S WHERE S.sname LIKE 'B_%B' Hợp, giao và trừ SQL cung cấp 3 cấu trúc thực hiện trên tập hợp, phần mở rộng của các dạng truy vấn cơ bản phía trước. Vì kết quả của một truy vấn là tập hợp các dòng nên việc xem xét đến các phép toán như hợp (UNION), giao (INTERSECT), trừ (EXCEPT) là rất tự nhiên. SQL hỗ trợ ba phép toán này thông qua từ khoá UNION, INTERSECT, and EXCEPT. SQL cũng cung cấp các phép toán tập hợp khác: IN (để kiểm tra một phần tử nào đó có ở trong tập hợp hay không), op ANY, op ALL (để so sánh một giá trị cùng với các phần tử trong một tập hợp nào đó, sử dụng phép so sánh op), và EXIST (để kiểm tra một tập hợp có rỗng hay không), Chúng ta khám phá các toán tử UNION, INTERSECT, và EXCEPT trong phần này, và các toán tử khác trong Phần 4. Xem xét truy vấn sau đây: (Q5) Tìm tên các thuỷ thủ đã phục vụ trên tàu màu đỏ hoặc màu xanh. SELECT S.sname FROM Sailors S, Reserves R, Boats B WHERE S.sid = R.sid AND R.bid = B.bid AND (B.color = 'red' OR B.color = 'green') (Q6) Tìm tên các thuỷ thủ đã phục vụ trên cả hai tàu màu đỏ và màu xanh. Nếu chúng ta chỉ thay thế OR bằng AND, chúng ta sẽ nhận được tên các thuỷ thủ đã phục vụ trên một tàu có hai màu đỏ và xanh. Một ràng buộc tham chiếu chỉ ra rằng bid là khoá của Boats chứng tỏ rằng cùng một tàu không thể có hai màu, vì thế sự thay đổi AND cho OR trong truy vấn trước sẽ trả lại kết quả là một tập rỗng. Câu lệnh đúng của Q6 sử dụng toán tử AND như sau: SELECT S.sname FROM Sailors S, Reserves R1, Boats B1, Reserves R2, Boats B2 WHERE S.sid = R1.sid AND R1.bid = B1.bid AND S.sid = R2.sid AND R2.bid = B2.bid AND B1.color='red' AND B2.color = 'green' 9/46

Truy vấn trước rất khó để hiểu (và cũng không hiệu quả cho việc thực hiện). Giải pháp tốt cho hai truy vấn này là sử dụng UNION và INTERSECT. Truy vấn Q5 có thể viết lại như sau: SELECT S.sname FROM Sailors S, Reserves R, Boats B WHERE S.sid = R.sid AND R.bid = B.bid AND B.color = 'red' UNION SELECT S2.sname FROM Sailors S2, Boats B2, Reserves R2 WHERE S2.sid = R2.sid AND R2.bid = B2.bid AND B2.color = 'green' SELECT S.sname FROM Sailors S, Reserves R, Boats B WHERE S.sid = R.sid AND R.bid = B.bid AND B.color = 'red' INTERSECT SELECT S2.sname FROM Sailors S2, Boats B2, Reserves R2 WHERE S2.sid = R2.sid AND R2.bid = B2.bid AND B2.color = 'green' Như chúng ta đã quan sát trong chương 4, vấn đề này tồn tại bởi vì sname không xác định được một thuỷ thủ nào đó, vì sname không phải là khoá của Sailor. Nếu chúng ta chọn sid thay cho sname, chúng ta sẽ đưa ra được tập các thuỷ thủ đã phục vụ trên cả hai tàu màu đỏ và màu xanh. (Để đưa ra được tên các thuỷ thủ như yêu cầu của truy vấn, chúng ta sẽ phải sử dụng đến truy vấn lồng nhau, chúng ta sẽ bàn đến ví dụ này trong Phần 5.4.4) Truy vấn tiếp theo minh hoạ phép toán tập hợp trong SQL là: (Q19) Tìm sid của các thuỷ thủ đã phục vụ trên tàu màu đỏ, nhưng không phục vụ trên tàu màu xanh. SELECT S.sid FROM Sailors S, Reserves R, Boats B WHERE S.sid = R.sid AND R.bid = B.bid AND B.color = 'red' EXCEPT SELECT S2.sid FROM Sailors S2, Reserves R2, Boats B2 WHERE S2.sid = R2.sid AND R2.bid = B2.bid AND B2.color ='green' Ngoài ra, vì quan hệ Reserves chứa trường sid nên chúng ta không cần tìm trong quan hệ Sailors, và chúng ta có thể sử dụng một truy vấn đơn giản hơn. SELECT R.sid FROM Boats B, Reserves R WHERE R.bid = B.bid AND B.color = 'red' EXCEPT SELECT R2.sid FROM Boats B2, Reserves R2 WHERE R2.bid = B2.bid AND B2.color = 'green' (Q20) Tìm tất cả các sid của thuỷ thủ có rating là 10 hoặc đã phục vụ trên tàu 104. SELECT S.sid FROM Sailors S WHERE S.rating = 10 UNION SELECT R.sid FROM Reserves R WHERE R.bid = 104 10/46

Truy vấn lồng nhau Một trong các tính năng mạnh mẽ nhất của SQL là truy vấn lồng nhau. Một truy vấn lồng nhau là một truy vấn có một hay nhiều truy vấn khác bên trong nó, truy vấn bên trong được gọi là truy vấn con. Khi viết một truy vấn, đôi khi chúng ta cần biểu diễn một điều kiện, điều kiện đó liên quan đến kết quả của một truy vấn khác. Truy vấn con thông thường xuất hiện trong mệnh đề WHERE. Truy vấn con đôi khi cũng xuất hiện trong mệnh đề FROM hoặc HAVING (chúng tôi sẽ trình bày trong Phần 5) Phần này chỉ bàn tới những truy vấn con xuất hiện trong mệnh đề WHERE. Cách làm truy vấn con trong các mệnh đề khác cũng tương tự. Những ví dụ về truy vấn con xuất hiện trong mệnh đề FROM sẽ được trình bày trong Phần 5.5.1. Đại số quan hệ và SQL: Sự lồng nhau của các truy vấn là một tính năng không thể biểu diễn được trong đại số quan hệ, nhưng các truy vấn con có thể được chuyển vào đại số, chúng ta sẽ nhìn thấy trong Chương 15. Sự lồng nhau trong SQL được các phép toán logic trên quan hệ hỗ trợ nhiều hơn là được đại số quan hệ hỗ trợ. Trong mối liên quan với một số tính năng khác của SQL, như các toán tử hỗ trợ tập hợp và nhóm, lồng nhau là một cấu trúc thường xuyên được sử dụng. Giới thiệu về các truy vấn lồng nhau Để ví dụ, chúng ta cùng nhau viết lại truy vấn sau sử dụng truy vấn lồng nhau: (Q1) Tìm tên các thuỷ thủ đã phục vụ trên tàu 103. SELECT S.sname FROM Sailors S WHERE S.sid IN ( SELECT R.sid FROM Reserves R WHERE R.bid = 103 ) Truy vấn con tìm ra một tập các sid của thuỷ thủ đã phục vu trên tàu 103 (đó là 22, 31, và 74 trong minh hoạ R2 và S3), và truy vấn bên trên đưa ra tên các thuỷ thủ có sid nằm trong tập đó. Toán tử IN cho phép chúng ta kiểm tra một giá trị có nằm trong một tập các phần tử; một truy vấn SQL được sử dụng để để đưa ra tập các bộ giá trị thoả mãn điều kiện kiểm tra. Ghi nhớ rằng, nếu muốn đưa ra tập các thuỷ thủ không phục vụ trên tàu 103 thì rất đơn giản chỉ cần thay IN bằng NOT IN. Cách tốt nhất để hiểu truy vấn lồng nhau là chỉ nghĩ đến nó trong ngữ cảnh đánh giá truy vấn ở mức khái niệm. Trong ví dụ của chúng ta, chiến lược thực hiện ở đây là: đầu tiên kiểm tra các dòng trong Sailors, sau đó ứng với từng dòng này, thực hiện truy vấn con trên quan hệ Reserves. Nói chung, chiến lược đánh giá khái niệm chúng ta đã sử dụng để biểu diễn việc định nghĩa một truy vấn có thể được mở rộng để biểu diễn truy vấn lồng nhau như sau: Xây dựng phép nhân chéo giữa các bảng trong mệnh đề FROM. Với mỗi dòng trong phép nhân chéo, khi kiểm tra điều kiện trong mệnh đề WHERE, 11/46

tính toán (lại) truy vấn con. Tất nhiên, truy vấn con bản thân nó có thể chứa những truy vấn con khác, trong trường hợp này chúng ta tiếp tục áp dụng ý tưởng này. Để biểu diễn truy vấn lồng nhau nhiều mức, chúng ta viết lại truy vấn Q2 như sau: (Q2) Tìm tên các thuỷ thủ đã phục vụ trên tàu màu đỏ. SELECT S.sname FROM Sailors S WHERE S.sid IN (SELECT R.sid FROM Reserves R WHERE R.bid IN (SELECT B.bid FROM Boats B WHERE B.color = 'red' ) Truy vấn trong cùng tìm ra tập các bid của tàu màu đỏ (102 và 104 trong minh hoạ B1). Truy vấn con phía trên tìm ra tập các thuỷ thủ đã phục vụ trên một trong những tàu này. Trong minh hoạ B1, R2 và S3, tập sid là 22, 31 và 64. Truy vấn trên cùng tìm ra tên các thuỷ thủ có sid nằm trong tập sid trên. Trong các minh hoạ này, kết quả có Dustin, Lubber, và Horatio. Để tìm tên các thuỷ thủ không phục vụ trên tàu màu đỏ, chúng ta chỉ thay thế IN bằng NOT IN. (Q21) Tìm tên các thuỷ thủ chưa từng phục vụ trên tàu nào có màu đỏ. SELECT S.sname FROM Sailors S WHERE S.sid NOT IN ( SELECT R.sid FROM Reserves R WHERE R.bid IN (SELECT B.bid FROM Boats B WHERE B.color = 'red' ) Truy vấn này đưa ra tên các thuỷ thủ có sid không nằm trong tập 22, 31 và 64. Ngược lại với truy vấn Q21, chúng ta có thể sửa truy vấn trước (phiên bản lồng nhau của Q2) bằng việc thay thế IN bằng NOT IN trong truy vấn con bên trong. Việc sửa này sẽ đưa ra tên các thuỷ thủ đã phục vụ trên tàu không phải màu đỏ. Hãy cùng chúng tôi xem xét cụ thể. Trong truy vấn con, chúng ta kiểm tra R.bid không phải là 102 và 104 (bid của những tàu màu đỏ). Truy vấn bên ngoài tìm ra những bộ giá trị trong Reserves có bid không phải là 102 và 104. Trên minh hoạ B1, R2 và S3, truy vấn ngoài trả lại kết quả là tập sid 22, 31, 64 và 74. Cuối cùng, chúng ta tìm ra tên các thuỷ thủ có sid nằm trong tập này. Chúng ta có thể sửa truy vấn lồng nhau Q2 bằng việc thay thế cả hai từ khoá IN bằng NOT IN. Việc thay thế này sẽ giúp tìm ra tên các thuỷ thủ chưa từng phục vụ trên tàu không phải màu đỏ, tức là, họ chỉ phục vụ trên những tàu có màu đỏ. Trên minh hoạ B1, R2 và S3, truy vấn bên ngoài đưa ra tập các sid của thuỷ thủ không phải là 22, 31, 64 và 74. Tập này là 29, 32, 58, 71, 85, và 95. Chúng ta sau đó sẽ tìm ra tên tương ứng của từng thuỷ thủ. 12/46

Truy vấn lồng nhau liên kết Trong các truy vấn lồng nhau chúng ta đã xem xét phía trước, truy vấn bên trong thực hiện độc lập với truy vấn bên ngoài. Thông thường, truy vấn bên trong có thể phụ thuộc vào bản ghi đang xét ở truy vấn bên ngoài (xét về khía cạnh kế hoạch thực hiện truy vấn). Hãy cùng chúng tôi viết lại truy vấn sau: (Q1) Tìm tên các thuỷ thủ đã phục vụ trên tàu 103 SELECT S.sname FROM Sailors S WHERE EXISTS ( SELECT * FROM Reserves R WHERE R.bid = 103 AND R.sid = S.sid ) Toán tử EXISTS là toán tử so sánh trên tập hợp, giống như IN. Nó cho phép chúng ta kiểm tra một giá trị nào đó có tồn tại trong một tập hợp không. Vì thế, với mỗi thuỷ thủ trên dòng S, chúng ta kiểm tra giá trị này trên tập các dòng của Reserves (R) xem có rỗng không. Nếu không rỗng, tức là thuỷ thủ S đã phục vụ trên tàu 103 và chúng ta sẽ đưa ra tên của họ. Truy vấn con rõ ràng phụ thuộc vào dòng đang xét S và phải xem xét trên từng dòng của Sailors. Sự xuất hiện của S trong truy vấn con (có dạng S.sid) được gọi là liên kết, và truy vấn như thế này gọi là những truy vấn liên kết. Trong ví dụ phía trước, bằng việc sử dụng NOT EXIST thay cho EXIST, chúng ta có thể đưa ra tên các thuỷ thủ chưa từng phục vụ trên tàu màu đỏ. Liên quan chặt chẽ đến EXISTS là xác nhận UNIQUE. Khi chúng ta áp dụng UNIQUE trong truy vấn con, nó sẽ trả lại True nếu không có dòng nào xuất hiện hai lần trong kết quả của truy vấn con, có nghĩa là, ở đó không có sự trùng nhau; trong trường hợp đặc biệt, nó trả lại True nếu kết quả truy vấn con rỗng (Và đây cũng là trường hợp của NOT UNIQUE) Các toán tử so sánh trên tập hợp Chúng ta đã xem xét một số toán tử trên tập hợp là EXISTS, IN và UNIQUE và trường hợp phủ định tương ứng. SQL cũng hỗ trợ op ANY và op ALL, trong đó op là một trong những phép so sánh?>, <=, =, <, >=? (SOME cũng có thể sử dụng, nhưng nó cùng nghĩa với ANY) (Q22) Tìm những thuỷ thủ có rating lớn hơn của bất kỳ thuỷ thủ nào có tên là Horatio. SELECT S.sid FROM Sailors S WHERE S.rating > ANY ( SELECT S2.rating FROM Sailors S2 WHERE S2.sname = 'Horatio' ) Nếu chúng ta có một vài thuỷ thủ có tên là Horatio, truy vấn này tìm ra tất cả các thuỷ thủ có rating cao hơn một thủy thủ nào đó có tên Horatio. Trên minh hoạ S3, kết quả truy vấn này là các sid 31, 32, 58, 71, và 74. Nếu ở đó không có thuỷ thủ nào có tên là Horatio thì sao? Trong trường hợp này so sánh S.rating> ANY được định nghĩa để trả 13/46

về giá trị False, và truy vấn trên trả về tập kết quả là rỗng. Để hiểu những so sánh có chứa ANY, chúng ta cần phải biết rằng những so sánh được thực hiện so sánh lặp đi lặp lại. Trong ví dụ trên, S.rating được so sánh thành công với một số giá trị rating trong kết quả của truy vấn con. Truy vấn con phải trả lại dòng mà kết quả so sánh là True. So sánh trả về giá trị True nếu một trong số so sánh trên từng dòng trả lại giá trị True. (Q23) Tìm các thuỷ thủ có rating lớn hơn của tất cả các thuỷ thủ có tên là Horatio. Chúng ta có thể đạt được yêu cầu trên bằng việc sửa truy vấn Q22 một chút, chỉ cần thay thế ANY bằng ALL trong mệnh đề WHERE của truy vấn ngoài. Trong minh hoạ S3, chúng ta sẽ có sids là 58 và 71. Nếu ở đó không có thuỷ thủ nào có tên là Horatio, so sánh S.rating>ALL sẽ trả về giá trị True. Sau đó, truy vấn sẽ đưa ra tên của tất cả các thuỷ thủ. Một lần nữa, chúng ta lại cần phải biết rằng việc thực hiện so sánh được lặp đi lặp lại. So sánh phải trả về giá trị True nếu tất cả các so sánh trên từng dòng trả lại giá trị True. Một minh hoạ khác sử dụng ALL, xem xét truy vấn sau: (Q24) Tìm tất cả các thuỷ thủ có rating cao nhất. SELECT S.sid FROM Sailors S WHERE S.rating >= ALL ( SELECT S2.rating FROM Sailors S2 ) Truy vấn con đưa ra tập rating của tất cả các thuỷ thủ. Điều kiện WHERE chỉ được thoả mãn S.rating lớn hơn hoặc bằng tất cả các giá trị rating trong truy vấn con, tức là, khi nó là giá trị rating lớn nhất. Trong minh họa S3, điều kiện thoả mãn với rating bằng 10, và các sid có rating này là 58 và 71. Ghi nhớ rằng IN và NOT IN lần lượt tương đương với =ANY và <>ALL. Một số ví dụ khác về truy vấn lồng nhau Chúng ta cùng nhau xem lại một số truy vấn phía trên sử dụng toán tử INTERSECT. (Q6) Tìm tên các thuỷ thủ đã phục vụ trên tàu màu 'red' và tàu màu 'green' SELECT S.sname FROM Sailors S, Reserves R, Boats B WHERE S.sid = R.sid AND R.bid = B.bid AND B.color = 'red' AND S.sid IN ( SELECT S2.sid FROM Sailors S2, Boats B2, Reserves R2 WHERE S2.sid = R2.sid AND R2.bid = B2.bid AND B2.color = 'green' ) 14/46

Truy vấn này có thể được hiểu như sau: Tìm tất cả thuỷ thủ đã phục vụ trên tàu màu đỏ và thêm nữa, các sid này có trong tập các sid của thuỷ thủ đã phục vụ trên tàu màu xanh. Minh hoạ này chỉ ra cách thức một truy vấn sử dụng INTERSECT có thể được viết lại sử dụng IN, nó sẽ rất hữu ích nếu hệ thống của bạn không hỗ trợ toán tử INTERSECT. Những truy vấn sử dụng EXCEPT có thể viết lại tương đương sử dụng NOT IN. Để tìm những sid của thuỷ thủ đã phục vụ trên tàu màu đỏ nhưng chưa phục vụ trên tàu màu xanh, chúng ta chỉ cần thay thế từ khoá IN trong truy vấn trước bằng từ khoá NOT IN. Viết lại truy vấn (Q6) sử dụng INTERSECT là phức tạp hơn vì chúng ta phải sử dụng các sid để xác định các thuỷ thủ và phải trả về tên của họ: SELECT S3.sname FROM Sailors S3 WHERE S3.sid IN (( SELECT R.sid FROM Boats B, Reserves R WHERE R.bid = B.bid AND B.color = `red' ) INTERSECT (SELECT R2.sid FROM Boats B2, Reserves R2 WHERE R2.bid = B2.bid AND B2.color = 'green' )) Ví dụ tiếp theo của chúng ta minh hoạ cách biểu diễn SQL của phép chia trong đại số quan hệ. (Q9) Tìm ra tên các thuỷ thủ đã phục vụ trên tất cả các tàu. SELECT S.sname FROM Sailors S WHERE NOT EXISTS (( SELECT B.bid FROM Boats B ) EXCEPT (SELECT R.bid FROM Reserves R WHERE R.sid = S.sid )) Ghi nhớ rằng truy vấn này là liên kết- với mỗi thuỷ thủ S, chúng ta kiểm tra để thấy rằng tập các tàu mà S đã phục vụ là một tập chứa tất cả các tàu. Cách khác để thực hiện truy vấn này mà không sử dụng EXCEPT như sau: SELECT S.sname FROM Sailors S WHERE NOT EXISTS ( SELECT B.bid FROM Boats B WHERE NOT EXISTS ( SELECT R.bid FROM Reserves R WHERE R.bid = B.bid AND R.sid = S.sid )) Trong đó, mỗi thủy thủ chúng ta kiểm tra thì không có một tàu nào mà thuỷ thủ này chưa phục vụ. SQL: 1999 Các hàm nhóm: Tập hợp các hàm nhóm được mở rộng rất nhiều trong chuẩn mới, bao gồm một số hàm thống kê như độ lệch chuẩn, hiệp phương sai. Tuy nhiên, các hàm nhóm mới được đóng gói trong SQL/OLAP không phải được tất cả các nhà sản xuất hỗ trợ. 15/46

Hàm nhóm Khi truy vấn dữ liệu, chúng ta thường muốn thực hiện một số tính toán hoặc tổng kết trên những dữ liệu đó. Như chúng ta đã biết trong chương trước, SQL cho phép thực hiện các biểu thức toán học. Chúng ta sẽ xem xét khả năng tính toán trên các nhóm dữ liệu thông qua các hàm như MIN và SUM. Những đặc tính này là một trong những phần mở rộng của đại số quan hệ. SQL hỗ trợ năm hàm nhóm, có thể áp dụng trên bất kỳ cột nào, giả sử A, của một quan hệ: 1. COUNT([DISTINCT] A): Số các giá trị (khác nhau) tại cột A 2. SUM([DISTINCT] A): Tổng số của tất cả các giá trị (khác nhau) tại cột A. 3. AVG([DISTINCT] A): Giá trị trung bình của tất cả các giá trị (khác nhau) tại cột A. 4. MAX(A): Giá trị lớn nhất trên cột A 5. MIN(A): Giá trị lớn nhất trên cột A Ghi nhớ rằng sẽ không có ý nghĩa nếu chỉ ra từ khoá DISTINCT đằng sau MIN hoặc MAX. (Q25) Tìm tuổi trung bình của tất cả thuỷ thủ. SELECT AVG (S.age) FROM Sailors S Trong minh hoạ S3, tuổi trung bình là 37.4. Tất nhiên, mệnh đề WHERE có thể được sử dụng để giới hạn bớt các thuỷ thủ tham gia vào hàm nhóm. (Q26) Tìm tuổi trung bình của các thuỷ thủ có rating bằng 10 SELECT AVG (S.age) FROM Sailors S WHERE S.rating = 10 Chỉ có hai thuỷ thủ thoả mãn điều kiện này, tuổi trung bình của họ là 25.5. MIN hoặc MAX có thể được sử dụng thay thế cho AVG trong truy vấn trên để tìm ra tuổi ít nhất và tuổi nhiều nhất của thuỷ thủ. Tuy nhiên, tìm cả tên và tuổi của thuỷ thủ lớn tuổi nhất thì phức tạp hơn, như minh hoạ trong truy vấn tiếp theo. (Q27) Tìm tên và tuổi của thuỷ thủ lớn tuổi nhất. Xem xét truy vấn sau và cố gắng đưa ra kết quả của truy vấn này. SELECT S.sname, MAX (S.age) FROM Sailors S 16/46

Mục đích của truy vấn này là trả lại chỉ tuổi lớn nhất và tên của người thuỷ thủ tương ứng. Tuy nhiên, truy vấn này không hợp lệ trong SQL - nếu mệnh đề SELECT sử dụng một hàm nhóm, thì nó phải sử dụng chỉ những hàm nhóm trừ khi truy vấn đó có chứa mệnh đề GROUP BY! (Cụ thể của hạn chế này sẽ được bàn đến trong mệnh đề GROUP BY ở Phần 5.5.1). Vì thế, chúng ta không thể sử dụng Max(S.age) cùng với S.name trong mệnh đề SELECT. Chúng ta phải sử dụng đến truy vấn con để thực hiện yêu cầu trong Q27. SELECT S.sname, S.age FROM Sailors S WHERE S.age = ( SELECT MAX (S2.age) FROM Sailors S2 ) Quan sát thấy rằng, chúng ta sử dụng kết quả của hàm nhóm trong truy vấn con như một đối số của phép so sánh. Nói đúng ra, chúng ta so sánh giá trị tuổi của tất cả các thuỷ thủ với kết quả của truy vấn con. Tuy nhiên, vì sử dụng hàm nhóm, truy vấn con đảm bảo sẽ trả về giá trị duy nhất trong một trường duy nhất, và SQL chuyển quan hệ thành một giá trị để có thể so sánh được. Sau đây là một truy vấn cho kết quả tương đương trong chuẩn SQL, tuy nhiên không nhiều hệ thống hỗ trợ kiểu truy vấn này. SELECT S.sname, S.age FROM Sailors S WHERE (SELECT MAX (S2.age) FROM Sailors S2 ) = S.age Chúng ta có thể đếm số thuỷ thủ sử dụng mệnh đề COUNT. Ví dụ này minh hoạ việc sử dụng COUNT, nó hữu ích khi chúng ta muốn đếm xem có tất cả bao nhiêu thuỷ thủ. (Q28) Đếm xem có tổng số bao nhiêu thuỷ thủ SELECT COUNT (*) FROM Sailors S Chúng ta có thể nghĩ ký tự * như cách viết ngắn để thay thế tất cả các cột. Ngược lại với truy vấn này, truy vấn sau đây chỉ ra số các thuỷ thủ có tên khác nhau. (Ghi nhớ rằng sname không phải là khoá) (Q29) Đếm số các thuỷ thủ có tên khác nhau SELECT COUNT ( DISTINCT S.sname ) FROM Sailors S Trong minh hoạ S3, kết quả của truy vấn Q28 là 10, trong khi kết quả của Q29 là 9 vì có hai thuỷ thủ có tên trùng nhau là Horatio. Nếu bỏ từ khóa DISTINCT, kết quả của Q29 là 10 vì tên Horatio được đếm hai lần. Vì thế, nếu không có DISTINCT thì Q29 và Q28 tương đương nhau. Tuy nhiên, sử dụng COUNT(*) là lựa chọn tốt khi có thể. Hàm nhóm thường được sử dụng kết hợp với cấu trúc ANY và ALL. Ví dụ, xem xét truy vấn sau: 17/46

(Q30) Tìm tên các thủy thủ người lớn tuổi hơn người già nhất có rating bằng 10. SELECT S.sname FROM Sailors S WHERE S.age > ( SELECT MAX ( S2.age ) FROM Sailors S2 WHERE S2.rating = 10 ) Trong minh họa S3, thủy thủ già nhất có rating bằng 10 là sid=58, tuổi là 35. Tên các thủy thủ lớn tuổi hơn người này là Bob, Dustin, Horatio, và Lubber. Nếu sử dụng ALL, truy vấn này có thể được viết như sau: SELECT S.sname FROM Sailors S WHERE S.age > ALL ( SELECT S2.age FROM Sailors S2 WHERE S2.rating = 10 ) Nếu thay ANY bằng ALL thì truy vấn sẽ đưa ra tên những người lớn tuổi hơn một người nào đó có rating=10. Việc này sẽ tương đương với việc thay MAX bằng MIN trong truy vấn trên. Đại số quan hệ và SQL: Hàm nhóm là những hàm không thể biểu diễn được trong đại số quan hệ. Tương tự, cấu trúc nhóm trong SQL không thể biểu diễn được trong đại số. Mệnh đề GROUP BY và HAVING Phần trước, chúng ta đã áp dụng toán tử nhóm tới tất cả các dòng trong quan hệ. Thường thì chúng ta muốn áp dụng các toán tử nhóm tới một số các dòng trong quan hệ. Ví dụ, xem xét truy vấn sau: (Q31) Tìm tuổi của các thủy thủ trẻ nhất ứng với từng mức rating. Nếu chúng ta biết rằng rating là các số nguyên nằm trong khoảng từ 1 đến 10, chúng ta sẽ viết 10 truy vấn theo dạng: SELECT MIN (S.age) FROM Sailors S WHERE S.rating = i trong đó i=1,2,, 10. Viết 10 truy vấn như thế thì rất nhàm chán và mệt mỏi. Quan trọng hơn, trên thực tế chúng ta có lẽ không biết có bao nhiêu mức rating tồn tại. Để viết truy vấn kiểu này, chúng ta cần mở rộng các chức năng cơ bản của dạng câu lệnh SQL cơ bản, như mệnh đề GROUP BY. Trên thực tế, sự mở rộng này cũng bao gồm cả mệnh đề HAVING, là mệnh đề có thể lựa chọn để thêm vào điều kiện của nhóm (ví dụ, chúng ta có thể chỉ đưa ra những mức rating>6). Dạng chung của truy vấn SQL có mở rộng như sau: 18/46

SELECT [ DISTINCT ] select-list FROM from-list WHERE qualification GROUP BY grouping-list HAVING groupqualification Sử dụng mệnh đề GROUP BY, chúng ta có thể viết Q31 như sau: SELECT S.rating, MIN (S.age) FROM Sailors S GROUP BY S.rating Hãy cùng chúng tôi xem xét một số điểm quan trọng liên quan đến các mệnh đề mới này: Cụm Select-list trong mệnh đề SELECT chứa (1) danh sách tên các cột và (2) danh sách các hàm nhóm có dạng aggop (colum-name) AS new-name. Lựa chọn AS new-name cung cấp cho cột này một tên mới trong kết quả của truy vấn. Bất kỳ toán tử nhóm nào cũng có thể được sử dụng trong aggop. Tất cả các cột xuất hiện trong (1) cũng phải xuất hiện trong grouping-list. Lý do là mỗi dòng trong kết quả tương ứng với một nhóm. Nếu một cột xuất hiện trong danh sách (1), nhưng không xuất hiện trong group-list, thì kết quả của truy vấn sẽ không rõ ràng. Các biểu thức xuất hiện trong group-qualification của mệnh đề HAVING phải có một giá trị duy nhất ứng với mỗi nhóm. Mệnh đề HAVING xác định những dòng kết quả nào của nhóm sẽ được đưa ra. Vì thế, cột xuất hiện trong groupqualification phải là đối số của một hàm nhóm, hoặc nó cũng phải xuất hiện trong grouping-list. Nếu mệnh đề GROUP BY bị bỏ đi, toàn bộ bảng được đề cập đến như là một nhóm. Chúng ta sẽ giải thích về mặt ngữ nghĩa của điều này thông qua ví dụ. Xem xét truy vấn: (Q32) Tìm tuổi của thủy thủ trẻ nhất (ít nhất 18 tuổi) ứng với mỗi mức rating có ít nhất hai thủy thủ. SELECT S.rating, MIN (S.age) AS minage FROM Sailors S WHERE S.age >= 18 GROUP BY S.rating HAVING COUNT (*) > 1 Chúng ta sẽ đánh giá truy vấn này trong minh họa S3 của Sailors trong Hình 10. Mở rộng chiến lược thực hiện truy vấn ở mức khái niệm đã trình bày trong Phần 2, truy vấn này thực hiện như sau: Bước đầu tiên là thực hiện phép nhân chéo trên các bảng trong from-list. Vì chỉ có một quan hệ trong from-list trong Q23 nên kết quả của phép nhân chéo này chính là quan hệ trong Hình 10. 19/46

Minh họa S3 của Sailors Bước thứ hai là thực hiện điều kiện trong mệnh đề WHERE, S.age>=18. Bước này loại đi dòng <71, Zorba, 10, 16.0>. Bước ba loại đi những cột không mong muốn. Chỉ những cột được đề cập trong mệnh đề SELECT, mệnh đề GROUP BY, hoặc mệnh đề HAVING là cần thiết, có nghĩa là chúng ta có thể bỏ đi sid và sname trong ví dụ của chúng ta. Kết quả chỉ ra trong Hình 11. Quan sát thấy rằng có hai dòng khác nhau với rating=3 và age=25, SQL không loại đi những bộ giá trị trùng nhau trừ khi chúng được yêu cầu bằng việc sử dụng từ khóa DISTINCT! Bước thứ 4 là sắp xếp bảng tùy theo mệnh đề GROUP BY để xác định các nhóm. Kết quả của bước này chỉ ra trong Hình 12. Kết quả sau Bước 3 20/46

Kết quả sau Bước 4 Bước thứ 5 là áp dụng group-qualification trong mệnh đề HAVING, đó là điều kiện COUNT(*)>1. Bước này loại đi những nhóm có rating bằng 1, 9 và 10. Quan sát thấy rằng thứ tự xem xét điều kiện trong mệnh đề WHERE và HAVING rất có ý nghĩa: Nếu mệnh đề WHERE không được xem xét đầu tiên, nhóm có rating=10 sẽ có mặt trong kết quả (mặc dù có một dòng không thỏa mãn điều kiện age>=18). Bước thứ 6 là đưa ra một dòng kết quả ứng một nhóm còn lại. Dòng kết quả ứng với một nhóm chứa tập con của các cột trong nhóm, cộng với một hoặc nhiều cột trong hàm nhóm. Trong ví dụ của chúng ta, mỗi dòng kết quả có cột rating và minage, cột đã được tính toán bằng cách áp dụng hàm MIN cho cột age. Kết quả của bước này chỉ ra trong Hình 13. Kết quả cuối cùng của truy vấn SQL:1999 đã giới thiệu hai hàm tập hợp mới, EVERY và ANY. Để minh họa cho những hàm này, chúng ta có thể thay thế mệnh đề HAVING trong ví dụ của chúng ta bằng HAVING COUNT(*)>1 AND EVERY(S.age<=60) Bước thứ 5 của quá trình thực hiện bị thay đổi do những thay đổi trong mệnh đề HAVING. Xem xét kết quả trong bước 4, chỉ ra trong Hình 12. Từ khóa EVERY yêu cầu tất cả các dòng trong nhóm phải thỏa mãn điều kiện trong group-qualification. Nhóm có rating=3 không thỏa mãn điều kiện và bị xóa, kết quả chỉ ra trong Hình 14. Có thể thay thế truy vấn trên bằng truy vấn theo sau, điều kiện của age được đặt lên mệnh đề WHERE thay vì để ở HAVING: 21/46

SELECT S.rating, MIN (S.age) AS minage FROM Sailors S WHERE S.age >= 18 AND S.age<=60 GROUP BY S.rating HAVING COUNT (*) > 1 Bây giờ, kết quả sau bước 3 của quá trình thực hiện không chứa dòng có age=63.5. Tuy nhiên, nhóm có rating=3 thỏa mãn điều kiện COUNT(*)>1, vì nó vẫn có hai dòng, và thỏa mãn điều kiện trong group-qualification được kiểm tra trong bước 5. Kết quả cuối cùng của truy vấn này chỉ ra trong Hình 15. Kết quả sau Bước 3 Kết quả sau Bước 4 Các ví dụ khác của truy vấn sử dụng hàm nhóm (Q33) Với mỗi tàu màu đỏ, tìm số lượng các phục vụ (reservation) cho từng tàu. SELECT B.bid, COUNT (*) AS sailorcount FROM Boats B, Reserves R WHERE R.bid = B.bid AND B.color = 'red' GROUP BY B.bid Trên minh họa B1 và R2, kết quả của truy vấn này chứa hai bộ giá trị?102, 3? và?104, 2?. Quan sát thấy rằng cách viết của truy vấn phía sau đây sẽ không hợp lệ: SELECT B.bid, COUNT (*) AS sailorcount FROM Boats B, Reserves R WHERE R.bid = B.bid GROUP BY B.bid HAVING B.color = 'red' Cho dù là group-qualificationb.color='red' là giá trị duy nhất trên mỗi nhóm, vì thuộc tính được nhóm bid là khóa của Boats (vì thế xác định được duy nhất màu tương ứng), thì SQL cũng không cho phép truy vấn này. Chỉ những cột xuất hiện trong mệnh đề GROUP BY thì mới được phép xuất hiện trong mệnh đề HAVING, trừ khi nó xuất hiện như là đối số của một hàm nhóm trong mệnh đề HAVING. 22/46

(Q34) Tìm tuổi trung bình của các thủy thủ ứng với mỗi mức rating có ít nhất hai thủy thủ. SELECT S.rating, AVG (S.age) AS avgage FROM Sailors S GROUP BY S.rating HAVING COUNT (*) > 1 Sau khi xác định các nhóm dựa trên rating, chúng ta giữ lại chỉ những những nhóm có ít nhất hai thủy thủ. Kết quả của truy vấn áp dụng trên minh họa S3 được chỉ ra trong Hình 16. Kết quả Q34 Kết quả Q35 Kết quả Q36 Thêm vào một truy vấn con bên trong mệnh đề HAVING của Q34 (cách viết như với mệnh đề WHERE). Ghi nhớ rằng chúng ta có thể sử dụng S.rating bên trong truy vấn con của mệnh đề HAVING vì nó có một giá trị duy nhất cho nhóm hiện tại của các thủy thủ. SELECT S.rating, AVG ( S.age ) AS avgage FROM Sailors S GROUP BY S.rating HAVING 1 < ( SELECT COUNT (*) FROM Sailors S2 WHERE S.rating = S2.rating ) (Q35) Tìm tuổi trung bình của các thủy thủ (ít nhất 18 tuổi) ứng với mỗi mức rating có ít nhất hai thủy thủ. 23/46

SELECT S.rating, AVG ( S.age ) AS avgage FROM Sailors S WHERE S. age >= 18 GROUP BY S.rating HAVING 1 < ( SELECT COUNT (*) FROM Sailors S2 WHERE S.rating = S2.rating ) Sự khác nhau đối với Q34, chúng ta loại đi những bộ giá trị có age<=18 và nhóm những bộ giá trị còn lại theo rating. Với mỗi nhóm, truy vấn con bên trong mệnh đề HAVING đưa ra số lượng các bộ giá trị của Sailors (không áp dụng điều kiện lựa chọn age<=18) có giá trị rating bằng với nhóm hiện tại đang xét. Nếu một nhóm có ít hơn hai thủy thủ, nó sẽ bị loại đi. Với mỗi nhóm còn lại, chúng ta đưa ra tuổi trung bình. Kết quả của truy vấn này áp dụng trên minh họa S3 chỉ ra trong Hình 15. Ghi nhớ rằng kết quả này tương đương với kết quả của truy vấn Q34, chỉ có sự khác nhau ở nhóm có rating = 10, chúng ta bỏ đi thủy thủ có age=16 trong khi tính tuổi trung bình. (Q36) Tìm tuổi trung bình của các thủy thủ (ít nhất 18 tuổi), với mỗi mức rating chỉ ra trong kết quả phải có ít nhất hai thủy thủ. SELECT S.rating, AVG ( S.age ) AS avgage FROM Sailors S WHERE S. age >18 GROUP BY S.rating HAVING 1 < ( SELECT COUNT (*) FROM Sailors S2 WHERE S.rating = S2.rating AND S2.age >= 18 ) Biểu diễn trên của truy vấn đã có sự thay đổi với Q35. Kết quả của truy vấn Q36 trên minh họa S3 chỉ ra trong Hình 16. Nó khác với kết quả của Q35 là không có bộ giá trị rating =10, vì chỉ có một bộ giá trị có rating=10 và age>=18. Truy vấn Q36 thực sự tương tự với Q32, biểu diễn đơn giản như sau: SELECT S.rating, AVG ( S.age ) AS avgage FROM Sailors S WHERE S. age > 18 GROUP BY S.rating HAVING COUNT (*) > 1 Phát biểu của truy vấn Q36 chỉ ra thực tế rằng mệnh đề điều kiện trong mệnh đề WHERE được áp dụng trước điều kiện nhóm, vì thế, chỉ những thủy thủ có age>18 được đưa vào nhóm. Chúng ta sẽ xem xét cách khác để viết truy vấn này: SELECT Temp.rating, Temp.avgage FROM ( SELECT S.rating, AVG ( S.age ) AS avgage, COUNT (*) AS ratingcount FROM Sailors S WHERE S. age > 18 GROUP BY S.rating ) AS Temp WHERE Temp.ratingcount > 1 Sự thay đổi này mang đến một số điểm đáng chú ý. Đầu tiên, mệnh đề FROM có thể chứa truy vấn con, theo chuẩn SQL. Thứ 2, mệnh đề HAVING không phải lúc nào cũng cần. Bất kỳ mệnh đề HAVING nào cũng có thể được viết lại mà không có nó, nhưng rất nhiều truy vấn sẽ đơn giản hơn nếu chúng ta sử dụng HAVING. Cuối cùng, khi một 24/46

truy vấn con xuất hiện trong mệnh đề FROM, sử dụng từ khóa AS để cung cấp cho nó một tên mới khi cần thiết (vì nếu không thì chúng ta không thể biểu diễn được điều kiện Temp.ratingcount> 1 trong trường hợp này). (Q37) Tìm những rating mà tuổi trung bình của thủy thủ bằng tuổi trung bình nhỏ nhất trên tất cả các mức rating. Chúng ta sử dụng truy vấn này để minh họa rằng các hàm nhóm không thể được lồng nhau. Một cách viết như sau có thể được xem xét: SELECT S.rating FROM Sailors S WHERE AVG (S.age) = ( SELECT MIN (AVG (S2.age)) FROM Sailors S2 GROUP BY S2.rating ) Suy nghĩ một chút cũng thấy rằng truy vấn này không thể thực hiện được cho dù ta giả sử biểu thức MIN(AVG(S2.age)) không hợp lệ được thực hiện. Trong truy vấn con, Sailors được chia vào các nhóm theo rating, và tuổi trung bình được tính trên mỗi nhóm. Với mỗi nhóm, áp dụng MIN trên các giá trị trung bình này sẽ trả lại cùng một giá trị! Cách viết đúng của truy vấn trên như sau. Là cần thiết để đưa ra một bảng phụ lưu tuổi trung bình trên ứng với mỗi mức rating, sau đó tìm ra rating mà tuổi trung bình là nhỏ nhất. SELECT Temp.rating, Temp.avgage FROM ( SELECT S.rating, AVG (S.age) AS avgage, FROM Sailors S GROUP BY S.rating) AS Temp WHERE Temp.avgage =(SELECT MIN (Temp.avgage) FROM Temp ) Kết quả của truy vấn này trên minh họa S3 là?10, 25.5?. Xem như là bài tập, người đọc nên xem xét xem truy vấn sau ra kết quả tương đương không, nếu không thì vì sao không: SELECT Temp.rating, MIN ( Temp.avgage ) FROM ( SELECT S.rating, AVG (S.age) AS avgage, FROM Sailors S GROUP BY S.rating ) AS Temp GROUP BY Temp.rating Các giá trị NULL Ở trên, chúng ta đã giả sử rằng giá trị các cột trong từng dòng đã được biết. Nhưng thực tế, ta sẽ gặp rất nhiều trường hợp mà giá trị này không có. Ví dụ, khi một thủy thủ, như Dan, tham gia một câu lạc bộ du thuyền, anh ấy có lẽ không cần đăng ký rating của mình.vì định nghĩa của bảng có cột rating, nên giá trị rating của Dan không biết phải 25/46

thêm gì vào đó. Điều cần làm ở đây là thêm vào đó một giá trị đặc biệt được gọi là giá trị chưa biết. Giả sử định nghĩa bảng Sailors được thêm vào một cột là maiden-name. Tuy nhiên, chỉ có những phụ nữ đã lập gia đình mới có họ của chồng (maiden-name). Với những phụ nữ độc thân và những người đàn ông, giá trị maiden-name sẽ không có. Một lần nữa, chúng ta phải thêm giá trị nào vào cột này cho Dan? SQL cung cấp một giá trị cột đặc biệt gọi là null cho những trường hợp này. Sử dụng định nghĩa bảng Sailors, chúng ta sẽ nhập vào dòng?98; Dan; null; 39? để biểu diễn Dan, sự hiện diện của giá trị null làm nảy sinh nhiều vấn đề phức tạp, và chúng ta xem xét tác động của giá trị null đối với SQL trong phần này. Các so sánh sử dụng giá trị Null Xem xét một so sánh là rating=8. Nếu áp dụng so sánh này cho dòng của Dan, kết quả so sánh sẽ True hay False? Vì rating của Dan không biết, nó là nguyên nhân để có thể nói rằng phép so sánh này có kết quả là unknown. Trên thực tế, so sánh rating>8 và rating<8 sẽ thực hiện tốt. Nếu chúng ta so sánh hai giá trị null sử dụng >, <, = và nhiều hơn nữa, kết quả luôn luôn là unknown. Ví dụ, nếu chúng ta có null trong hai dòng phân biệt của quan hệ Sailor, bất kỳ so sánh nào cũng trả lại kết quả unknown. SQL cũng cung cấp một phép so sánh đặc biệt IS NULL để kiểm tra giá trị của cột có null hay không; ví dụ, chúng ta có thể viết rating IS NULL, sẽ trả lại kết quả true trên dòng biểu diễn Dan. Chúng ta cũng có thể viết rating IS NOT NULL, sẽ trả lại kết quả false trên dòng biểu diễn Dan. Các kết nối logic AND, OR, NOT Bây giờ chúng ta tìm hiểu cách biểu diễn rating = 8 OR age < 40 và rating = 8 AND age < 40 có nghĩa là gì? Xem xét bản ghi Dan một lần nữa, vì age < 40, biểu thức đầu tiên trả lại giá trị True vì chúng ta không cần quan tâm đến rating, nhưng biểu thức thứ hai thì sao? Chúng ta chỉ có thể nói là unknown. Nhưng ví dụ này đưa ra một điểm quan trọng- đó là chúng ta có các giá trị null, chúng ta phải định nghĩa các toán tử logic AND, OR, NOT mà kết quả trả về có ba giá trị true, false, và unknown. Chúng ta mở rộng cách hiểu bình thường của AND, OR, NOT để có thể bao được những trường hợp khi mà các đối số là unknown như trên. Biểu diễn NOT unknown được định nghĩa như unknown. OR của hai đối số cho kết quả là true nếu một trong hai đối số là true, và unknown nếu một trong các đối số là false và các trường hợp khác là unknown. (Nếu cả hai đối số là false, thì tất nhiên, kết quả sẽ là false). AND của hai đối số cho kết quả là false nếu một trong hai đối số là false, và unknown nếu một trong hai đối số là unknown và những trường hợp khác là true hoặc unknown. (Nếu cả hai đối số là true, kết quả là true). 26/46

Ảnh hưởng đến cấu trúc của SQL Biểu thức logic xuất hiện trong rất nhiều câu lệnh SQL, và ảnh hưởng của giá trị null phải được nhận ra. Ví dụ, điều kiện trong mệnh đề WHERE loại đi những dòng (trong phép nhân chéo của các bảng mà tên có ở mệnh đề FROM) mà kết quả kiểm tra điều kiện không trả về giá trị true. Vì thế, nếu có sự hiện diện của giá trị null, bất kỳ dòng nào cho kết quả là false hoặc unknown đều bị loại bỏ. Loại bỏ các dòng có giá trị unknown có ảnh hưởng rất tinh tế và ý nghĩa trên các truy vấn, đặc biệt đối với các truy vấn con có mệnh đề EXISTS hoặc UNIQUE. Vấn đề khác khi xuất hiện giá trị null là khi cần xác định hai dòng trong một minh hoạ quan hệ có trùng nhau hay không. SQL định nghĩa rằng hai dòng là trùng nhau nếu các cột tương đương có giá trị bằng nhau, hoặc cả hai đều chứa giá trị null. Đối lập với định nghĩa này là thực tế rằng nếu chúng ta so sánh hai giá trị null sử dụng =, kết quả sẽ là unknown! Trong ngữ cảnh của các dòng trùng nhau, so sánh này hoàn toàn được trả lại kết quả true, đó là một điều dị thường. Như chúng ta mong đợi, các phép toán +,?, *, và / tất cả trả lại giá tri null nếu một trong các đối số là null. Tuy nhiên, nulls có thể gây ra một số điều không mong đợi khi thực hiện các phép toán trên tập hợp. COUNT(*) coi giá trị null giống như những giá trị khác, vì thế, giá trị này vẫn được đếm. Tất cả các toán tử nhóm khác (COUNT, SUM, AVG, MIN, MAX và những biến dạng của khi kết hợp với DISTINCT) hoàn toàn bỏ đi những giá trị null- vì thế SUM không được hiểu chỉ là phép cộng trên tất cả các giá trị; bước chuẩn bị ở đây là bỏ đi tất cả các giá trị null phải được đề cập tới. Như là một trường hợp đặc biệt, nếu một trong các toán tử này- không phải là COUNT- được áp dụng với chỉ những giá trị null, thì kết quả sẽ trả lại giá trị null. Phép nối ngoài (Outer joins) Một số những biến thể của phép nối dựa trên các giá trị null, gọi là phép nối ngoài, được SQL hỗ trợ. Xem xét việc nối hai bảng, giả sử Sailors c Reserves. Các bộ giá trị của Sailors không so sánh được với một dòng nào đó trong Reserves theo điều kiện nối sẽ không xuất hiện trong kết quả. Trong phép nối ngoài thì không phải như vậy. Trên thực tế, có một vài dạng của phép nối ngoài. LEFT OUTER JOIN trả về tất cả các dòng có ở quan hệ Sailors, mặc dù các dòng ở Reserves không thỏa mãn phép so sánh. RIGHT OUTER JOIN trả về tất cả các dòng có ở quan hệ Reserves, mặc dù các dòng ở quan hệ Sailors không thỏa mãn phép so sánh. FULL OUTER JOIN trả về tất cả các dòng từ quan hệ Sailors và Reserves mặc dù không thỏa mãn điều kiện so sánh. (Tất nhiên, những dòng mà thoả mãn điều kiện so sánh luôn luôn xuất hiện trong kết quả, gọi là INNER JOINS, chúng ta đã trình bày trong chương 4). 27/46