一、背景知識(shí)
與編程語言中的函數(shù)一樣,SQL Server 用戶定義函數(shù)是接受參數(shù)、執(zhí)行操作(如復(fù)雜計(jì)算)并將該操作的結(jié)果作為值返回的例程。返回值可以是單個(gè)標(biāo)量值,也可以是結(jié)果集。
1.1、用戶定義函數(shù)的優(yōu)點(diǎn)
-
模塊化編程??梢詣?chuàng)建一次函數(shù),將其存儲(chǔ)在數(shù)據(jù)庫(kù)中,并在程序中調(diào)用它任意次數(shù)??梢元?dú)立于程序源代碼修改用戶定義的函數(shù)。
-
執(zhí)行速度更快。與存儲(chǔ)過程類似,Transact-SQL 用戶定義函數(shù)通過緩存計(jì)劃并重用它們進(jìn)行重復(fù)執(zhí)行來降低 Transact-SQL 代碼的編譯成本。這意味著用戶定義的函數(shù)不需要在每次使用時(shí)重新解析和重新優(yōu)化,從而縮短執(zhí)行時(shí)間。
-
與 Transact-SQL 函數(shù)相比,CLR 函數(shù)在計(jì)算任務(wù)、字符串操作和業(yè)務(wù)邏輯方面具有顯著的性能優(yōu)勢(shì)。事務(wù)處理 SQL 函數(shù)更適合數(shù)據(jù)訪問密集型邏輯。
-
減少網(wǎng)絡(luò)流量?;谀承o法在單個(gè)標(biāo)量表達(dá)式中表示的復(fù)雜約束篩選數(shù)據(jù)的操作可以表示為函數(shù)。然后可以在 WHERE 子句中調(diào)用該函數(shù),以減少發(fā)送到客戶端的行數(shù)。
查詢中的事務(wù)處理 SQL UDF 只能在單個(gè)線程(串行執(zhí)行計(jì)劃)上執(zhí)行。因此,使用 UDF 會(huì)抑制并行查詢處理。
1.2、函數(shù)類型
-
標(biāo)量函數(shù)。用戶定義的標(biāo)量函數(shù)返回 RETURNS 子句中定義的類型的單個(gè)數(shù)據(jù)值。對(duì)于內(nèi)聯(lián)標(biāo)量函數(shù),返回的標(biāo)量值是單個(gè)語句的結(jié)果。對(duì)于多語句標(biāo)量函數(shù),函數(shù)體可以包含一系列返回單個(gè)值的 Transact-SQL 語句。返回類型可以是除文本、ntext、圖像、光標(biāo)和時(shí)間戳之外的任何數(shù)據(jù)類型。
-
表值函數(shù)。用戶定義的表值函數(shù) (TVF) 返回表數(shù)據(jù)類型。對(duì)于內(nèi)聯(lián)表值函數(shù),沒有函數(shù)體;該表是單個(gè) SELECT 語句的結(jié)果集。有關(guān)示例,請(qǐng)參閱創(chuàng)建用戶定義函數(shù)(數(shù)據(jù)庫(kù)引擎)。
-
系統(tǒng)功能。SQL Server 提供了許多可用于執(zhí)行各種操作的系統(tǒng)函數(shù);它們無法修改。
1.3、指引
導(dǎo)致語句被取消并繼續(xù)執(zhí)行模塊中的下一條語句(如觸發(fā)器或存儲(chǔ)過程)的 Transact-SQL 錯(cuò)誤在函數(shù)中處理方式不同。在函數(shù)中,此類錯(cuò)誤會(huì)導(dǎo)致函數(shù)的執(zhí)行停止。這反過來會(huì)導(dǎo)致調(diào)用函數(shù)的語句被取消。
塊中的語句不能有任何副作用。函數(shù)副作用是對(duì)具有函數(shù)范圍之外的資源狀態(tài)的任何永久更改,例如對(duì)數(shù)據(jù)庫(kù)表的修改。函數(shù)中的語句可以進(jìn)行的唯一更改是對(duì)函數(shù)局部對(duì)象的更改,例如局部游標(biāo)或變量。對(duì)數(shù)據(jù)庫(kù)表的修改、對(duì)非函數(shù)本地游標(biāo)的操作、發(fā)送電子郵件、嘗試修改目錄以及生成返回給用戶的結(jié)果集是無法在函數(shù)中執(zhí)行的操作的示例。
如果語句對(duì)發(fā)出該語句時(shí)不存在的資源產(chǎn)生副作用,則 SQL Server 將執(zhí)行該語句。但是,SQL Server 在調(diào)用函數(shù)時(shí)不會(huì)執(zhí)行該函數(shù)。
查詢中指定的函數(shù)的執(zhí)行次數(shù)可能因優(yōu)化程序構(gòu)建的執(zhí)行計(jì)劃而異。例如,子句中的子查詢調(diào)用的函數(shù)。子查詢及其函數(shù)的執(zhí)行次數(shù)可能因優(yōu)化程序選擇的不同訪問路徑而異。
確定性函數(shù)必須是架構(gòu)綁定的。在創(chuàng)建確定性函數(shù)時(shí)使用SCHEMABINDING子句。
1.4、函數(shù)中的有效語句
在函數(shù)中有效的語句類型包括:
-
DECLARE語句可用于定義函數(shù)的本地?cái)?shù)據(jù)變量和游標(biāo)。
-
將值賦值到函數(shù)的本地對(duì)象,例如用于將值賦值給標(biāo)量變量和表局部變量。
-
引用在函數(shù)中聲明、打開、關(guān)閉和釋放的本地游標(biāo)的游標(biāo)操作。 不允許使用將數(shù)據(jù)返回到客戶端的語句。只允許使用該子句將值賦值給局部變量的 FETCH 語句。
-
流控制語句(語句除外)。
-
SELECT包含選擇列表的語句,這些表達(dá)式將值分配給函數(shù)的局部變量。
-
UPDATE語句修改函數(shù)的局部表變量。
-
EXECUTE調(diào)用擴(kuò)展存儲(chǔ)過程的語句。
內(nèi)置系統(tǒng)功能:
(1)以下非確定性內(nèi)置函數(shù)可用于事務(wù)處理 SQL 用戶定義函數(shù)。
- CURRENT_TIMESTAMP
- GET_TRANSMISSION_STATUS
- GETDATE
- GETUTCDATE
- @@CONNECTIONS
- @@CPU_BUSY
- @@DBTS
- @@IDLE
- @@IO_BUSY
- @@MAX_CONNECTIONS
- @@PACK_RECEIVED
- @@PACK_SENT
- @@PACKET_ERRORS
- @@TIMETICKS
- @@TOTAL_ERRORS
- @@TOTAL_READ
- @@TOTAL_WRITE
(2)以下非確定性內(nèi)置函數(shù)不能在 Transact-SQL 用戶定義函數(shù)中使用。
- NEWID
- NEWSEQUENTIALID
- RAND
- TEXTPTR
1.5、架構(gòu)綁定函數(shù)
CREATE FUNCTION支持將函數(shù)綁定到它引用的任何對(duì)象(如表、視圖和其他用戶定義函數(shù))的架構(gòu)的子句。嘗試更改或刪除架構(gòu)綁定函數(shù)引用的任何對(duì)象失敗。
必須先滿足以下條件,然后才能在創(chuàng)建函數(shù)中指定:
-
函數(shù)引用的所有視圖和用戶定義函數(shù)都必須是架構(gòu)綁定的。
-
函數(shù)引用的所有對(duì)象必須與函數(shù)位于同一數(shù)據(jù)庫(kù)中。必須使用由一部分或兩部分組成的名稱來引用對(duì)象。
-
必須對(duì)函數(shù)中引用的所有對(duì)象(表、視圖和用戶定義函數(shù))具有權(quán)限。
可以使用 ALTER FUNCTION、ALTER FUNCTIONWITH SCHEMABINDING 刪除架構(gòu)綁定。該語句應(yīng)重新定義函數(shù)而不指定 。
1.6、指定參數(shù)
用戶定義的函數(shù)采用零個(gè)或多個(gè)輸入?yún)?shù),并返回標(biāo)量值或表。一個(gè)函數(shù)最多可以有 1024 個(gè)輸入?yún)?shù)。當(dāng)函數(shù)的參數(shù)具有默認(rèn)值時(shí),調(diào)用函數(shù)時(shí)必須指定關(guān)鍵字 DEFAULT 才能獲取默認(rèn)值。此行為不同于用戶定義存儲(chǔ)過程中具有默認(rèn)值的參數(shù),在用戶定義存儲(chǔ)過程中,省略參數(shù)也意味著默認(rèn)值。用戶定義的函數(shù)不支持輸出參數(shù)。
二、創(chuàng)建用戶定義函數(shù)
2.1、限制和權(quán)限
限制:
-
用戶定義的函數(shù)不能用于執(zhí)行修改數(shù)據(jù)庫(kù)狀態(tài)的操作。
-
用戶定義的函數(shù)不能包含以表為目標(biāo)的子句。
-
用戶定義的函數(shù)不能返回多個(gè)結(jié)果集。如果需要返回多個(gè)結(jié)果集,請(qǐng)使用存儲(chǔ)過程。
-
錯(cuò)誤處理在用戶定義的函數(shù)中受到限制。UDF 不支持TRY…CATCH@ERRORRAISERROR。
-
用戶定義函數(shù)不能調(diào)用存儲(chǔ)過程,但可以調(diào)用擴(kuò)展存儲(chǔ)過程。
-
用戶定義的函數(shù)不能使用動(dòng)態(tài) SQL 或臨時(shí)表。允許使用表變量。
-
SET語句不允許在用戶定義的函數(shù)中使用。
-
不允許使用FOR XML子句。
-
用戶定義的函數(shù)可以嵌套;也就是說,一個(gè)用戶定義的函數(shù)可以調(diào)用另一個(gè)用戶定義的函數(shù)。嵌套級(jí)別在被調(diào)用函數(shù)開始執(zhí)行時(shí)遞增,在被調(diào)用函數(shù)完成執(zhí)行時(shí)遞減。用戶定義的函數(shù)最多可嵌套 32 個(gè)級(jí)別。超過最大嵌套級(jí)別會(huì)導(dǎo)致整個(gè)調(diào)用函數(shù)鏈?zhǔn)?。?duì)來自 Transact-SQL 用戶定義函數(shù)的托管代碼的任何引用都計(jì)為 32 級(jí)嵌套限制中的一個(gè)級(jí)別。從托管代碼中調(diào)用的方法不計(jì)入此限制。
-
以下服務(wù)代理語句不能包含在 Transact-SQL 用戶定義函數(shù)的定義中:BEGIN DIALOG CONVERSATION、END CONVERSATION、GET CONVERSATION GROUP、MOVE CONVERSATION、RECEIVE、SEND。
權(quán)限:
需要數(shù)據(jù)庫(kù)中的權(quán)限以及對(duì)在其中創(chuàng)建函數(shù)的架構(gòu)的權(quán)限。如果函數(shù)指定用戶定義類型,則需要CREATE FUNCTIONALTEREXECUTE該類型的權(quán)限。
2.2、標(biāo)量函數(shù)示例(標(biāo)量 UDF)
創(chuàng)建一個(gè)多語句標(biāo)量函數(shù)(標(biāo)量 UDF)。該函數(shù)采用一個(gè)輸入值 a 并返回單個(gè)數(shù)據(jù)值,即庫(kù)存中指定產(chǎn)品的聚合數(shù)量。
IF OBJECT_ID (N'dbo.ufnGetInventoryStock', N'FN') IS NOT NULL
DROP FUNCTION ufnGetInventoryStock;
GO
CREATE FUNCTION dbo.ufnGetInventoryStock(@ProductID int)
RETURNS int
AS
-- Returns the stock level for the product.
BEGIN
DECLARE @ret int;
SELECT @ret = SUM(p.Quantity)
FROM Production.ProductInventory p
WHERE p.ProductID = @ProductID
AND p.LocationID = '6';
IF (@ret IS NULL)
SET @ret = 0;
RETURN @ret;
END;
使用該函數(shù)返回介于 75 和 80 之間的產(chǎn)品的當(dāng)前庫(kù)存數(shù)量。
SELECT ProductModelID, Name, dbo.ufnGetInventoryStock(ProductID)AS CurrentSupply
FROM Production.Product
WHERE ProductModelID BETWEEN 75 and 80;
2.3、表值函數(shù)示例
2.3.1、內(nèi)聯(lián)表值函數(shù) (TVF)
創(chuàng)建一個(gè)內(nèi)聯(lián)表值函數(shù) (TVF)。該函數(shù)采用一個(gè)輸入?yún)?shù)、一個(gè)客戶(商店)ID,并返回列 、 和銷售到商店的每個(gè)產(chǎn)品的年初至今銷售額的匯總。
IF OBJECT_ID (N'Sales.ufn_SalesByStore', N'IF') IS NOT NULL
DROP FUNCTION Sales.ufn_SalesByStore;
GO
CREATE FUNCTION Sales.ufn_SalesByStore (@storeid int)
RETURNS TABLE
AS
RETURN
(
SELECT P.ProductID, P.Name, SUM(SD.LineTotal) AS 'Total'
FROM Production.Product AS P
JOIN Sales.SalesOrderDetail AS SD ON SD.ProductID = P.ProductID
JOIN Sales.SalesOrderHeader AS SH ON SH.SalesOrderID = SD.SalesOrderID
JOIN Sales.Customer AS C ON SH.CustomerID = C.CustomerID
WHERE C.StoreID = @storeid
GROUP BY P.ProductID, P.Name
);
調(diào)用該函數(shù)并指定客戶 ID 602。
SELECT * FROM Sales.ufn_SalesByStore (602);
2.3.2、多語句表值函數(shù) (MSTVF)
創(chuàng)建一個(gè)多語句表值函數(shù) (MSTVF)。該函數(shù)采用單個(gè)輸入?yún)?shù) an,并返回直接或間接向指定員工報(bào)告的所有員工的列表。然后調(diào)用該函數(shù),指定員工 ID 109。
IF OBJECT_ID (N'dbo.ufn_FindReports', N'TF') IS NOT NULL
DROP FUNCTION dbo.ufn_FindReports;
GO
CREATE FUNCTION dbo.ufn_FindReports (@InEmpID INTEGER)
RETURNS @retFindReports TABLE
(
EmployeeID int primary key NOT NULL,
FirstName nvarchar(255) NOT NULL,
LastName nvarchar(255) NOT NULL,
JobTitle nvarchar(50) NOT NULL,
RecursionLevel int NOT NULL
)
--Returns a result set that lists all the employees who report to the
--specific employee directly or indirectly.*/
AS
BEGIN
WITH EMP_cte(EmployeeID, OrganizationNode, FirstName, LastName, JobTitle, RecursionLevel) -- CTE name and columns
AS (
SELECT e.BusinessEntityID, e.OrganizationNode, p.FirstName, p.LastName, e.JobTitle, 0 -- Get the initial list of Employees for Manager n
FROM HumanResources.Employee e
INNER JOIN Person.Person p
ON p.BusinessEntityID = e.BusinessEntityID
WHERE e.BusinessEntityID = @InEmpID
UNION ALL
SELECT e.BusinessEntityID, e.OrganizationNode, p.FirstName, p.LastName, e.JobTitle, RecursionLevel + 1 -- Join recursive member to anchor
FROM HumanResources.Employee e
INNER JOIN EMP_cte
ON e.OrganizationNode.GetAncestor(1) = EMP_cte.OrganizationNode
INNER JOIN Person.Person p
ON p.BusinessEntityID = e.BusinessEntityID
)
-- copy the required columns to the result of the function
INSERT @retFindReports
SELECT EmployeeID, FirstName, LastName, JobTitle, RecursionLevel
FROM EMP_cte
RETURN
END;
GO
調(diào)用該函數(shù)并指定員工 ID 1。
SELECT EmployeeID, FirstName, LastName, JobTitle, RecursionLevel
FROM dbo.ufn_FindReports(1);
三、修改用戶定義的函數(shù)
修改用戶定義函數(shù)(如下所述)不會(huì)更改函數(shù)的權(quán)限,也不會(huì)影響任何依賴函數(shù)、存儲(chǔ)過程或觸發(fā)器。
ALTER 函數(shù)不能用于執(zhí)行以下任何操作:
-
將標(biāo)量值函數(shù)更改為表值函數(shù),反之亦然。
-
將內(nèi)聯(lián)函數(shù)更改為多語句函數(shù),反之亦然。
-
將事務(wù)處理 SQL 函數(shù)更改為 CLR 函數(shù),反之亦然。
權(quán)限:需要對(duì)函數(shù)或架構(gòu)的 ALTER 權(quán)限。如果函數(shù)指定用戶定義類型,則需要對(duì)該類型具有 EXECUTE 權(quán)限。
(1)更改標(biāo)量值函數(shù)。
-- Scalar-Valued Function
USE [AdventureWorks2012]
GO
ALTER FUNCTION [dbo].[ufnGetAccountingEndDate]()
RETURNS [datetime]
AS
BEGIN
RETURN DATEADD(millisecond, -2, CONVERT(datetime, '20040701', 112));
END;
(2)更改表值函數(shù)。
-- Table-Valued Function
USE [AdventureWorks2012]
GO
ALTER FUNCTION [dbo].[ufnGetContactInformation](@PersonID int)
RETURNS @retContactInformation TABLE
(
-- Columns returned by the function
[PersonID] int NOT NULL,
[FirstName] [nvarchar](50) NULL,
[LastName] [nvarchar](50) NULL,
[JobTitle] [nvarchar](50) NULL,
[BusinessEntityType] [nvarchar](50) NULL
)
AS
-- Returns the first name, last name, job title and business entity type for the specified contact.
-- Since a contact can serve multiple roles, more than one row may be returned.
BEGIN
IF @PersonID IS NOT NULL
BEGIN
IF EXISTS(SELECT * FROM [HumanResources].[Employee] e
WHERE e.[BusinessEntityID] = @PersonID)
INSERT INTO @retContactInformation
SELECT @PersonID, p.FirstName, p.LastName, e.[JobTitle], 'Employee'
FROM [HumanResources].[Employee] AS e
INNER JOIN [Person].[Person] p ON p.[BusinessEntityID] = e.[BusinessEntityID]
WHERE e.[BusinessEntityID] = @PersonID;
IF EXISTS(SELECT * FROM [Purchasing].[Vendor] AS v
INNER JOIN [Person].[BusinessEntityContact] bec ON bec.[BusinessEntityID] = v.[BusinessEntityID]
WHERE bec.[PersonID] = @PersonID)
INSERT INTO @retContactInformation
SELECT @PersonID, p.FirstName, p.LastName, ct.[Name], 'Vendor Contact'
FROM [Purchasing].[Vendor] AS v
INNER JOIN [Person].[BusinessEntityContact] bec ON bec.[BusinessEntityID] = v.[BusinessEntityID]
INNER JOIN [Person].ContactType ct ON ct.[ContactTypeID] = bec.[ContactTypeID]
INNER JOIN [Person].[Person] p ON p.[BusinessEntityID] = bec.[PersonID]
WHERE bec.[PersonID] = @PersonID;
IF EXISTS(SELECT * FROM [Sales].[Store] AS s
INNER JOIN [Person].[BusinessEntityContact] bec ON bec.[BusinessEntityID] = s.[BusinessEntityID]
WHERE bec.[PersonID] = @PersonID)
INSERT INTO @retContactInformation
SELECT @PersonID, p.FirstName, p.LastName, ct.[Name], 'Store Contact'
FROM [Sales].[Store] AS s
INNER JOIN [Person].[BusinessEntityContact] bec ON bec.[BusinessEntityID] = s.[BusinessEntityID]
INNER JOIN [Person].ContactType ct ON ct.[ContactTypeID] = bec.[ContactTypeID]
INNER JOIN [Person].[Person] p ON p.[BusinessEntityID] = bec.[PersonID]
WHERE bec.[PersonID] = @PersonID;
IF EXISTS(SELECT * FROM [Person].[Person] AS p
INNER JOIN [Sales].[Customer] AS c ON c.[PersonID] = p.[BusinessEntityID]
WHERE p.[BusinessEntityID] = @PersonID AND c.[StoreID] IS NULL)
INSERT INTO @retContactInformation
SELECT @PersonID, p.FirstName, p.LastName, NULL, 'Consumer'
FROM [Person].[Person] AS p
INNER JOIN [Sales].[Customer] AS c ON c.[PersonID] = p.[BusinessEntityID]
WHERE p.[BusinessEntityID] = @PersonID AND c.[StoreID] IS NULL;
END
RETURN;
END;
四、刪除用戶定義的函數(shù)
限制:
-
如果數(shù)據(jù)庫(kù)中存在引用此函數(shù)且是使用 SCHEMABINDING 創(chuàng)建的 Transact-SQL 函數(shù)或視圖,或者存在引用該函數(shù)的計(jì)算列、CHECK 約束或 DEFAULT 約束,則無法刪除該函數(shù)。
-
如果存在引用此函數(shù)并已編制索引的計(jì)算列,則無法刪除該函數(shù)。
權(quán)限:需要對(duì)函數(shù)所屬架構(gòu)的 ALTER 權(quán)限,或?qū)瘮?shù)具有 CONTROL 權(quán)限。
(1)創(chuàng)建一個(gè)用戶定義的函數(shù):
-- creates function called "Sales.ufn_SalesByStore"
USE AdventureWorks2012;
GO
CREATE FUNCTION Sales.ufn_SalesByStore (@storeid int)
RETURNS TABLE
AS
RETURN
(
SELECT P.ProductID, P.Name, SUM(SD.LineTotal) AS 'Total'
FROM Production.Product AS P
JOIN Sales.SalesOrderDetail AS SD ON SD.ProductID = P.ProductID
JOIN Sales.SalesOrderHeader AS SH ON SH.SalesOrderID = SD.SalesOrderID
JOIN Sales.Customer AS C ON SH.CustomerID = C.CustomerID
WHERE C.StoreID = @storeid
GROUP BY P.ProductID, P.Name
);
GO
(2)刪除在上面示例中創(chuàng)建的用戶定義函數(shù):
USE AdventureWorks2012;
GO
-- determines if function exists in database
IF OBJECT_ID (N'Sales.fn_SalesByStore', N'IF') IS NOT NULL
-- deletes function
DROP FUNCTION Sales.fn_SalesByStore;
GO
五、執(zhí)行用戶定義的函數(shù)
限制:
在 Transact-SQL 中,可以使用值或使用 @parameter_name=value 來提供參數(shù)。參數(shù)不是事務(wù)的一部分;因此,如果在稍后回滾的事務(wù)中更改了參數(shù),則該參數(shù)的值不會(huì)還原為其以前的值。返回給調(diào)用方的值始終是模塊返回時(shí)的值。
權(quán)限:
運(yùn)行 EXECUTE 語句不需要權(quán)限。但是,需要對(duì) EXECUTE 字符串中引用的安全對(duì)象具有權(quán)限。例如,如果字符串包含 INSERT 語句,則 EXECUTE 語句的調(diào)用方必須對(duì)目標(biāo)表具有 INSERT 權(quán)限。在遇到 EXECUTE 語句時(shí)檢查權(quán)限,即使 EXECUTE 語句包含在模塊中也是如此。
示例;
此示例使用大多數(shù)版本的 中可用的標(biāo)量值函數(shù)。該函數(shù)的目的是從給定整數(shù)返回銷售狀態(tài)的文本值。通過將整數(shù) 1 到 7 傳遞給參數(shù)來改變示例。
USE [AdventureWorks2016CTP3]
GO
-- Declare a variable to return the results of the function.
DECLARE @ret nvarchar(15);
-- Execute the function while passing a value to the @status parameter
EXEC @ret = dbo.ufnGetSalesOrderStatusText @Status = 5;
-- View the returned value. The Execute and Select statements must be executed at the same time.
SELECT N'Order Status: ' + @ret;
-- Result:
-- Order Status: Shipped
六、重命名用戶定義函數(shù)
限制:
-
函數(shù)名稱必須符合標(biāo)識(shí)符規(guī)則。
-
重命名用戶定義函數(shù)不會(huì)更改 sys.sql_modules 目錄視圖的定義列中相應(yīng)對(duì)象名稱的名稱。因此,建議不要重命名此對(duì)象類型。而是刪除存儲(chǔ)過程,然后使用其新名稱重新創(chuàng)建存儲(chǔ)過程。
-
更改用戶定義函數(shù)的名稱或定義可能會(huì)導(dǎo)致依賴對(duì)象在對(duì)象未更新以反映對(duì)函數(shù)所做的更改時(shí)失敗。
權(quán)限:
刪除函數(shù)需要對(duì)函數(shù)所屬架構(gòu)具有 ALTER 權(quán)限,或者需要對(duì)函數(shù)具有 CONTROL 權(quán)限。若要重新創(chuàng)建函數(shù),需要數(shù)據(jù)庫(kù)中的 CREATE FUNCTION 權(quán)限和要在其中創(chuàng)建函數(shù)的架構(gòu)的 ALTER 權(quán)限。
注意:若要使用 Transact-SQL 重命名用戶定義函數(shù),必須先刪除現(xiàn)有函數(shù),然后使用新名稱重新創(chuàng)建它。確保使用函數(shù)舊名稱的所有代碼和應(yīng)用程序現(xiàn)在都使用新名稱。
七、查看用戶定義的函數(shù)
獲取有關(guān) SQL Server 中用戶定義函數(shù)的定義或?qū)傩缘男畔ⅰ?赡苄枰榭春瘮?shù)的定義,以了解其數(shù)據(jù)是如何從源表派生的,或者查看函數(shù)定義的數(shù)據(jù)。
如果更改函數(shù)引用的對(duì)象的名稱,則必須修改該函數(shù),使其文本反映新名稱。因此,在重命名對(duì)象之前,請(qǐng)先顯示對(duì)象的依賴項(xiàng),以確定是否有任何函數(shù)受到建議更改的影響。
權(quán)限:
用于查找函數(shù)上的所有依賴項(xiàng)需要對(duì)數(shù)據(jù)庫(kù)具有 VIEW DEFINITION 權(quán)限,對(duì)數(shù)據(jù)庫(kù)具有 SELECT 權(quán)限。系統(tǒng)對(duì)象定義(如 OBJECT_DEFINITION 中返回的那些定義)是公開可見的。
7.1、獲取函數(shù)的定義和屬性
(1)獲取函數(shù)的定義和屬性。
USE AdventureWorks2012;
GO
-- Get the function name, definition, and relevant properties
SELECT sm.object_id,
OBJECT_NAME(sm.object_id) AS object_name,
o.type,
o.type_desc,
sm.definition,
sm.uses_ansi_nulls,
sm.uses_quoted_identifier,
sm.is_schema_bound,
sm.execute_as_principal_id
-- using the two system tables sys.sql_modules and sys.objects
FROM sys.sql_modules AS sm
JOIN sys.objects AS o ON sm.object_id = o.object_id
-- from the function 'dbo.ufnGetProductDealerPrice'
WHERE sm.object_id = OBJECT_ID('dbo.ufnGetProductDealerPrice')
ORDER BY o.type;
GO
(2)獲取示例函數(shù)的定義。文章來源:http://www.zghlxwxcb.cn/news/detail-411463.html
USE AdventureWorks2012;
GO
-- Get the definition of the function dbo.ufnGetProductDealerPrice
SELECT OBJECT_DEFINITION (OBJECT_ID('dbo.ufnGetProductDealerPrice')) AS ObjectDefinition;
GO
7.2、獲取函數(shù)的依賴項(xiàng)
USE AdventureWorks2012;
GO
-- Get all of the dependency information
SELECT OBJECT_NAME(sed.referencing_id) AS referencing_entity_name,
o.type_desc AS referencing_desciption,
COALESCE(COL_NAME(sed.referencing_id, sed.referencing_minor_id), '(n/a)') AS referencing_minor_id,
sed.referencing_class_desc, sed.referenced_class_desc,
sed.referenced_server_name, sed.referenced_database_name, sed.referenced_schema_name,
sed.referenced_entity_name,
COALESCE(COL_NAME(sed.referenced_id, sed.referenced_minor_id), '(n/a)') AS referenced_column_name,
sed.is_caller_dependent, sed.is_ambiguous
-- from the two system tables sys.sql_expression_dependencies and sys.object
FROM sys.sql_expression_dependencies AS sed
INNER JOIN sys.objects AS o ON sed.referencing_id = o.object_id
-- on the function dbo.ufnGetProductDealerPrice
WHERE sed.referencing_id = OBJECT_ID('dbo.ufnGetProductDealerPrice');
GO
文章來源地址http://www.zghlxwxcb.cn/news/detail-411463.html
到了這里,關(guān)于SQL Server用戶定義的函數(shù)(UDF)使用詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!