Session 5 T-SQL Programming
Mục tiêu của chương
Kết thúc chương này, bạn có thể
Hiểu được khái niệm của quá trình chạy batch (xử lý bó) trong SQL
Học về các câu lệnh điều khiển để tạo ứng dụng
Định nghĩa và gán giá trị cho các biến
Viết các hàm cơ bản SQL Server
Sử dụng các hàm cơ bản trong truy vấn
Giới thiệu
Trong chương trước, chúng ta đã học về cách thực thi các truy vấn con và câu lệnh SELECT với
các mệnh đề khác nhau. Chúng ta cũng học về cấu trúc SELECT INTO sử dụng để chuyển dữ
liệu từ một bảng sang một bảng khác.
Trong chương này, chúng ta sẽ thảo luận về quá trình chạy batch trong SQL Server. Chúng ta
cũng sẽ học về cách tạo và sử dụng các biến cục bộ và toàn cục. Cuối chương này chúng ta cũng
đề cập đến các luồng câu lệnh điều khiển khác nhau và các kiểu hàm khác nhau như là hàm
aggregate & rowset.
5.1 SQL Batch và xử lý Batch
Batch là tập hợp bao gồm một hoặc nhiều lệnh được máy khách gửi trong một nhóm. Mỗi batch
được biên dịch thành một phiên thực hiện đơn lẻ. Nếu batch chứa nhiều câu lệnh SQL, tất cả các
câu lệnh sẽ được tối ưu từng bước cần thiết để thi hành lần lượt các câu lệnh này trong một lần xử
lý
5.1.1 Khái niệm và nguồn gốc các câu lệnh Batch
Trong môi trường đa nhiệm, nhiều người sử dụng có thể truy cập CSDL đồng thời trên mạng.
Trong môi trường đơn nhiệm, một người sử dụng có thể cần thực hiện nhiều thao tác trên một
CSDL, như là cập nhật bảng, tính toán kết quả của truy vấn SELECT.v.v. Những thao tác này có
thể tạo thành một chuỗi các câu lệnh để thực thi trên CSDL.
Ví dụ, CSDL chi tiết nhân viên employee và chi tiết về công việc của họ Work. Một người sử
dụng CSDL muốn tính toán net pay cho mỗi nhân viên dựa trên chi tiết lương cơ bản, tổng số
ngày làm việc và tổng số ngày nghỉ. Tập hợp các yêu cầu trên có thể hoàn thành trong cùng một
nhiệm vụ. Theo thứ tự net pay sẽ được tính cho mỗi nhân viên, nó được thực hiện dễ dàng hơn
nếu các yêu cầu được chứa trong một tệp và sẽ được tác động tới CSDL trong một lần thực thi.
Quá trình xử lý một chuỗi các lệnh tại một thời điểm từ một tập hợp các lệnh được gọi là xử lý bó
(batchprocessing)
Ưu điểm chính của batch processing là dễ dàng quản lý CSDL. Ví dụ, Nếu chúng ta cần thay đổi
một truy vấn đang tồn tại, mà truy vấn này được lưu giữ trên máy tính của người sử dụng, chúng
ta phải thực hiện những thay đổi này trên tất cả các máy tính của mỗi người sử dụng. Thay vào
T-SQL Programming 59
đó, Nếu chúng ta lưu giữ truy vấn trên máy chủ trung tâm (Server) như là một tệp hoặc thủ tục
lưu trữ, chúng ta chỉ phải thực hiện sự thay đổi này một lần tại phía máy chủ. Cách làm này tiết
kiệm được thời gian và có hiệu quả cao.
5.1.2 SQL Batch
Batch processing trong SQL Server 2000 được thi hành dưới dạng thủ tục chứa (stored
procedures). Một thủ tục chứa là một nhóm các câu lệnh T-SQL được biên dịch và thực hiện
trong cùng một lần. Stored procedure thực thi hoàn thành các lệnh logic thông qua các ứng dụng
khác nhau. Các câu lệnh SQL cần thiết để thực hiện các tác vụ nào đó lặp đi lặp lại được thiết kế,
phát triển và kiểm tra một lần trong stored procedure. Một khi stored procedure được tạo lập, mỗi
ứng dụng cần thực hiện các tác vụ tương tự chỉ cần thực hiện lại store procedure. Coding
business logic into a single stored procedure also offers a single point of control for ensuring
that business rules are correctly enforced. Stored procedure cũng có thể thực hiện tốt hơn.
Nhiều tác vụ được thực thi tương ứng với chuỗi các câu lệnh SQL. Cấu trúc điều kiện của câu
lệnh SQL đầu tiên sẽ trả về kết quả để căn cứ vào đó thực hiện các các câu lệnh SQL con.
Ví dụ về tạo batch
Use Master
Go
Từ khoá Go chỉ ra sự kết thúc của một batch
Xét ví dụ khác
Use Pubs
Select * from authors
Update authors set phone= '890 451-7366' where au_lname=
'White'
Go
Ở đây, cả ba câu lệnh có thể được nhóm vào cùng một tác vụ thực hiện và sau đó thực thi tác vụ
đó
Tiếp theo, chúng ta sẽ tìm hiểu cách sử dụng chú thích trong batches
5.1.3 Sử dụng chú thích trong SQL
Chú thích là một chuỗi văn bản viết trong chương trình (giống như là đánh dấu), chú thích này sẽ
bị bỏ qua khi biên dịch. Chú thích có thể sử dụng trong tài liệu code và có thể sử dụng để ẩn các
câu lệnh SQL và batches tạm thời để gỡ lỗi. Sử dụng chú thích trong khi viết code giúp cho việc
bảo trì code dễ dàng . Chú thích thường được sử dụng để ghi nhớ tên chương trình, tên tác giả, và
ngày thay đổi các đoạn code quan trọng. Chú thích cũng có thể sử dụng để diễn giải một đoạn
tính toán phức tạp và giải thích các phương thức lập trình.
Microsoft SQL Server 2000 hỗ trợ 2 kiểu chú thích:
(//): Mọi thứ viết trong dòng có 2 dấu gạch nối (//) bắt đầu được coi là dòng chú thích.
Nếu muốn chú thích trên nhiều dòng thì dấu (//) phải xuất hiện ở đầu mỗi dòng.
/*…*/(cặp dấu gạch và hoa thị ). Mọi thứ viết trong dòng bắt đầu với cặp dấu mở chú
thích (/*) và dấu đóng chú thích (*/) được coi là dòng chú thích. Đối với đoạn chú thích nhiều
60 Database Design and Implementation with SQL Server
dòng, đoạn chú thích được bắt đầu bởi kí tự mở chú thích (/*) và kết thúc bởi kí tự đóng chú
thích (*/)
Nhiều dòng /* */ chú thích không thể trải dài trong nhiều batch. Chú thích phải được chứa trong
một batch. Ví dụ, như đã đề cập trước đó, lệnh GO là tín hiệu kết thúc một batch. Khi tiện ích
biên dịch gặp kí tự GO trong 2 byte đầu tiên của dòng, chúng sẽ gửi tất cả các đoạn mã từ sau
lệnh GO tới máy chủ như là một batch. Nếu gặp lệnh GO tại vị trí đầu tiên của dòng chú thích
nằm giữa dấu /* */ , thì đoạn chú thích không phù hợp này sẽ gửi tới mỗi batch và chúng sẽ gây
ra lôi cú pháp.
Ví dụ, đoạn code dưới đây có lỗi cú pháp:
USE Northwind
GO
SELECT * FROM Employees
/* The
GO in this comment causes it to be broken in half */
SELECT * FROM Products
GO
Đoạn code này có các chú thích hợp lệ:
USE Northwind
GO
-- First line of a multiple-line comment.
-- Second line of a multiple-line comment.
SELECT * FROM Employees
GO
/* First line of a multiple-line comment.
Second line of a multiple-line comment. */
SELECT * FROM Products
GO
-- Using a comment in a Transact-SQL statement
-- during diagnosis.
SELECT EmployeeID, /* FirstName, */ LastName
FROM Employees
-- Using a comment after the code on a line.
USE Northwind
GO
UPDATE Products
SET UnitPrice = UnitPrice * .9 -- Try to build market share.
GO
Các điều quan trọng cần chú ý trong khi sử dụng chú thích là:
T-SQL Programming 61
Tất cả các kí tự hoặc ký hiệu có thể sử dụng trong chú thích. SQL Server bỏ qua tất cả các
ký tự trong chú thích, Tuy nhiên truy vấn SQL sẽ phân tích, tìm kiếm từ GO như là 2 ký tự
đầu tiên trong đoạn chú thích.
Không có quy định độ dài tối đa cho đoạn chú thích. Một đoạn chú thích có thể bao gồm
một hoặc nhiều dòng.
5.2 Các câu lệnh điều khiển Logic
Khi chúng ta thực hiện một chương trình, Theo chế độ mặc định các câu lệnh được thực hiện tuần
tự. Chúng ta có thể điều khiển luồng thực hiện của chương trình bằng cách sử dụng các câu lệnh
điều khiển.
Trong SQL, các câu lệnh DML có thể sử dụng để thực hiện một hành động trên một tập các hàng
hoặc tất cả các hàng. Tuy nhiên, một tập hợp các hành động lại được yêu cầu thực hiện trên nhiều
hàng một cách lặp đi lặp lại hoặc có điều kiện. Để thực hiện điều này, SQL Server đã cung cấp
ngôn ngữ lập trình có cấu trúc. Các cấu trúc này được gọi là các câu lệnh điều khiển bởi vì chúng
xử lý chính một cách chính xác thứ tự thực hiện các đoạn code. Nhóm luồng các câu lệnh điều
khiển này thực hiện các nhiệm vụ sử dụng các kỹ thuật như là quá trình xử lý lặp hoặc điều kiện
giống như các ngôn ngữ lập trình đã biết như Visual Basic hoặc C++.
Khái niệm của luồng xử lý tuần tự và luồng thay đổi bằng cách sử dụng các câu lệnh điều khiển
được vẽ trong hình 5.1.
Hình 5.1: Thi hành tuần tự và luồng thay đổi bằng cách sử dụng các câu lệnh điều khiển
Nói chung, các câu lệnh T-SQL được thực hiện một cách tuần tự. Giao tác SQL (Transact-SQL)
cho phép chúng ta điều khiển luồng thực hiện của các câu lệnh T-SQL và stored procedures với
sự trợ giúp của tập các ký tự điều khiển.
Ví dụ, chúng ta có thể sử dụng các lệnh BEGIN...END để tạo lập một khối logic khi chúng ta phải
xử lý nhiều hơn một câu lệnh T-SQL tại một thời điểm. Chúng ta có thể sử dụng câu lệnh IF…
ELSE khi chúng ta muốn thực hiện một câu lệnh hoặc một khối các câu lệnh dựa trên một hoặc
vài điều kiện nào đó.
62 Database Design and Implementation with SQL Server
Bảng dưới đây tóm tắt các câu lệnh điều khiển khác nhau có sẵn trong T-SQL.
Cú pháp của các cấu trúc
điều khiển
Diễn tả
BEGIN
<sql statements>
END
Các câu lệnh nằm trong khối BEGIN…END được coi như
một đơn vị xử lý đơn
RETURN Câu lệnh này có thể sử dụng để thoát khỏi thủ tục hoặc các
truy vấn.
GOTO <label>
<label>:
Chuyển luồng xử lý tới một vị trí xác định được chỉ ra bởi
nhãn.
IF <condition>
<sql statements>
ELSE
<sql statements>
Cấu trúc này có thể sử dụng để thực hịên tập hợp các câu
lệnh được lựa chọn dựa trên giá trị true-false của điều kiện.
WHILE <condition>
BEGIN
<sql statements>
<on some condition>
BREAK
<on some condition>
CONTINUE
END
Trong cấu trúc này, một tập hợp các lệnh được thưc hiện lặp
đi lặp lại trong khi giá trị của điềi kiện là true. Điều kiện
được kiểm tra trước tiên sau đó bắt đầu xử lý khối lệnh.
BREAK Câu lệnh này chuyển điều khiển ra ngoài vòng lặp trong
luồng xử lý hiện tại.
CONTINUE Câu lệnh này có thể sử dụng để bắt đầu thực hiện các câu
lệnh trong vòng lặp tiếp theo bỏ qua các câu lệnh nằm sau
lệnh này trong vòng lặp hiện tại.
CASE <expression>
WHEN <expression1> THEN
<expression1>
[WHEN <expression2> THEN
<expression2>]
[ELSE <expression>
END
Sử dụng cấu trúc này, tập hợp các lệnh khác nhau được xử
lý dựa trên giá trị của điều kiện.
Bảng 5.1: Tổng kết của luồng các câu lệnh điều khiển
Tóm tắt ngắn gọn các cấu trúc điều khiển
5.2.1 BEGIN END
Cú pháp:
BEGIN
{
statement | statement_block
}
END
T-SQL Programming 63
Chú ý: Chúng ta có thể sử dụng các từ khoá BEGIN và END để định nghĩa một khối
lệnh.
5.2.2 Câu lệnh GOTO và RETURN
Chúng ta có thể thay đổi luồng thực hiện tới một vị trí khác (nhãn). Các câu lệnh sau từ khoá
GOTO bị bỏ qua và quá trình thực hiện tiếp tục các câu lệnh từ nhãn đã chỉ ra trong lệnh
GOTO. Chúng ta có thể sử dụng lệnh GOTO bất kỳ đâu trong một khối câu lệnh, thủ tục.
Chúng ta cũng có thể sử dụng nhiều câu lệnh GOTO lồng nhau.
Cú pháp:
GOTO label
Label là nhãn xác định vị trí mới mà tại đó các câu lệnh tiếp tục được thực hiện. Định nghĩa
(label) phải tuân theo quy luật như định danh. GOTO có thể tồn tại trong câu lệnh điều kiện,
trong khôi, hoặc thủ tục, nhưng nó không thể tồn tại ở bên ngoài batch. Lệnh GOTO thay đổi
luồng thực hiện tới một nhãn, nó có thể được định nghĩa trước hoặc sau lệnh GOTO.
Chúng ta có thể sử dụng lệnh RETURN tại bất kỳ điểm nào để thoát khỏi một khối lệnh hay thủ
tục. Các câu lệnh sau RETURN ở trong khối hoặc thủ tục không được thực hiện.
Cú pháp:
RETURN [ integer_expression ]
Tham số trong lệnh RETURN chứa giá trị nguyên trả về. Stored procedures có thể trả về một giá
trị nguyên cho thủ tục hoặc chương trình gọi nó. Mặc định, tất cả các stored procedures cũng trả
về giá trị 0 (khi thành công) hoặc khác 0 (khi không thành công)
5.2.3 IF ELSE
Chúng ta có thể thực hiện một tập hợp các câu lệnh khác của SQL dựa trên điều kiện chỉ ra. Câu
lệnh SQL sau từ khoá IF và điều kiện chỉ được thực hiện nếu điều kiện đúng. Trong trường
hợp, điều kiện trong mệnh đề IF không thoả mãn (nó chứa trị sai), thì tập hợp các lệnh SQL
sau từ khoá ELSE được thực hiện (nếu có).
Cú pháp:
IF Boolean_expression
{ sql_statement | statement_block }
[ ELSE
{ sql_statement | statement_block } ]
64 Database Design and Implementation with SQL Server
Biểu thức được sử dụng với IF phải trả về TRUE hoặc FALSE. Trong trường hợp chúng ta sử
dụng câu lệnh SELECT trong biểu thức, câu lệnh nên được nằm trong dấu ngoặc đơn. Chúng ta
cũng có thể sử dụng câu lệnh IF…ELSE lồng nhau và không có giới hạn về số mức lồng nhau.
Chúng ta xét ví dụ sau. Trong ví dụ này chúng ta sẽ sử dụng câu lệnh IF…ELSE và GOTO. Ví dụ
giống như hình 5.2. Trong ví dụ này, orders lớn hơn 1 thì chương trình sẽ thực hiện các lệnh sau
nhãn X đó là hiển thị tất cả các bản ghi từ bảng Shippers.
Hình 5.2: Lệnh IF…ELSE
5.2.4 Vòng lặp WHILE
Chúng ta có thể thực hiện một lệnh SQL hoặc một khối lệnh một cách lặp đi lặp lại bằng cách dựa
trên điều kiện. Sử dụng từ khoá WHILE chúng ta có thể bảo đảm các câu lệnh được thực
hiện lặp đi lặp lại trong khi điều kiện chỉ ra có giá trị đúng. Chúng ta có thể sử dụng từ khoá
CONTINUE và BREAK trong vòng lặp WHILE để điều khiển sự thực thi của các câu lệnh.
Cú pháp:
WHILE Boolean_expression
{ statement | statement_block }
[ BREAK ]
{ statement | statement_block }
[ CONTINUE ]
Boolean_expression là bíểu thức điều kiện, nó có thể trả về giá trị ĐÚNG hoặc SAI. Trong trường
hợp biểu thức điều kiện chứa câu lệnh SELECT, nó phải được bao trong dấu ngoặc đơn.
Từ khoá BREAK dùng để thoát khỏi vòng lặp WHILE trong cùng ngược lại từ khoá
CONTINUTE dùng để điều khiển vòng lặp được thực hiện tiếp tục bỏ qua một loạt các lệnh sau từ
khoá CONTINUTE.
T-SQL Programming 65
Nếu chúng ta có các vòng lặp WHILE lồng nhau, câu lệnh BREAK ở vòng lặp phía trong sẽ
chuyển quyền thực hiện ra vòng lặp phía ngoài cùng. Đầu tiên, các câu lệnh tại vòng lặp phía
trong được kết thúc, sau đó các câu lệnh của vòng lặp phía ngoài được thực hiện.
Ví dụ 1: Sử dụng từ khoá BREAK và CONTINUE với các lệnh IF …ELSE lồng nhau và
WHILE
Trong ví dụ này, nếu giá trung bình của các cuốn sách trong bảng titles nhỏ hơn $30, vòng lặp
WHILE sẽ thực hiện cập nhật giá của các cuốn sách đó gấp 2 lần và sau đó lựa chọn giá lơn nhất.
Nếu giá lớn nhất vừa tìm được nhỏ hơn hoặc bằng $50, vòng lặp WHILE sẽ lặp lại và gấp đôi giá
lần nữa. Vòng lặp này sẽ tiếp tục gấp đôi giá của các cuốn sách tới khi giá lớn nhất lớn hơn $50,
thì thoát khỏi vòng lặp và hiển thị một thông báo.
1. USE pubs
2. GO
3. WHILE (SELECT AVG(price) FROM titles) < $30
4. BEGIN
5. UPDATE titles
SET price = price * 2
6. SELECT MAX(price) FROM titles
7. IF (SELECT MAX(price) FROM titles) > $50
BREAK
8. ELSE
CONTINUE
9. END
10. PRINT 'Too much for the market to bear'
5.2.5 Lệnh rẽ nhánh CASE
Từ khoá CASE cho phép chúng ta trả về giá trị dựa trên giá trị của biểu thức điều kiện là đúng.
Nó có thể sử dụng bất kỳ ở nhánh nào khi biểu thức điều kiện thoả mãn.
Cú pháp:
CASE expression
WHEN expression1 THEN expression1
[[WHEN expression2 THEN expression2] […]]
[ELSE expression]
END
Trong đó:
Biểu thức: là một hằng số, tên cột, một hàm, truy vấn con, hoặc bất kỳ biểu thức nào có thể so
sánh với biểu thức khác.
66 Database Design and Implementation with SQL Server