Trong bài trước mình đã giới thiệu về Stored Procedure , Trong bài này chúng ta sẽ tìm hiểu về Function và Trigger – một phần cũng không kém phần quan trong trong lập trình với cơ sở dữ liệu
1. Hàm – FunctionsCũng giống như Stored Procedure Hàm là một đối tượng trong cơ sở dữ liệu bao gồm một tập nhiều câu lệnh SQL được nhóm lại với nhau thành một nhóm. Điểm khác biệt giữa hàm và thủ tục là hàm trả về một giá trị thông qua tên hàm. Điều này cho phép ta sử dụng hàm như là một thành phần của một biểu thức chẳng hạn như trong các câu lệnh truy vấn hay các câu lệnh thực hiện cập nhật dữ liệu
Trong SQL có rất nhiều các hàm được định nghĩa sẵn (Được chia theo nhóm – Trong 1 Database bạn chọn Programmability/Functions/System Functions) như các hàm về chuỗi (String Functions), các hàm về ngày tháng (Date and Time Functions), Các hàm toán học (Mathematical Function), … Ngoài những hàm do hệ quản trị cơ sở dữ liệu cung cấp sẵn, bạn có thể tự xây dựng các hàm nhằm phục vụ cho mục đích riêng của mình – Các hàm do người dùng định nghĩa. Các hàm do người dùng định nghĩa thường có 2 loại: Loại 1 là Hàm với giá trị trả về là “dữ liệu kiểu bảng” – Table-valued Functions; Loại 2 là Hàm với giá trị trả về là một giá trị – Scalar-valued Functions và các hàm này cũng sẽ được Hệ quản trị phân thành 2 nhóm.
Các hàm sẵn có của SQL bạn tự tìm hiểu và sử dụng, trong bài viết này mình giới thiệu qua về những hàm “Do người dùng định nghĩa”.
Cú pháp của hàm như sau:
CREATE FUNCTION Ten_Ham ( [Danh_Sach_Cac_Tham_So] ) RETURNS Kieu_Du_Lieu_Tra_Ve_Cua_Ham AS BEGIN Cac_Cau_Lenh_Cua_Ham END
– Ten_Ham: Tên của hàm cần tạo. Tên phải tuân theo qui tắc định danh và không trùng với tên của các hàm hệ thống có sắn. – Danh_Sach_Cac_Tham_So: Các tham số của hàm được khai báo ngay sau tên hàm và được bao bởi cặp dấu (), Danh sách các tham số này có thể không có – trường hợp này thì sau tên hàm bạn cần có cặp dấu (). Nếu hàm có nhiều tham số thì các khai báo phân cách nhau bởi dấu phẩy và phải bao hồm 2 phần: Tên tham số được bắt đầu bởi dấu @, Kiểu dữ liệu của tham số – Cac_Cau_Lenh_Cua_Ham: Tập hợp các câu lệnh sử dụng trong nội dung hàm để thực hiện các yêu cầu của hàm.
Ví dụ 1: Mình sẽ lấy một ví dụ thật đơn giản là hàm không có Danh_Sach_Cac_Tham_So – trả về giá trị là năm hiện hành (Theo giờ hệ thống trên máy Database server):
CREATE FUNCTION dbo.fuGetCurrYear () RETURNS int AS BEGIN RETURN YEAR(getdate()) END
Xem ví dụ trên bạn sẽ thấy nó rất đơn giản nhưng qua đây bạn cũng đã biết được việc viết hàm trong SQL như thế nào.
Ví dụ 2: Tiếp theo mình sẽ viết một ví dụ nữa để bạn hiểu và có thể viết cho mình các hàm tự định nghĩa:
CREATE FUNCTION dbo.fuDaysInMonth ( @Thang Int, @Nam Int ) RETURNS int AS BEGIN DECLARE @Ngay Int IF @Thang = 2 BEGIN OR (@Nam % 400 = 0)) SET @Ngay = 29 ELSE SET @Ngay = 28 END ELSE SELECT @Ngay = CASE @Thang WHEN 1 THEN 31 WHEN 3 THEN 31 WHEN 5 THEN 31 WHEN 7 THEN 31 WHEN 8 THEN 31 WHEN 10 THEN 31 WHEN 12 THEN 31 WHEN 4 THEN 30 WHEN 6 THEN 30 WHEN 9 THEN 30 WHEN 11 THEN 30 END RETURN @Ngay ENDVí dụ 3: Bạn xem tiếp ví dụ sau để xác định thứ trong tuần của một giá trị kiểu ngày
CREATE FUNCTION fuThu ( @ngay DATETIME ) RETURNS NVARCHAR(10) AS BEGIN DECLARE @KetQua NVARCHAR(10) SELECT @KetQua=CASE DATEPART(DW,@ngay) WHEN 1 THEN N’Chủ nhật’ WHEN 2 THEN N’Thứ hai’ WHEN 3 THEN N’Thứ ba’ WHEN 4 THEN N’Thứ tư’ WHEN 5 THEN N’Thứ năm’ WHEN 6 THEN N’Thứ sáu’ ELSE N’Thứ bảy’ END RETURN (@KetQua) /* Trị trả về của hàm */ END
SELECT e.FirstName, e.LastName, dbo.fuThu(e.BirthDate) AS ThuOfBirth FROM Employees e
Tiếp theo mình sẽ nói về Hàm với giá trị trả về là “dữ liệu kiểu bảng” Nếu đã biết về SQL chắc hẳn bạn đã biết cách tạo View từ các bảng trong CSDL, Nhưng với View bạn không thể truyền các tham số được, điều này phần nào đó làm giảm tính linh hoạt trong việc sử dụng View. Vậy nên khi bạn cần sử dụng dữ liệu dạng View mà có các tham số thì việc sử dụng hàm là một giải pháp hợp lý nhất. Ví dụ 4: Giả sử Mình tạo 1 View như sau:
CREATE VIEW vProducts as SELECT Categories.CategoryID, Categories.CategoryName, Products.ProductName, Products.QuantityPerUnit, Products.UnitPrice FROM Categories INNER JOIN Products ON Categories.CategoryID = Products.CategoryID WHERE Categories.CategoryID=1Ví dụ 5: Tạo một hàm trả về dữ liệu dạng bảng tùy theo giá trị của biến @CategoryID truyền vào:
CREATE FUNCTION fuGetProducts ( @CategoryID int )RETURNS TABLE AS RETURN ( SELECT Categories.CategoryID, Categories.CategoryName, Products.ProductName, Products.QuantityPerUnit, Products.UnitPrice FROM Categories INNER JOIN Products ON Categories.CategoryID = Products.CategoryID WHERE Categories.CategoryID=@CategoryID)
chạy thử hàm trên(Chú ý là khi hàm trả về dạng bảng bạn cũng coi đó như 1 table hoặc 1 View và bạn có thể truy vấn theo 1 hay nhiều trường của hàm) như sau:
SELECT CategoryID, CategoryName, ProductName, QuantityPerUnit, UnitPrice FROM dbo.fuGetProducts(1)
Sẽ tra về dữ liệu chính là Select * from vProducts ở trên. Nếu muốn lầy Theo CategoryID=2 bạn dùng câu lệnh Select * from dbo.fuGetProducts(2)…