User Defined Functions - UDFs
Nguồn : forum.t3h.vn
I Khái quát về hàm do người dùng định nghĩa
I.1 Hàm do người dùng định nghĩa là gì?
Hàm do người dùng định nghĩa (user defined functions - UDFs) là một đối
tượng mới được bổ sung của phiên bản SQL Server 2000. Trước hết, bạn
cần biết rằng UDFs mang đầy đủ các ý nghĩa và tính chất của một hàm
như đa số các ngôn ngữ lập trình khác, có nghĩa là một UDFs là một
chương trình con đảm trách một xử lý nào đó với đặc tính là sẽ nhận các
tham số đầu vào và trả về một giá trị kết quả xử lý tính toán được dựa trên
các tham số đầu vào đã nhận.
Không chỉ UDFs mà tất cả các hàm nói chung (Các phiên bản SQL Server
trước đây cung cấp các hàm được cài đặt sẵn như getdate(),
object_name(),… ) có thể phân ra thành hai nhóm : hàm xác định
(deterministic) và hàm không xác định (non-deterministic).
Các hàm xác định sẽ luôn luôn trả về cùng giá trị nếu giá trị các tham số
được cung cấp (truyền vào) là như nhau.
Các hàm không xác định có thể tạo ra các kết quả khác biệt tại mỗi thời
điểm chúng được gọi thực hiện, ngay cả khi giá trị các tham số được cung
cấp vẫn không thay đổi.
Trong một số tài liệu bạn thấy có xuất hiện thuật ngữ “scalar functions –
các hàm vô hướng” dùng để chỉ các hàm trả về một giá trị, tương phản với
nó là các hàm trả về một table.
Hàm getdate() là một ví dụ điển hình cho cả hai : hàm vô hướng (scalar)
và hàm không xác định (non-deterministic). Nếu bạn gọi thực hiện nó hai
lần với cùng một dòng lệnh gọi, bạn sẽ nhận được hai kết quả khác nhau
và chỉ có duy nhất một giá trị cho mỗi lần gọi.
Như chúng tôi đã trình bày, UDFs mang đầy đủ các tính chất của một
hàm, ngoài ra, bạn cũng có thể hình dung UDFs là sự kết hợp của hai đối
tượng View và Stored Procedure. Hơn thế nữa, nó còn có những tính
năng sử dụng mà View và Stored Procedure không có được, hay nói cách
khác nó khắc phục một số các hạn chế của View và Stored Procedure. Ví
dụ : Stored Procedure không thể là một phần của câu lệnh SELECT
nhưng UDFs , View không hỗ trợ sự đệ quy trong khi với UDFs thì bạn có
thể làm được điều này.
II Làm việc với UDFs
Trong phần này chúng tôi sẽ hướng dẫn các bạn cách thức:
Tạo UDFs .
Thay đổi tên của UDFs và nội dung các câu lệnh chứa bên trong nó.
Xem (view), xoá (drop) UDFs.
II.1 Tạo mới UDFs
Giống như các đối tượng khác trong Microsoft SQL Server mà chúng tôi
đã trình bày trước đây ở các chương trước, các bạn có hai (2) cách để có
thể tạo mới một UDFs: sử dụng các câu lệnh T-SQL hoặc dùng tiện ích
Enterprise Manager.
II.1.1 Sử dụng câu lệnh T-SQL
Bạn có thể câu lệnh CREATE FUNCTION để tạo một UDFs bằng cách sử
dụng tiện ích SQL Query Analyzer hoặc sử dụng công cụ dạng dấu nhắc
lệnh (command-prompt) điển hình như công cụ osql.
Cú pháp:
CREATE FUNCTION [Tên_FUNCTION] (Khai báo các tham số )
RETURNS Kiểu_dữ Liệu_trả_về AS
BEGIN
-Các câu lệnh bên trong FUNCTION-
RETURN
END
Mệnh đề CREATE FUNCTION
Việc tạo UDFs bắt đầu với mệnh đề CREATE FUNCTION theo sau làtên
của UDFs. Ngay sau tên của UDFs là phần khai báo các tham số của
UDFs. Chú ý là các tham số phải tuân thủ quy tắc của một định danh và
phải bắt đầu bằng ký hiệu @. Về nguyên tắc, một UDFs có thể không có
tham số.
Ví dụ : UDFs không có tham số
CREATE FUNCTION [Test_Func] ()
Ví dụ : UDFs có tham số
CREATE FUNCTION [Chuan_Ho_Ten] (@ChuoiHoTen varchar(50))
Mệnh đề RETURNS
Dùng để thiết lập kiểu dữ liệu trả về của UDFs. Có hai cách thiết lập chính
:
Trả về giá trị kiểu vô hướng. Khi chỉ định kiểu này, UDFs sẽ trả về giá
trị kết quả đơn lẻ như là: một chuỗi , một giá trị logic, hoặc một giá trị kiểu
số.
Trả về một table. Trên thực tế bạn có thể chỉ định trả về hai loại table:
o inline table : Với loại này, bạn chỉ có thể thực hiện bên trong nó câu
lệnh SELECT rõ ràng không quá phức tạp. UDFs loại này thực chất được
dùng để thay thế cho các đối tượng VIEW, bởi nó khắc phục được nhược
điểm không có tham số của VIEW. Bạn có thể hình dung một UDFs loại
inline table giống như là một VIEW có tham số.
Ví dụ :
create view V_DSHangHoa
as
Select * from DM_HANG_HOA where MaLoai_HH='TiVi'
go
Ví dụ : Việc tạo view ở ví dụ trên thật khó làm cho ta thoả mãn bởi trong
trường hợp ta muốn danh sách gồm các mặt hàng không phải là loại TiVi
thì sao? Bạn cũng đã biết là VIEW không hỗ trợ tham số. Để giải quyết
vấn đề này, bạn có thể tạo một UDFs với tham số cho phép truyền vào giá
trị loại hàng hoá.
CREATE FUNCTION F_DSHangHoa(@LoaiHH varchar(50))
RETURNS Table AS
Return
(Select * from DM_HANG_HOA where MaLoai_HH=@LoaiHH)
Go
Chú ý : Khi sử dụng UDFs loại inline table bạn cần quan tâm đến các quy
tắc sau :
Mệnh đề RETURNS chứa duy nhất từ khoá table. Bạn không phải
định nghĩa kiểu của biến trả về, bởi vì nó là tập được định dạng bởi tập kết
quả truy vấn của câu lệnh SELECT trong mệnh đề RETURN.
Không có phần thân của hàm với việc bắt đầu bởi BEGIN và kết thúc
bởi END.
Mệnh đề RETURN chứa một câu lệnh SELECT đơn giản nằm trong
cặp dấu ngoặc đơn. Câu lệnh SELECT được sử dụng trong hàm có các
hạn chế giống như câu lệnh SELECT được sử dụng trong đối tượng
VIEW.
o Multistatement table : Khi bạn chỉ định kiểu này, UDFs trở nên rất
giống các Stored Procedure. Nó cho phép thực hiện các câu lệnh SELECT
phức tạp, hơn nữa nó còn cho phép thực hiện các câu lệnh logic khác như
UPDATE, INSERT INTO,… Đồng thời bạn có thể thiết lập cấu trúc trong
cặp dấu ngoặc đơn ngay sau câu lệnh RETURNS. Loại này sẽ luôn trả về
một biến table (chỉ duy nhất một biến table).
Ví dụ :
CREATE FUNCTION F_DSHangHoa(@LoaiHH varchar(50),@PhanTram
numeric)
RETURNS @DSHangHoa Table
(
Ma_HH varchar(50),
Ten_HH varchar(50),
DonGiaKhuyenMai numeric
)
AS
Begin
Insert Into @DSHangHoa(Ma_HH,Ten_HH,DonGiaKhuyenMai)
Select ID_HH,Ten_HH,DonGiaHienHanh
from DM_HANG_HOA where IDLoai_HH=@LoaiHH
Update @DSHangHoa
Set DonGiaKhuyenMai=DonGiaKhuyenMai-
(DonGiaKhuyenMai*@PhanTram)/100
Return
End
Chú ý : Khisử dụng UDFs loại Multistatement table bạn cần quan tâm đến
các hạn chế sau :
Không thể gọi một stored procedure từ các câu lệnh bên trong nó.
Không thể sử dụng các hàm loại không xác định được xây dựng sẵn
trong SQL Server, ví dụ: Getdate, Rand, …
Việc sử dụng RAISERROR và @@ERROR là hoàn toàn không hợp
lệ.
UDFs không thể được sử dụng để sửa đổi thông tin trên table cơ sở.
Mệnh đề AS
Mệnh AS được khai báo trước các câu lệnh bên trong UDFs.
Khối lệnh BEGIN … END
Phần thân của UDFs được bắt đầu sau từ khoá BEGIN và kết thúc bởi từ
khóa END. Chú ý rằng khối lệnh này không sử dụng cho trường hợp UDFs
loại inline table.