UDF:user-defined functions,用户自定义函数。
UDF是一个例程,它接受参数、执行操作并返回该操作的结果。根据定义,结果可以是标量值(单个)或表。
该函数一旦误用会产生潜在的性能问题。必须针对WHERE子句的每一行执行的任何函数,不管是用户定义的函数还是系统函数,都将减慢执行速度。
UDF主要有3种类型(Management Studio把内联表值函数与多语句表值函数放到了一个组中):
标量函数是返回一个具体值的函数。函数可以接收多个参数、执行计算然后返回一个值。返回值通过RETURN命令返回。用户定义的函数中的每个可能代码路径都以RETURN命令结尾。
标量函数可以运用于SQL Server中的任何表达式,甚至在CHECK约束的表达式中也可以使用(但不推荐这种用法)。
标题函数必须是确定性的,也就是说标量函数必须反复地为相同的输入参数返回相同的值。因此,如newid()函数和rand()函数不允许出现在标量函数中。不允许用户定义标量函数更新数据库、调用存储过程或调用DBCC命令,唯一的例外是可以更新表变量。用户定义函数不能返回BLOB(二进制大型对象)数据,如text、next、timestamp和image数据类型变量。也不能返回表变量可cursor数据类型。对于错误处理,UDF也不包含TRY...CATCH或RAISERROR。
UDF可以调用嵌套深度为32层以内的其他用户定义函数,或者递归调用自己到32层的深度。当然,这只是理论限制,嵌套函数会严重影响性能,应尽可能避免使用嵌套函数。
1 CREATE FUNCTION FunctionName (InputParameters) 2 RETURNS DataType 3 AS 4 BEGIN 5 Code; 6 RETURN Expression; 7 END;
InputParameters输入参数包含数据类型定义。参数可以设置默认值(Parameter = default ),需要注意的是在UDF中有默认值的参数并不能成为可选参数,为在调用函数时请求到默认值,需要把关键字DEFAULT传递到函数的默认值参数位置。
示例1:下面的UDF执行一个简单的数学计算,其中第二个参数带有默认值。
CREATE FUNCTION dbo.ufnCalculate (@Numer_a numeric(5,2), @Numer_b numeric(5,2) = 1.0) RETURNS numeric(5,2) AS BEGIN RETURN @Numer_a / @Numer_b ; END; GO select dbo.ufnCalculate(15.3 , 6.54), dbo.ufnCalculate(9.0 , DEFAULT); 结果: ------ ------ 2.38 9.00
示例2:计算并返回某个时间所在月份的天数。
CREATE FUNCTION [dbo].[GetMonthDay](@date datetime) RETURNS int AS BEGIN DECLARE @date1 datetime SELECT @date1 =Dateadd(MM,1,@date) RETURN day(Dateadd(DD,-day(@date1),@date1)) END;
在接受单值的表达式中,标量函数可用于任何地方。用户定义的标量函数必须通过一个最少有两部分的名称(所有者.函数名)来调用。
下面的脚本演示了在数据库的订单表中调用示例2中的函数及其返回值。
SELECT S.BIL_DD,dbo.GetMonthDay(BIL_DD) as DAYS_M FROM Orders S 结果 BIL_DD DAYS_M ------ ------ 2019-01-31 31 2019-02-15 28
与视图相似,内联表值函数也是为一个存储的SELECT语句封装。内联表值函数保留了视图的优点,还添加了一些参数。
创建方法
内联表值用户定义函数没有BEGIN / END主体。SELECT语句是作为一个虚拟数据表返回的:
CREATE FUNCTION FunctionName (InputParameters) RETURNS Table AS RETURN (Select Statement);
示例:下面的示例返回某个客户所订购产品的汇总情况。
CREATE FUNCTION dbo.ufnGetProductTotalByCust (@custNo varchar (10)) RETURNS Table AS RETURN( SELECT H.CUS_NO,B.PRD_NO,SUM(B.QTY) as TOTAL_PRD FROM TF_POS AS B --订单货品明细表 LEFT JOIN MF_POS AS H --订单客户信息表 ON H.OS_NO=B.OS_NO WHERE H.CUS_NO=@custNo GROUP BY H.CUS_NO,B.PRD_NO ); GO
调用内联表值函数
通过dbo.ufnGetProductTotalByCust查询客户代号为"CT060228" 的产品汇总数据,函数出现在SELECT语句的FROM部分:
SELECT PRD_NO,TOTAL_PRD FROM dbo.ufnGetProductTotalByCust(‘CT060228‘) ORDER BY PRD_NO DESC
返回结果(部分):
PRD_NO TOTAL_PRD ------------ ------------------------ 10910030006 5792.00000000 10910040003 10776.00000000 10912060014 11442.00000000 10913040009 9276.00000000 11410030028 900.00000000 ......
与视图的关系
与视图相比,内联表值函数的优势在于其可以使用参数。而视图不包含参数,而且在运行时想要限制结果需要把WHERE子句添加到调用视图的SELECT语句中来实现。
示图的调用示例,假设已经存在视图dbo.vwProductTotalByCust,调用视图时,在SELECT语句中添加了一个WHERE子句限制:
SELECT * FROM dbo.vwProductTotalByCust WHERE cus_no=‘CT060228‘
关联方法
原文:https://www.cnblogs.com/idreamo/p/10767923.html