用户定义的函数

原创 2008年04月28日 17:14:00
<script type="text/javascript"><!-- google_ad_client = "pub-2947489232296736"; /* 728x15, 创建于 08-4-23MSDN */ google_ad_slot = "3624277373"; google_ad_width = 728; google_ad_height = 15; //--> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"><!-- google_ad_client = "pub-2947489232296736"; /* 160x600, 创建于 08-4-23MSDN */ google_ad_slot = "4367022601"; google_ad_width = 160; google_ad_height = 600; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

户定义函数(UDF)是准备好的代码片段,它可以接受参数,处理逻辑,然后返回某些数据。根据SQLServerBooksOnline,SQLServer™2000中的UDF可以接受从0到1024的任意个数的参数,不过我必须承认,我还未尝试将1024个参数传递到UDF中。UDF的另一个关键特征是返回一个值。取决于UDF的类型,调用例程可以使用这个值来继续处理它的数据。因此,如果UDF返回单一值(标量值),调用例程就可以在任何能够使用标准变量或文字值的地方使用这个值。如果UDF返回一个行集,则调用例程可以循环访问该行集,联接到该行集,或简单地从该行集中选择列。

虽然现在大多数语言已经暂时支持函数,但只有SQLServer2000引入了UDF。存储过程和视图在SQLServer中可用的时间远早于UDF,但这些对象中的每一个在SQLServer开发中都有自己适当的位置。存储过程可以很好地用于处理复杂的SQL逻辑、保证和控制对数据的访问,以及将行集返回到调用例程,无论此例程是基于®的程序,还是另一个Transact-SQL(T-SQL)批处理文件。与视图不同,存储过程是已编译的,这使得它们成为用来表示和处理频繁运行的SQL语句的理想候选者。视图可以很好地用于控制对数据的访问,但它们的控制方式与存储过程不同。视图仅限于生成该视图的基础SELECT语句中的某些列和行。因而视图常用于表示常用的SELECT语句,该语句可以联接多个表、使用WHERE子句,以及公开特定的列。在联接到其他表和视图的SQL语句的FROM子句中经常会发现视图。

在其核心部分,UDF既类似于视图,也类似于存储过程。像视图一样,UDF可以返回一个行集,该行集可用于JOIN中。因此,当UDF返回一个行集并接受参数时,它像一个您可以联接到的存储过程、或者一个参数化的视图。但是,正如我将演示的,UDF可以做到这一点,甚至更多。

有两种主要的UDF类型:返回标量值的UDF和返回表值的UDF。在表值UDF中,您将找到返回内联表和多语句表的UDF(请参见图1)。在以下部分中,我将对每种类型都加以关注。

标量UDF

返回标量值的UDF最类似于许多编程语言所引用的作为函数的内容。它们返回由标量数据类型(例如,integer、varchar(n)、char(n)、money、datetime、bit,等等)组成的单一值。如果用户定义的数据类型(UDDT)基于标量数据类型,UDF也可以返回这些数据类型。使用返回内联或多语句表的UDF,可以通过表数据类型返回行集。然而,并非所有的数据类型都可以从UDF中返回。例如,UDF无法返回下列数据类型中任何一个的值:text、ntext、image、cursor、或timestamp。

返回标量数据类型的UDF可以用于多种情况,以使代码具有更好的可维护性、可重用性和更少的复杂性。当T-SQL代码的相同段在几个地方(可能由几个存储过程和批SQL语句)使用时,这会非常有用。例如,假定一个应用程序中的几个部分都需要查找产品是否必须重新订购。在每个需要此操作的地方,代码可以检查重新订购等级,并将它与库存量加订购量的和相比较。然而,因为这个代码在几个地方用到,所以可以改为使用UDF以减少代码块,并使得万一需要更改时维护函数更加容易。这样的UDF可能看起来像图2中的代码,并可以使用以下SQL语句进行调用:

SELECTProductID,ReorderLevel,UnitsInStock,UnitsOnOrder,dbo.fnNeedToReorder(ReorderLevel,UnitsInStock,UnitsOnOrder)ASsNeedToReorderFROMProducts

图2中,fnNeedToReorderUDF执行计算并返回适当的值。这本来可以通过CASE语句在SELECT子句内完成,但如果改为使用UDF,代码就会简洁得多。而且更容易传播到其他可能需要相同逻辑的地方。假定一个应用程序中有几个部分需要确定是否要重新订购产品,那么图2中的UDF确实变得有价值,因为它使得当逻辑改变时应用程序更容易维护。例如,重新订购已经终止的产品并不是很有意义。因此,通过更改UDF以说明这个业务规则,可以在一个地方更改此逻辑(请参见图3)并使用下列代码运行:

SELECTProductID,ReorderLevel,UnitsInStock,UnitsOnOrder,dbo.fnNeedToReorder(ReorderLevel,UnitsInStock,UnitsOnOrder,Discontinued)ASsNeedToReorderFROMProducts1 <script type="text/javascript"><!-- google_ad_client = "pub-2947489232296736"; /* 728x15, 创建于 08-4-23MSDN */ google_ad_slot = "3624277373"; google_ad_width = 728; google_ad_height = 15; //--> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"><!-- google_ad_client = "pub-2947489232296736"; /* 160x600, 创建于 08-4-23MSDN */ google_ad_slot = "4367022601"; google_ad_width = 160; google_ad_height = 600; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
收藏助手
不良信息举报
您举报文章:用户定义的函数
举报原因:
原因补充:

(最多只允许输入30个字)