Ngôn ngữ truy vấn cơ sở dữ liệu SQL

Ngôn ngữ SQL

Như trong Chương I mục 1.4, bài 1 đã trình bày, một hệ quản trị CSDL phải có ngôn ngữ giao tiếp giữa người sử dụng với CSDL (hoặc cũng còn gọi là ngôn ngữ truy nhập CSDL). Ngôn ngữ giao tiếp CSDL gồm các phạm trù:

Ngôn ngữ mô tả dữ liệu (Data Definition Language - DDL) để cho phép khai báo cấu trúc các bảng của CSDL, khai báo các mối liên hệ của dữ liệu (Data RelationShip) và các quy tắc (Rules, Constraint) quản lý áp đặt lên các dữ liệu đó.

Ngôn ngữ thao tác dữ liệu (Data Manipulation Language - DML) cho phép người sử dụng có thể thên (Insert), xóa (Delete), sửa (Update) dữ liệu trong CSDL.

Ngôn ngữ truy vấn dữ liệu, hay ngôn ngữ hỏi đáp có cấu trúc (Structured Query Language - SQL) cho phép những người khai thác CSDL (chuyên nghiệp hoặc không chuyên) sử dụng để truy vấn các thông tin cần thiết trong CSDL.

Ngôn ngữ quản lý dữ liệu (Data Control Language - DCL) cho phép những người quản trị hệ thống thay đổi cấu trúc của các bảng dữ liệu, khai báo bảo mật thông tin và cấp quyền hạn khai thác CSDL cho người sử dụng.

Những năm 1975-1976, IBM lần đầu tiên đưa ra hệ quản trị CSDL kiểu quan hệ mang tên SYSTEM-R với ngôn ngữ giao tiếp CSDL là SEQUEL (Structured English QUEry Language), đó một ngôn ngữ con để thao tác với CSDL.

Năm 1976 ngôn ngữ SEQUEL được cải tiến thành SEQUEL2. Khoảng năm 1978-1979 SEQUEL2 được cải tiến và đổi tên thành Ngôn Ngữ Truy Vấn Có Cấu Trúc (Structured Query Language - SQL) và cuối năm 1979 hệ quản trị CSDL được cải tiến thành SYSTEM-R*.

Năm 1986 Viện Tiêu Chuẩn Quốc Gia Mỹ (American National Standards Institute - ANSI) đã công nhận và chuẩn hóa ngôn ngữ SQL, và sau đó Tổ chức Tiêu chuẩn Thế giới (International Standards Organization - ISO) cũng đã công nhận ngôn ngữ này. Đó là chuẩn SQL-86.

Tới nay SQL đã qua 3 lần chuẩn hóa lại (1989, 1992, 1996) để mở rộng các phép toán và tăng cường khả năng bảo mật và tính toàn vẹn dữ liệu. Tài liệu này trình bày Ngôn ngữ truy vấn CSDL dựa trên chuẩn SQL-92 và có tham khảo với SQL, SQL*PLUS, PL/SQL của Oracle Server Release 7.3 (1996) và MicroSoft SQL Server 7.1 với các phạm trù nêu trên.

Để việc trình bày cú pháp các câu lệnh SQL được gọn gàng và dễ hiểu, tài liệu này có đưa ra một số quy ước ký pháp (Typographic Conventions) như sau:

Các từ khóa (KeyWords), các hàm (Functions), tên bảng (quan hệ - Table Names) của các câu lệnh được viết bằng chữ in hoa (UpperCase).

Các tên thuộc tính (Column Names) của các bảng được viết đậm. Những tên thuộc tính có dấu tiếng Việt hay có khoảng trắng được viết trong dấu ngoặc vuông ( [ ] ) theo ký pháp của SQL-Server.

Ví dụ: SELECT Deptno, Deptname FROM DEPARTMENT;

Các biến cú pháp (Syntax Variables), tức là các thành phần ngôn ngữ mà người sử dụng phải điền cụ thể vào khi viết lệnh, sẽ được viết bằng chữ thường (LowerCase), trong cặp dấu ( < > ) và nghiêng.

Ví dụ:CREATE TABLE <tên bảng> (<tên cột> <kiểu>, <tên cột> <kiểu>, ...);

Các thành phần tùy chọn (Optional), tức là có thể có hoặc không được viết trong cặp dấu ngoặc vuông đậm nét ([ ]).

                    Ví dụ: UPDATE <tên quan hệ>

SET <tên cột> = <biểu thức>, <tên cột> = <biểu thức>, ...

                        [ WHERE <điều kiện> ];

Việc lựa chọn một trong các khả năng được thể hiện bởi dấu xổ đứng đậm (½ ).

Thành phần bắt buộc phải chọn trong danh sách được viết trong cặp dấu móc đậm nét ( { } ).

Giá trị mặc định (Default Value) được viết với dấu gạch chân (Underline).

Ví dụ: SELECT { * ½ <biểu thức 1>, <biểu thức 2>, ... }

FROM <các bảng>

[ORDER BY <tên cột>½ <biểu thức>[ASC ½ DESC ], ...]

        Lệnh SQL có thể được viết trên nhiều dòng và kết thúc lệnh bởi dấu chấm phảy ( ; ), tuy nhiên từ khóa, tên hàm, tên thuộc tính, tên bảng, tên đối tượng (Objects) thì không được phép viết tách xuống hàng. Trong vận dụng thực tế, từ khóa, tên thuộc tính, tên bảng, tên đối tượng được viết in hoa hoặc chữ thường là như nhau.

        Cho đến bây giờ chúng ta đã có các CSDL với đầy đủ dữ liệu về quản lý học viên - được trình bày trong Chương III, bài 4 (gồm các quan hệ: KHOA, GIẢNG-VIÊN, LỚP-HỌC, MÔN-HỌC, HỌC-VIÊN, KQUẢ-THI), quản lý nhân sự của một công ty EMPLOYMENT – được trình bày trong Chương V, mục 5.3, bài 7 (gồm các quan hệ: DEPARTMENT, EMPLOYEE, JOBS, EMPLHIST) và CSDL quản lý cán bộ - công chức CCVC – được trình bày trong Chương V, mục 5.4, bài 8 (gồm các bảng: ĐƠN-VỊ, LOẠI-ĐVỊ, NGẠCH-CBVC, NGẠCH-BẬC-LƯƠNG và CBVC). Các CSDL này sẽ được sử dụng làm các mẫu cho việc trình bày các câu lệnh SQL trong toàn bộ chương này.

Các lệnh hỏi - tìm kiếm dữ liệu: (Data Retrieval SQL)

Câu lệnh SELECT - SQL tìm kiếm dữ liệu là một trong số các câu lệnh SQL cài đặt đầy đủ các phép toán quan hệ dựa trên các từ khóa cơ bản SELECT, FROM, WHERE, GROUP BY, ORDER BY, HAVING. Đây là câu lệnh được sử dụng phổ biến nhất với mục đích tìm kiếm thông tin trong CSDL quan hệ. Cú pháp tổng quát của câu lệnh như sau:

SELECT [DISTINCT]<biểu thức 1>, <biếu thức 2>, ...

FROM <tên bảng 1>, <tên bảng 2>, ...

[WHERE <điều kiện chọn> ]

[GROUP BY <tên cột 1>, <tên cột 2>, ...]

[ORDER BY <tên cột 1> | <biểu thức số 1>[ASC | | DESC ], ...]

[HAVING <điều kiện in kết quả>];

Chúng ta sẽ lần lượt làm rõ từng phần của cú pháp ngôn ngữ. Cơ sở dữ liệu được sử dụng để minh họa các ví dụ trong chương này là hệ quản lý nhân sự của một công ty EMPLOYMENT với các bảng – quan hệ: DEPARTMENT, EMPLOYEE, JOBS, EMPLHIST đã nói trên.

Tìm thông tin từ các cột của bảng.

 

SELECT [DISTINCT]{ * | <biểu thức 1>[AS <Tên mới 1>],

<biếu thức 2>[AS <Tên mới 2>], ... }

FROM <tên bảng>;

Câu hỏi 6.1.1: Cho danh sách các phòng ban (bao gồm tất cả các thông tin về Mã số (

Câu hỏi 6.1.1: Cho danh sách các phòng ban (bao gồm tất cả các thông tin về Mã số (DeptNo), Tên (DeptName), Địa điểm (Loc), Mã số người lãnh đạo (Mgr), Kinh phí hoạt động (Exp_Budg) và Doanh thu (Rev_Budg) của các phòng ban) trong Công ty:

SELECT Deptno, Deptname, Loc, Mgr, Exp_budg, Rev_budg

FROM DEPARTMENT;

Khi cần lấy thông tin về tất cả các cột của bảng chúng ta có thể sử dụng dấu sao ( * ) thay cho việc liệt kê các tên cột của bảng. Câu lệnh trên tương đương với câu lệnh:

SELECT * FROM DEPARTMENT;

Kết quả của câu lệnh là một bảng (nằm trong bộ nhớ trong):

DepTno DeptName Loc Mgr Exp_Budg Rev_Budg
10 Accounting Dallas 200 10.000  
30 Research San Fransisco 105 125.000  
40 Sales Boston 109 280.000 800.000
50 Manufacturing Houston 210 130.000  
60 Shipping Houston 215 90.000  

Câu hỏi 6.1.2: Cho Mã số, Tên, Địa điểm, Kinh phí hoạt động của từng phòng ban trong Công ty:

SELECT DeptNo, DeptName, Loc, Exp_Budg

FROM DEPARTMENT;

Câu lệnh này là cài đặt của phép chiếu trên 4 thuộc tính DeptNo, DeptName, LocExp_Budg của bảng DEPARTMENT. Kết quả của câu lệnh là một bảng (nằm trong bộ nhớ trong):

DepTno DeptName Loc Exp_Budg
10 Accounting Dallas 10.000
30 Research San Fransisco 125.000
40 Sales Boston 280.000
50 Manufacturing Houston 130.000
60 Shipping Houston 90.000

Chúng ta giả thiết rằng cần đặt tên khác (gọi là bí danh - Alias) cho các cột của bảng kết quả bằng tiếng Việt thay vì dùng tên của thuộc tính của bảng dữ liệu nguồn. Việc này được thực hiện bằng cách thêm từ khóa AS theo sau là một tên mới. Nếu tên có chứa các ký tự đặc biệt và/hoặc khoảng trắng thì viết tên đó trong cặp dấu ngoặc vuông ( [ ] ). Ví dụ trên được sửa thành:

SELECT DeptNo AS [Mã số], DeptName AS [Tên phòng], Loc AS [Địa diểm], Exp_Budg as [Kinh phí]

FROM DEPARTMENT;

Kết quả của câu lệnh là như sau:

Mã số Tên phòng Địa điểm Kinh phí
10 Accounting Dallas 10.000
30 Research San Fransisco 125.000
40 Sales Boston 280.000
50 Manufacturing Houston 130.000
60 Shipping Houston 90.000

Câu lệnh SELECT không chỉ thực hiện việc trích thông tin từ các cột đơn lẻ của bảng mà có thể thực hiện tính toán theo công thức hay biểu thức bất kỳ dựa trên giá trị của các cột trên từng bản ghi của bảng. Trong đó:

Biểu thức (expression) là một dãy các toán hạng (Operand) nối với nhau bởi các phép toán (Operator). Ở đây:

Toán hạng có thể là:

-Trực hằng (Literals): bao gồm hằng số (Number - Ví dụ. 1234.56 1234.56), hằng văn bản (Text) trong cặp dấu nháy đơn (Ví dụ. ‘Nguyễn Hồng Anh’ ) , hằng ngày tháng (Date/Time) đặt trong cặp dấu hàng rào ( # - Ví dụ.#19/05/1890# ), và hằng lôgic (True hay False) hoặc tên gọi của trực hằng.

-Tên thuộc tính (có thể kèm theo tên bảng và dấu chấm đứng trước). Ví dụ. DEPARTMENT.DeptNo.

- Tên hàm (function). Ví dụ. SUM (...), COUNT(...), SIN (...), COS(...)

- Tên biến (Variable).

Các phép toán có thể là:

- Các phép toán số học: ^ (lũy thừa); * (nhân), / (chia), % (chia nguyên), Mod (phần dư); + (cộng), - (trừ). Thứ tự ưu tiên cao nhất theo 3 cụm từ trái qua phải. Các phép toán số học thường cho kết quả là một số.

- Các phép toán so sánh: <, <=, >, >=, =, <>. Kết quả phép so sánh là giá trị lôgíc (True hoặc False).

- Các phép toán phạm vi: IN (<danh sách giá trị>), BETWEEN <Min> AND <Max>, LIKE <Mẫu v.bản>.

- Các phép toán lôgic: NOT (phủ định), AND (nối liền - conjunction), OR (nối rời - disjunction). Kết quả các phép toán lôgíc là một giá trị lôgíc.

Câu hỏi 6.1.3: Cho biết Mã số, Tên và lương cả năm của các nhân viên trong công ty:

SELECT EmpNo AS [Mã số], Name AS [Tên], Salary * 12 AS [Lương năm]

FROM EMPLOYEE;

    Kết quả là bảng:

Mã số Tên Lương năm
100 Wilson 20.400
101 Smith 30.000
103 Reed 42.000
105 Watson 54.000
109 Allen 45.600
110 Turner 21.600
200 Chen 34.800
210 Ramirez 43.200
213 McDonnel 19.500
214 Simpson 9.900
215 Di Salvo 32.400
220 Schwartz 50.400

Khi thực hiện phép chiếu tên một quan hệ, các bộ giá trị giống nhau có thể được chọn. Từ khóa DISTINCT được sử dụng nếu muốn chỉ giữ lại 1 bộ trong các bộ giá trị giống nhau tìm được.

Câu hỏi 6.1.4: Cho biết các nhân viên của công ty đang đảm nhận các công việc gì? Đây chính là phép chiếu trên thuộc tính Job của quan hệ EMPLOYEE.

SELECT DISTINCT Job FROM EMPLOYEE;

    Kết quả là bảng với 6 dòng và 1 cột như sau:

Job
Clrk
Anlt
Mngr
Drvr
Spvr
Slsm

Chọn các dòng của bảng - Mệnh đề WHERE

 

    Trong nhiều trường hợp chúng ta chỉ cần chọn ra những bộ giá trị của bảng thỏa mãn điều kiện nào đó. Mệnh đề WHERE (WHERE Clause) với cú pháp ) với cú pháp WHERE <điều kiện> cho phép thực hiện điều đó. Ở đây <điều kiện> là một biểu thức mà kết quả là một giá trị lôgic hoặc đúng (True) hoặc sai (False). Đây là sự cài đặt của phép chọn (Selection) trong đại số quan hệ.

Câu hỏi 6.1.5: Cho danh sách nhân viên của phòng số 40?.

SELECT * FROM EMPLOYEE WHERE Deptno = 40;

    Kết quả là bảng có 3 dòng (trên tổng số 12 dòng của bảng nguồn):

EmpNo Name Job Salary Comm DeptNo Sex
101 Smith Slsm 2.500 1.300 40 F
109 Allen Mngr 3.800 8.000 40 F
220 Schwartz Slsm 4.200 5.300 40 F

Câu hỏi 6.1.6: Cho danh sách nhân viên của phòng số 10, 30 và 50.

SELECT * FROM EMPLOYEE

WHERE (DeptNo = 10) OR (DeptNo = 30) OR (DeptNo = 50);

    Hoặc viết cách khác:

SELECT * FROM EMPLOYEE WHERE DeptNo IN (10, 30, 50);

    Kết quả là bảng:

EmpNo Name Job Salary Comm DeptNo Sex
100 Wilson Clrk 1.700   10 M
103 Reed Anlt 3.500   30 M
105 Watson Mngr 4.500 0 30 M
110 Turner Clrk 1.800   50 M
200 Chen Mngr 2.900   10 F
210 Ramirez Mngr 3.600   50 M

Câu hỏi 6.1.7: Cho danh sách các nhân viên có lương tháng 1ừ 3500 đến 4500 USD:

SELECT * FROM EMPLOYEE

WHERE (Salary >= 3500) AND (Salary >= 4500);

    Hoặc viết cách khác:

SELECT * FROM EMPLOYEE

WHERE Salary BETWEEN 3500 AND 4500;

EmpNo Name Job Salary Comm DeptNo Sex
103 Reed Anlt 3.500   30 M
105 Watson Mngr 4.500 0 30 M
109 Allen Mngr 3.800 8.000 40 F
210 Ramirez Mngr 3.600   50 M
220 Schwartz Slsm 4.200 5.300 40 F

Mẫu so sánh trong phép toán LIKE là một giá trị kiểu Text, đó là một dãy ký tự bất kỳ trong đó có 2 ký tự có ý nghĩa đặc biệt sau đây:

_ : Đại diện cho một ký tự bất kỳ tại vị trí dấu ?

% : Đại diện cho một nhóm ký tự bất kỳ tại vị trí đó.

Ví dụ: Với tiếng Việt 1 byte (VNI, VietWare, ABC, ...) mẫu ‘Nguy_n’ đại diện cho một dãy ký tự có 6 ký tự, trong đó có 4 ký tự đầu là ‘Nguy ’, ký tự thứ 5 là gì cũng được và ký tự thứ 6 là chữ ‘n’.

Mẫu %tổ chức% đại diện cho bất cứ giá trị văn bản nào có chứa hai từ "tổ chức".

Câu hỏi 6.1.8: Cho danh sách nhân viên có tên bắt đầu bằng chữ W:

SELECT * FROM EMPLOYEE WHERE Name LIKE ‘W%’;

EmpNo Name Job Salary Comm DeptNo Sex
100 Wilson Clrk 1.700   10 M
105 Watson Mngr 4.500 0 30 M

F Lưu ý: Trong MS Access, hằng văn bản được đặt trong cặp dấu nháy kép – ví dụ "

F Lưu ý: Trong MS Access, hằng văn bản được đặt trong cặp dấu nháy kép – ví dụ "Nguyễn Hồng An" - và ký tự đại diện trong mẫu so sánh với phép LIKE là:

? : Đại diện cho một ký tự bất kỳ tại vị trí dấu ?

* : Đại diện cho một nhóm ký tự bất kỳ tại vị trí đó.

 

Thứ tự hiển thị các bản ghi - Mệnh đề ORDER BY

 

        Trong ví dụ 6.1.6 và 6.1.7 chúng ta thấy các nhân viên không được sắp xếp theo phòng ban hay không theo thư tự tăng hay giảm dần của mức lương tháng. Để thực hiện được các điều trên, SQL hỗ trợ bởi mệnh đề ORDER BY để sắp xếp kết quả tìm được. Cú pháp mệnh đề này là:

ORDER BY <tên cột>|<biểu thức>[ASC| DESC], <tên cột> , <tên cột>|<biểu thức>[ASC| DESC], ...

        Biểu thức phải có giá trị số; nó thể hiện số thứ tự của cột trong bảng kết quả được chỉ định phải sắp xếp thứ tự thay vì phải chỉ rõ tên cột, hơn nữa nếu cột kết quả là cột tính toán thì nó chưa có tên nên các sử dụng biểu thức là một biện pháp thay thế hữu dụng. Có thể sắp xếp theo thứ tự tăng dần (với từ khóa ASC - Viết tắt của ASCending - mặc định là ASC) hoặc giảm dần (DESCending) theo giá trị cột. Trước hết các bản ghi được xếp theo thứ tự của cột thứ nhất; các bản ghi có cùng giá trị ở cột 1 sẽ được sắp xếp theo thứ tự cột thứ 2, Các bản ghi có cùng giá trị ở cả 2 cột 1 và 2 sẽ được xếp theo cột thứ 3 và v.v...

Câu hỏi 6.1.9: Cho danh sách các nhân viên của phòng 10, 30 và 50. Kết quả in ra theo thứ tự tăng dần của mã phòng và giảm dần theo mức lương.

, ...

        Biểu thức phải có giá trị số; nó thể hiện số thứ tự của cột trong bảng kết quả được chỉ định phải sắp xếp thứ tự thay vì phải chỉ rõ tên cột, hơn nữa nếu cột kết quả là cột tính toán thì nó chưa có tên nên các sử dụng biểu thức là một biện pháp thay thế hữu dụng. Có thể sắp xếp theo thứ tự tăng dần (với từ khóa ASC - Viết tắt của ASCending - mặc định là ASC) hoặc giảm dần (DESCending) theo giá trị cột. Trước hết các bản ghi được xếp theo thứ tự của cột thứ nhất; các bản ghi có cùng giá trị ở cột 1 sẽ được sắp xếp theo thứ tự cột thứ 2, Các bản ghi có cùng giá trị ở cả 2 cột 1 và 2 sẽ được xếp theo cột thứ 3 và v.v...

Câu hỏi 6.1.9: Cho danh sách các nhân viên của phòng 10, 30 và 50. Kết quả in ra theo thứ tự tăng dần của mã phòng và giảm dần theo mức lương.

SELECT * FROM EMPLOYEE WHERE Deptno IN (10, 30, 50)

ORDER BY Deptno, Salary DESC;

    Hoặc cách viết khác:

SELECT * FROM EMPLOYEE WHERE DeptNo IN (10, 30, 50)

ORDER BY 6 ASC, 4 DESC;

    Kết quả là bảng:

EmpNo Name Job Salary Comm DeptNo Sex
200 Chen Mngr 2.900   10 F
100 Wilson Clrk 1.700   10 M
105 Watson Mngr 4.500 0 30 M
103 Reed Anlt 3.500   30 M
210 Ramirez Mngr 3.600   50 M
110 Turner Clrk 1.800   50 M

Điều kiện hiển thị các bản ghi - Mệnh đề HAVING

        Mệnh đề WHERE cho phép chọn các bản ghi của bảng thỏa mãn điều kiện tìm kiếm. Trong một số trường hợp sau khi tìm được các bản ghi thỏa điều kiện tìm, chúng ta chỉ muốn hiển thị chỉ những bản ghi thỏa một điều kiện khác nữa. SQL hỗ trợ yêu cầu này bởi mệnh đề HAVING <điều kiện>. Thông thường mệnh đề này được áp dụng trong những câu lệnh tìm các bộ giá trị thông qua các quá trình tính toán trên nhóm.

        Câu hỏi 6.1.10 đưa ra sau đây để làm ví dụ không được "đắt giá" cho lắm nhưng cũng đủ để minh họa điều vừa nêu. "Hãy cho danh sách các nhân viên phòng 10, 30 và 50. Chỉ in những người là lãnh đạo phòng ban".

SELECT * FROM EMPLOYEE WHERE Deptno IN (10, 30, 50)

ORDER BY 6 ASC, 4 DESC

HAVING Job = "Mngr";

    Kết quả là bảng:

EmpNo Name Job Salary Comm DeptNo Sex
200 Chen Mngr 2.900   10 F
105 Watson Mngr 4.500 0 30 M
210 Ramirez Mngr 3.600   50 M

Câu hỏi 6.1.11: Cho Mã phòng mà người có mức lương cao nhất của phòng lớn hơn 4000 $US.

    Rõ ràng ở đây phải thực hiện 3 công việc:

  Phân tổ các nhân viên theo các phòng ban.

  Xác định mức lương cao nhất của từng phòng ban.

  Chọn phòng nào có mức lương cao nhất trên 4000 $US. Việc này chỉ có thể tiến hành được sau khi đã tìm ra tất cả các mức lương cao nhất của từng phòng ban. Câu lệnh sau đây là một gợi mở của mục 6.2 sắp được trình bày dưới đây.

SELECT Deptno, MAX(Salary)FROM EMPLOYEE

GROUP BY DeptNo

HAVING MAX(Salary) > 4000;

Deptno Max (Salary)
30 4.500
40 4.200

Truy vấn thông tin từ nhiều bảng dữ liệu.

 

        Việc thực hiện các câu truy vấn trên nhiều bảng, về bản chất là giống như trên một bảng, tức là cần chỉ ra thông tin gì cần tìm và lấy từ các nguồn dữ liệu nào. Các bảng dữ liệu nguồn này cần chỉ ra trong mệnh đề FROM trong câu lệnh SELECT.

        Nếu các bảng dữ liệu nguồn có các tên thuộc tính giống nhau thì tên thuộc tính này phải được viết tường minh trong biểu thức tìm kiếm với tên bảng đi kèm phía trước. Nói chung trong một CSDL quan hệ, các bảng thường có các mối liên hệ với nhau. Các bảng được liên hệ với nhau thông qua phép kết nối và thường là kết nối bằng (Equi-Join). Mối liên hệ phải được thể hiện trong phép kết nối của mệnh đề FROM hoặc thông qua điều kiện của mệnh đề WHERE của câu lệnh SELECT. Nếu không thể hiện mối liên hệ này, kết quả sẽ là bảng tích Đề-các của 2 bảng.

Câu hỏi 6.1.12: Cho Mã phòng, Tên phòng và tên người lãnh đạo phòng tương ứng.

Trong câu hỏi này, Tên phòng được lấy từ bảng DEPARTMENT, Mã phòng có thể lấy từ DEPARTMENT hoặc từ bảng EMPLOYEE, còn tên nhân viên làm lãnh đạo phòng được lấy từ bảng EMPLOYEE. Hai bảng này được kết nối với nhau thông qua giá trị của thuộc tính Mgr của DEPARTMENT và EmpNo của EMPLOYEE.

Một điểm nữa cần lưu ý là thuộc tính DeptNo có trong cả 2 bảng DEPARTMENT và EMPLOYEE, do đó khi viết lệnh phải chỉ rõ DeptNo của bảng nào (mặc dù chúng là như nhau)

SELECT DEPARTMENT.DeptNo, DeptName FROM

DEPARTMENT, EMPLOYEE

WHERE DEPARTMENT.Mgr = EMPLOYEE.EmpNo;

;

    Hoặc có thể viết cách khác nhờ sử dụng phép kết nối bằng INNER JOIN (đã trình bày trong chương V, mục 5.1, điểm 5.1.1) như sau:

SELECT DEPARTMENT.DeptNo, DeptName FROM

DEPARTMENT INNER JOIN EMPLOYEE

ON (DEPARTMENT.Mgr = EMPLOYEE.EmpNo);

);

        Để giảm nhẹ công việc phải viết tên bảng nhiều lần trong lệnh, SQL hỗ trợ tên bí danh cho bảng bằng cách đặt bí danh ngay sau tên bảng nguồn. Bí danh này có thể được dùng trước khi nó được đặt. Dạng đầu tiên của ví dụ này được viết lại tương đương như sau:

SELECT D.DeptNo, D.DeptName, E.Name

FROM DEPARTMENT D, EMPLOYEE E

WHERE D.Mgr = E.Empno;

;

    Kết quả của cả 3 cách thể hiện câu hỏi trên là:

D.Deptno D.Deptname E.Name
10 Accounting Chen
30 Research Watson
40 Sales Allen
50 Manufacturing Ramirez
60 Shipping Di Salvo

Các câu truy vấn lồng nhau (Query with SubQuery).

Trong nhiều trường hợp chúng ta cần phải tìm kiếm thông tin qua nhiều bước: kết quả của bước trước được sử dụng trong biểu thức của câu truy vấn tiếp theo, rồi kết quả của câu truy vấn này lại được dùng trong biểu thức của câu truy vấn tiếp theo nữa v.v... Bằng ngôn ngữ thủ tục, qua mỗi bước chúng ta phải ghi nhớ lại các kết quả trung gian này. Nếu như vậy thì công việc truy vấn dữ liệu sẽ rất vất vả cho những người thao tác trực tiếp với CSDL. SQL - SELECT cho phép lấy ngay kết quả của một câu truy vấn để xây dựng biều thức điều kiện cho một câu hỏi khác. Câu hỏi trung gian đó được gọi là câu hỏi con (SubQuery). Câu hỏi con phải được bao trong cặp dấu ngoặc tròn trong biểu thức của câu hỏi chính. Sự cho phép câu hỏi con là một trong những ưu điểm nổi bật của ngôn ngữ quản trị CSDL quan hệ.

Câu hỏi 6.1.13: Cho danh sách những người làm việc cùng phòng với ông Watson:

    Phân tích câu hỏi này ta có 2 bước:

Bước 1: Tìm số hiệu phòng (mà) ông Watson là nhân viên (giả sử phòng tìm được có mã là pp).

Bước 2: Tìm những người có số hiệu phòng làm việc bằng pp

    Câu hỏi ở bước 1 là câu hỏi con cho câu hỏi ở bước 2. Câu lệnh SQL như sau:

SELECT * FROM EMPLOYEE

WHERE DeptNo = ANY ( SELECT DeptNo

FROM EMPLOYEE WHERE Name = Watson );

    Kết quả là bảng:

EmpNo Name Job Salary Comm DeptNo Sex
103 Reed Anlt 3.500   30 M
105 Watson Mngr 4.500 0 30 M

Câu hỏi 6.1.14: Cho biết Mã số, Tên và Mức lương của người lãnh đạo của ông Smith.

    Câu hỏi này phải được thực hiện qua 3 bước:

Bước 1: Tìm Mã số phòng (mà) ông Smith làm nhân viên (phòng pp).

Bước 2: Tìm Mã số người lãnh đạo phòng pp (nhân viên xx).

Bước 3: Tìm Mà số, Tên, Mức lương của nhân viên có mã số là xx.

    Như vậy chúng ta phải viết 2 câu hỏi con lồng nhau trong một câu hỏi chính:

SELECT EmpNo, Name, Salary FROM EMPLOYEE

WHERE EmpNo = ANY

( SELECT Mgr FROM DEPARTMENT

WHERE DeptNo = SOME

( SELECT DeptNo FROM EMPLOYEE

WHERE Name = Smith

)

);

    Câu trả lời là:

Empno Name Salary
109 Allen 3.800

    Kết quả của câu hỏi con được sử dụng trong phép so sánh với một giá trị khác trong biểu thức điều kiện của câu hỏi bao nó. Các phép so sánh có dạng:

<phép so sánh> [<lượng từ>] (SELECT - câu hỏi con)

    Ở đây :

       <Phép so sánh> có thể là các phép so sánh số học (>, >=, <, <=, <>, =) hoặc phép toán tập hợp IN, LIKE hoặc NOT LIKE.

       <Lượng từ> có thể là ALL, ANY (hoặc SOME). Phép so sánh = ANY có thể được thay tương đương bằng phép toán IN; phép so sánh <> ALL có thể thay tương đương bằng phép toán NOT IN.

Câu hỏi 6.1.15: Cho danh sách nhân viên có mức lương lớn hơn hay bằng mức lương cao nhất của phòng ông McDonnel:

Bước 1: Tìm số hiệu phòng (mà) ông McDonnel là nhân viên (Mã phòng pp).

Bước 2: Tạo nhóm nhân viên có mã phòng làm việc là pp rồi tính lương trung bình của những người này (Lương cao nhất zz).

Bước 3: Tìm những người có lương lớn hơn hay bằng zz.

SELECT * FROM EMPLOYEE

WHERE Salary >= ALL

( SELECT MAX(Salary) FROM EMPLOYEE

WHERE DeptNo = ANY

( SELECT DeptNo FROM EMPLOYEE

WHERE Name = McDonnel

)

);

    Lương cao nhất phòng ông McDonnel là 2700 $US. Bảng kết quả là:

EmpNo Name Job Salary Comm DeptNo Sex
103 Reed Anlt 3.500   30 M
105 Watson Mngr 4.500 0 30 M
109 Allen Mngr 3.800 8.000 40 F
200 Chen Mngr 2.900   10 F
210 Ramirez Mngr 3.600   50 M
215 Di Salvo Spvr 2.700   60 M
220 Schwartz Slsm 4.200 5.300 40 F

Nhóm thực hiện tính toán.

Các hàm tính toán trên nhóm các bản ghi (Aggregate Functions):

    Qua ví dụ trên, chúng ta đã nhận thấy sự cần thiết của những tính toán trong câu lệnh SELECT. SQL cung cấp một số hàm xây dựng sẵn (Built-in) làm việc trên nhóm theo kỹ thuật tính toán nhanh tiên tiến RushMore. Đó là các hàm: COUNT (* |<tên cột>) - đếm số bản ghi có giá trị xác định tại cột được cho bởi <tên cột>, SUM (<biểu thức>) - tính tổng giá trị các biểu thức, MIN (<biểu thức>) - tìm giá trị nhỏ nhất, MAX (<biểu thức>) - tìm giá trị lớn nhất và AVG (<biểu thức>) - tính giá trị trung bình của biểu thức dựa trên các bản ghi của các nhóm. Các hàm này thường phải được đi kèm với mệnh đề GROUP BY để thực hiện phân nhóm các bản ghi theo giá trị các cột nào đó trước khi tính toán. Nếu không có mệnh đề GROUP BY thì câu lệnh sẽ coi toàn bộ các bản ghi của bảng là một nhóm.

Câu hỏi 6.2.1: Cho biết khoản tiền huê hồng (Commission) cao nhất và trung bình của các nhân viên (có khoản này).

SELECT MAX ( Comm ), AVG ( Comm ) FROM EMPLOYEE;

    Bảng kết quả:

MAX(Comm) AVG(Comm)
8000 3650

Chúng ta thấy rằng các hàm trên chỉ tính toán trên các giá trị xác định. Do đó, mặc dù không có sự phân nhóm nhưng hàm MAX (.) SUM (.), COUNT (.) và AVG (.) chỉ tính trên các giá trị xác định. Chỉ có 4 người có tiền huê hồng, nên giá trị trung bình là (1300 + 0 + 8000 + 5300) / 4 = 3650.

Câu hỏi 6.2.2: Cho biết Mã số, Tên, Tổng số nhân viên, mức lương cao nhất, thấp nhất, và trung bình của các phòng ban:

SELECT A.DeptNo AS [Mã số], A.DeptName AS [Tên phòng],

COUNT (*) AS [Tg.số n/v], MAX (Salary) AS [Lương Max],

MIN (Salary) AS [Lương Min],

AVG (Salary) AS [Lương TBình]

FROM DEPARTMENT A, EMPLOYEE B

WHERE A.Deptno = B.Deptno

GROUP BY A.Deptno, A.Deptname;

    Bảng kết quả:

Mã số Tên phòng TgSố n/v Lương Max Lương Min Lương TBình
10 Accounting 2 2.900 1.700 2.300
30 Research 2 4.500 3.500 4.000
40 Sales 3 4.200 2.500 3.500
50 Manufacturing 2 3.600 1.800 2.700
60 Shipping 3 2.700 825 1.716

Trên đây là danh sách các phòng ban với các mức lương cao nhất, thấp nhất và trung bình của các nhân viên trong từng phòng. Có thể biết được những ai trong phòng có mức lương cao nhất hay thấp nhất trong các phòng ban không ?

Câu hỏi 6.2.3: Cho biết các nhân viên có mức lương cao nhất (tương tự: lương thấp nhất, và lương trung bình) của các phòng:

    Ở đây cần phải tiến hành theo hai bước:

Bước 1: Xác định các mức lương cao nhất của từng phòng.

Bước 2: Tìm những nhân viên có mức lương bằng với mức lương cao nhất của phòng đó.

        Cần lưu ý rằng, kết quả của câu hỏi con được dùng làm toán hạng trong câu hỏi khác, do đó giá trị các phần tử (hay bộ giá trị) của bảng kết quả phải là vô hướng, tức là, câu lệnh SELECT con chỉ được chọn một biểu thức trong câu lệnh. Chúng ta không thể chỉ chọn một cột mức lương cao nhất trong bước 1, để rồi trong bước 2 chọn ra những người có mức lương trùng với một trong các mức lương tìm được. Bởi vì, người có mức lương cao nhất của một phòng có thể bằng với mức lương của một người bình thường trong phòng khác. Phải làm sao gán được mức lương cao nhất đi kèm với phòng cụ thể. Chúng ta thực hiện việc biến đổi nhỏ: Đổi Mã phòng và mức lương cao nhất của phòng thành chuỗi rồi ghép lại với nhau thành một chuỗi đặc trưng cho từng phòng. Trong câu hỏi chính, chúng ta cũng ghép hai chuỗi đổi được từ Mã phòng và mức lương của từng nhân viên, rồi so khớp với kết quả ở bước trên. Câu lệnh được viết trong MicroSoft SQL-Server như sau:

SELECT *

FROM EMPLOYEE

WHERE STR ( Deptno, 2 ) + STR ( Salary, 5 ) IN

( SELECT STR ( Deptno, 2 ) + STR ( MAX (Salary), 5)

FROM EMPLOYEE GROUP BY DeptNo

ORDER BY DeptNo;

    Bảng kết quả:

EmpNo Name Job Salary Comm DeptNo Sex
200 Chen Mngr 2.900   10 F
105 Watson Mngr 4.500 0 30 M
220 Schwartz Slsm 4.200 5.300 40 F
210 Ramirez Mngr 3.600   50 M
215 Di Salvo Spvr 2.700   60 M

F Ghi chú:

Hàm STR (<ExpN> [, m[, n]]) thực hiện việc đổi một giá trị của biểu thức số <ExpN> ra dãy ký tự chữ số gồm m ký tự, trong đó có n số lẻ sau dấu chấm thập phân. Nếu trong hàm không có n thì n có giá trị mặc nhiên là 0 – không có số lẻ; nếu không có m thì giá trị mặc nhiên của m là 10.

Trong MS Access có thể sử dụng phép toán dấu "" (&) để ghép nối hai giá trị có kiểu bất kỳ thành một giá trị có kiểu biến thể (Variant).

        Ngoài các hàm COUNT, SUM, MIN, MAX, AVG ngôn ngữ quản trị CSDL còn cài đặt một số hàm thống kê trong đó có hàm tính phương sai (VAR = Variance) và tính độ lệch chuẩn STDEV (Standard Deviation) của một dãy biểu thức dựa trên các cột số của các bản ghi của (các) bảng. Đó là các hàm tính toán trên nhóm các bản ghi, đòi hỏi có mệnh đề GROUP BY trong các câu lệnh truy vấn SQL.

Các hàm tính toán trên bản ghi:

        Hầu hết các hệ quản trị CSDL đều cài đặt thư viện các hàm xây dựng sẵn trong ngôn ngữ truy vấn dữ liệu nhằm hỗ trợ việc xây dựng các biểu thức tính toán cho từng bộ giá trị (hay bản ghi) của các quan hệ. Vì mỗi hãng cung cấp hệ quản trị CSDL đặt tên các hàm có thể khác nhau hoặc bổ sung một hàm riêng biệt của hãng hay loại bỏ bớt một số hàm, do đó, mục này của bài giảng chỉ nêu ra các hàm thuộc một số lĩnh vực mang tính gợi mở. Khi cài đặt CSDL trên một ngôn ngữ quản trị CSDL cụ thể, các học viên còn phải học hỏi nhiều thông qua các các bài giảng trực tiếp (Tutorials) và tài liệu hướng dẫn của hãng cung cấp ngôn ngữ quản trị CSDL.

Các hàm toán học:

ABS(x): Trị tuyệt đối của x

SQRT(x): Căn bậc hai của x (Access và SQL-Server là: SQR(x))

LOG(x): Logarit tự nhiên của x

EXP(x): Hàm mũ cơ số e của x: ex.

SIGN(x): Lấy dấu của số x (-1: x<0, 0: x=0, +1: x>0)

OUND(x,n): Làm tròn tới n số lẻ (Access và SQL-Server: RND(x))

... và các hàm lượng giác: SIN, COS, TAN, ASIN, ACOS, ATAN ...

Các hàm xử lý chuỗi ký tự:

LEN (str): Cho chiều dài dãy ký tự str.

LEFT(str,n): Lấy n ký tự phía trái của dãy str.

): Lấy n ký tự phía trái của dãy str.

RIGHT(str,n): Lấy n ký tự phía phải của dãy str.

MID(str,p,n): Lấy n ký tự của dãy str kể từ vị trí p trong dãy.

Các hàm xử lý ngày tháng và thời gian:

DATE(): Cho ngày tháng năm hiện tại (Oracle: SYSDATE)

DAY(dd): Cho số thứ tự ngày trong tháng của biểu thức ngày dd.

MONTH(dd): Cho số thứ tự tháng trong năm của biểu thức ngày dd.

YEAR(dd): Cho năm của biểu thức ngày dd.

HOUR(tt): Cho giờ trong ngày (0 ¸ 23)

MINUTE(tt): Cho số phút của thời gian tt.

SECONDS(tt): Cho số giây của biểu thức giờ tt.

Các hàm chuyển đổi kiểu giá trị:

FORMAT(bthức, mẫu): Đổi biểu thức có kiểu bất kỳ thành chuỗi theo mẫu đã cho trong tham số thứ 2. Có thể sử dụng hàm STR để thay thế.

... và họ các hàm chuyển đổi biểu thức có kiểu bất kỳ thành một giá trị thuộc kiểu xác định: CSTR, CINT, CLNG, CSIN, CDBL, v.v...

        Cú pháp và ngữ nghĩa cụ thể của các hàm này có thể được tìm thấy trong các tài liệu hướng dẫn cụ thể của các hãng cung cấp phần mềm. Tài liệu này không có tham vọng trình bày chi tiết các hàm của ngôn ngữ hệ quản trị CSDL cụ thể.