我們在這一章裏討論了實現用戶自定義函數的方法,解釋三種類型的用戶自定義,併爲它們分別提供了一個實例!
1.何爲用戶自定義函數:我們可以通過SQL SERVER2000設計自己的函數,來補充和擴展系統提供的內置函數!用戶自定義函數的輸入參數可以有多個,也可以沒有,但是其數據類型不能爲時間戳,遊標和表,同時用戶自定義函數的返回值或者是個標題,或者是個表!
有三種類型的用戶自定義函數:
1. 標量函數:與內置函數相似。
2. 多語句表值函數:返回由一個或是多個T-SQL語句建造的表,這一動作與存儲過程類似,但是與存儲過程不同的是它能夠像視圖一樣,在SELECT語句中的FROM語句中引用!它可用來代替返回表的存儲過程,這可大大提高SQL SERVER的性能!
3. 嵌入式表值函數:它返回一個表,該表是單條SELECT語句的結果,這和視圖相似,但在參數的使用上比視圖有更大的靈活性,在視圖上我們不能夠使用參數,但是在嵌入式表值函數中可以使用參數!我們可以使用嵌入式表值函數來創建參數化視圖!
2.定義用戶自定義函數:下面我們就進行用戶自定義函數的創建的,修改和刪除!
1.創建用戶自定義函數:我們使用create function語句來創建函數,同時指定的數據類型,處理的過程及返回值的數據類型:
CREATE FUNCTION [ owner_name.] function_name
( [ { @parameter_name [AS] scalar_parameter_data_type [ = default ] } [ ,...n ] ] )
RETURNS scalar_return_data_type
[ WITH < function_option> [ [,] ...n] ]
[ AS ]
BEGIN
function_body
RETURN scalar_expression
END
下面我們來看個例子:
create function fn_nNewRegion
(@myinput nvarchar(30))
returns nvarchar(30)
begin
if @myinput is null
set @myinput=’not applicable’
return @myinput
end
我們不能夠在用戶自定義函數的函數體內包括不確定性函數。不確定性函數也是一種函數,它是在相同的輸入條件下,每次返回不同的值。如:GETDATE()等。但是我們可以在輸入參數中使用它!
我們可以使用模式綁定創建函數:此時我們將把函數綁定到它所引用的數據庫對象上。如果一個函數通過使用模式綁定選項被創建,則這個函數所引用的數據庫對象不能(通過使用ALTER語句或DROP語句)被修改或刪除!但是在它創建的時候它所引用的視圖或用戶自定義函數也都是一種模式綁定,還要求函數和對象在一個數據庫內!
當我們修改函數的時候,SQL SERVER將用新的函數定義來代替已有的函數定義。但是像視圖和存儲過程一樣,仍保留所賦予的權限!――alter function…
刪除函數:drop function….
3.用戶自定義函數舉例:
函數類型 Returns子句指定的數據類型 是否使用BEGIN。。。
END SELECT 語句的個數 使用
標量函數 數據類型 使用 多個 在上結果集上使用複雜
多語句表值函數函數 表(表結構) 使用 多個 代替返回表的存儲過程
嵌入式表值函數 表 不使用(return) 單個 創建帶參數的視圖
實驗1。創建用戶自定義標量函數:計算稅率(因爲有些產品是免稅的,而有些是高稅的)
CREATE FUNCTION fn_TaxRate
(@ProdID INT)
RETURNS numeric(5,4)
AS
BEGIN
RETURN
(SELECT
CASE CategoryID
WHEN 1 THEN 1.10
WHEN 2 THEN 1
WHEN 3 THEN 1.10
WHEN 4 THEN 1.05
WHEN 5 THEN 1
WHEN 6 THEN 1.05
WHEN 7 THEN 1
WHEN 8 THEN 1.05
END
FROM Products
WHERE ProductID = @ProdID)
END
GO
測試:
SELECT ProductName, UnitPrice, CategoryID,dbo.fn_TaxRate(ProductID) AS TaxRate,
UnitPrice * Northwind.dbo.fn_TaxRate(ProductID) AS PriceWithTax FROM Products
實驗2。創建一個多語句表值函數:創建一個帶有管理者EmployeeID號爲參數的函數,並通過employee表進行迭帶,悼念向任何層次上指定管理者彙報的僱員的信息。
Create FUNCTION fn_FindReports (@InEmployeeID char(5))
RETURNS @reports TABLE
(EmployeeID char(5) PRIMARY KEY,
Name nvarchar(40) NOT NULL,
Title nvarchar(30),
MgrEmployeeID int,
processed tinyint default 0)
-- Returns a result set that lists all the employees who
-- report to a given employee directly or indirectly
AS
BEGIN
DECLARE @RowsAdded int
-- Initialize @reports with direct reports of the given employee
INSERT @reports
SELECT EmployeeID, Name = FirstName + ' ' + LastName, Title, ReportsTo, 0
FROM Employees
WHERE ReportsTo = @InEmployeeID
SET @RowsAdded = @@rowcount
-- While new employees were added in the previous iteration
WHILE @RowsAdded > 0
BEGIN
-- Mark all employee records whose direct reports are going to be
-- found in this iteration
UPDATE @reports
SET processed = 1
WHERE processed = 0
-- Insert employees who report to employees marked 1
INSERT @reports
SELECT e.EmployeeID, Name = FirstName + ' ' + LastName , e.Title, e.ReportsTo, 0
FROM Employees e, @reports r
WHERE e.ReportsTo = r.EmployeeID
AND r.processed = 1
SET @RowsAdded = @@rowcount
-- Mark all employee records whose direct reports hae been
-- found in this iteration
UPDATE @reports
SET processed = 2
WHERE processed = 1
END
RETURN -- Provides the value of @reports as the result
END
GO
測試:
SELECT EmployeeID, [Name], Title, MgrEmployeeID FROM dbo.fn_FindReports(5)
SELECT EmployeeID, [Name], Title, MgrEmployeeID FROM dbo.fn_FindReports(2)
實驗3。創建嵌入式表值函數:創建一個嵌入式表值函數來替代視圖,這個函數返回超過一定美元數量的貨物訂單
CREATE FUNCTION fn_LargeFreight
(@FreightAmt money)
RETURNS TABLE
AS
RETURN
( SELECT S.ShipperID, S.CompanyName,
O.OrderID, O.ShippedDate, O.Freight
FROM Shippers AS S JOIN Orders AS O
ON S.ShipperID = O.ShipVia
WHERE O.Freight > @FreightAmt
)
測試:
SELECT * FROM fn_LargeFreight(600)