Store Procedures, functions and Trigger in SQL (P2- Functions)

Hiện tại, vì công việc quá bận rộn nên mình không còn thời gian để post bài và duy trì nội dung cho blog nữa. Do đó tại thời điểm này, mình quyết định ngừng phát triển blog. Mọi bài viết sẽ vẫn được lưu trữ và mình sẽ cố gắng hỗ trợ tất cả các bạn khi có comment hỏi. Cảm ơn các bạn đã ủng hộ blog suốt thời gian qua !
Hàm do người dùng định nghĩa

Hàm là đối tượng cơ sở dữ liệu tương tự như thủ tục. Đ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 còn thủ tục thì không. Đ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 trong danh sách chọn của câu lệnh SELECT).

Ngoài những hàm do hệ quản trị cơ sở dữ liệu cung cấp sẵn, người sử dụng có thể định nghĩa thêm các hàm nhằm phục vụ cho mục đích riêng của mình.


Định nghĩa và sử dụng hàm

Hàm được định nghĩa thông qua câu lệnh CREATE FUNCTION với cú pháp như sau:

CREATE FUNCTION tên_hàm ([danh_sách_tham_số]) 
RETURNS (kiểu_trả_về_của_hàm)
AS 
BEGIN
   các_câu_lệnh_của_hàm
END

Ví dụ : Câu lệnh dưới đây định nghĩa hàm tính ngày trong tuần (thứ trong tuần) của một giá trị kiểu ngày

CREATE FUNCTION thu(@ngay DATETIME)
RETURNS NVARCHAR(10)
AS
     BEGIN
          DECLARE @st NVARCHAR(10)
          SELECT @st=CASE DATEPART(DW,@ngay)
                        WHEN 1 THEN 'Chu nhật'
                        WHEN 2 THEN 'Thứ hai'
                        WHEN 3 THEN 'Thứ ba'
                        WHEN 4 THEN 'Thứ tư'
                        WHEN 5 THEN 'Thứ năm'
                        WHEN 6 THEN 'Thứ sáu'
                        ELSE 'Thứ bảy'
                      END   
          RETURN (@st)  /* Trị trả về của hàm */
     END

Một hàm khi đã được định nghĩa có thể được sử dụng như các hàm do hệ quản trị cơ sở dữ liệu cung cấp (thông thường trước tên hàm ta phải chỉ định thêm tên của người sở hữu hàm)

Ví dụ Câu lệnh SELECT dưới đây sử dụng hàm đã được định nghĩa ở ví dụ trước:

SELECT masv,hodem,ten,dbo.thu(ngaysinh),ngaysinh
FROM sinhvien
WHERE malop='C24102'

Hàm với giá trị trả về là "dữ liệu kiểu bảng"

Ta đã biết được chức năng cũng như sự tiện lợi của việc sử dụng các khung nhìn trong cơ sở dữ liệu. Tuy nhiên, nếu cần phải sử dụng các tham số trong khung nhìn (chẳng hạn các tham số trong mệnh đề WHERE của câu lệnh SELECT) thì ta lại không thể thực hiện được. Điều này phần nào đó làm giảm tính linh hoạt trong việc sử dụng khung nhìn.

Ví dụ : Xét khung nhìn được định nghĩa như sau:

CREATE VIEW  sinhvien_k25
AS
     SELECT masv,hodem,ten,ngaysinh
     FROM sinhvien INNER JOIN lop
          ON sinhvien.malop=lop.malop
     WHERE khoa=25

với khung nhìn trên, thông qua câu lệnh:

SELECT * FROM sinhvien_K25

ta có thể biết được danh sách các sinh viên khoá 25 một cách dễ dàng nhưng rõ ràng không thể thông qua khung nhìn này để biết được danh sách sinh viên các khoá khác do không thể sử dụng điều kiện có dạng KHOA = @thamso trong mệnh đề WHERE của câu lệnh SELECT được.

Nhược điểm trên của khung nhìn có thể khắc phục bằng cách sử dụng hàm với giá trị trả về dưới dạng bảng và được gọi là hàm nội tuyến (inline function). Việc sử dụng hàm loại này cung cấp khả năng như khung nhìn nhưng cho phép chúng ta sử dụng được các tham số và nhờ đó tính linh hoạt sẽ cao hơn.

Một hàm nội tuyến được định nghĩa bởi câu lệnh CREATE TABLE với cú pháp như sau:

CREATE FUNCTION tên_hàm ([danh_sách_tham_số])
RETURNS TABLE
AS  
     RETURN (câu_lệnh_select)

Cú pháp của hàm nội tuyến phải tuân theo các qui tắc sau:
Kiểu trả về của hàm phải được chỉ định bởi mệnh đề RETURNS TABLE.
Trong phần thân của hàm chỉ có duy nhất một câu lệnh RETURN xác định giá trị trả về của hàm thông qua duy nhất một câu lệnh SELECT. Ngoài ra, không sử dụng bất kỳ câu lệnh nào khác trong phần thân của hàm.


Ví dụ : Ta định nghĩa hàm func_XemSV như sau:

CREATE FUNCTION func_XemSV(@khoa SMALLINT)
RETURNS TABLE
AS
  RETURN(SELECT masv,hodem,ten,ngaysinh
         FROM sinhvien INNER JOIN lop
              ON sinhvien.malop=lop.malop 
         WHERE khoa=@khoa)

hàm trên nhận tham số đầu vào là khóa của sinh viên cần xem và giá trị trả về của hàm là tập các dòng dữ liệu cho biết thông tin về các sinh viên của khoá đó. Các hàm trả về giá trị dưới dạng bảng được sử dụng như là các bảng hay khung nhìn trong các câu lệnh SQL.

Với hàm được định nghĩa như trên, để biết danh sách các sinh viên khoá 25, ta sử dụng câu lệnh như sau:

SELECT * FROM dbo.func_XemSV(25)

còn câu lệnh dưới đây cho ta biết được danh sách sinh viên khoá 26

SELECT * FROM dbo.func_XemSV(26)

Đối với hàm nội tuyến, phần thân của hàm chỉ cho phép sự xuất hiện duy nhất của câu lệnh RETURN. Trong trường hợp cần phải sử dụng đến nhiều câu lệnh trong phần thân của hàm, ta sử dụng cú pháp như sau để định nghĩa hàm:

CREATE FUNCTION tên_hàm([danh_sách_tham_số])
RETURNS @biến_bảng TABLE định_nghĩa_bảng
AS
  BEGIN 
các_câu_lệnh_trong_thân_hàm 
RETURN
END

Khi định nghĩa hàm dạng này cần lưu ý một số điểm sau:

Cấu trúc của bảng trả về bởi hàm được xác định dựa vào định nghĩa của bảng trong mệnh đề RETURNS. Biến @biến_bảng trong mệnh đề RETURNS có phạm vi sử dụng trong hàm và được sử dụng như là một tên bảng.

Câu lệnh RETURN trong thân hàm không chỉ định giá trị trả về. Giá trị trả về của hàm chính là các dòng dữ liệu trong bảng có tên là @biếnbảng được định nghĩa trong mệnh đề RETURNS

Cũng tương tự như hàm nội tuyến, dạng hàm này cũng được sử dụng trong các câu lệnh SQL với vai trò như bảng hay khung nhìn. Ví dụ dưới đây minh hoạ cách sử dụng dạng hàm này trong SQL.

Ví dụ : Ta định nghĩa hàm func_TongSV như sau:

CREATE FUNCTION Func_Tongsv(@khoa SMALLINT)
RETURNS @bangthongke TABLE
     (
          makhoa    NVARCHAR(5),
          tenkhoa   NVARCHAR(50),
          tongsosv  INT
     )
AS
     BEGIN
          IF @khoa=0
              INSERT INTO @bangthongke
              SELECT khoa.makhoa,tenkhoa,COUNT(masv)
               FROM (khoa INNER JOIN lop
                         ON khoa.makhoa=lop.makhoa)
                          INNER JOIN sinhvien
                         on lop.malop=sinhvien.malop
              GROUP BY khoa.makhoa,tenkhoa
          ELSE
              INSERT INTO @bangthongke
              SELECT khoa.makhoa,tenkhoa,COUNT(masv)
              FROM (khoa INNER JOIN lop
                         ON khoa.makhoa=lop.makhoa)
                          INNER JOIN sinhvien
                         ON lop.malop=sinhvien.malop
              WHERE khoa=@khoa
              GROUP BY khoa.makhoa,tenkhoa
          RETURN /*Trả kết quả về cho hàm*/
     END

Với hàm được định nghĩa như trên, câu lệnh:

SELECT * FROM dbo.func_TongSV(25)

Sẽ cho kết quả thống kê tổng số sinh viên khoá 25 của mỗi khoa:

Còn câu lệnh:

SELECT * FROM dbo.func_TongSV(0)

Cho ta biết tổng số sinh viên hiện có (tất cả các khoá) của mỗi khoa

Nguồn: BIS
 

Web Design Technology blogs [ itdl ] Auto Backlink

HomeBlog ArchiveServicesLink2MeContactSubmit your PostPost RSS

Copyright © 2012 [ itdl ] Just for Share. Designed by Ngoc Luong - Freelancer

Best view in Chrome 11+, Firefox 5+ with resolution 1024 x 768 pixel. Powered by Blogger.