微软公司出品的SQL Server是企业数据库市场上的一个大家伙,但是,由于 SQL Server缺乏对用户定义函数(UDF)的支持而在其它数据库产品面前逊色不少。Oracle、DB2甚至微软自己开发的桌面级数据库Access都早已提供UDF多年,所以微软公司有必要在SQL
Server 2000产品中增加这一非常有用的功能。
采用UDF之后就可以更容易地适应定制应用程序的特殊要求。大多数开发人员会通过SELECT表达式列出数据表变量和UDF调用作为UDF的主要功能。其实UDF还有更大的作用:它们在增加功能性的同时还减少了工作量。
所有的函数,不论是系统内置还是用户定义的,通常都可以说是返回一个值或者完成某项任务的子程序。你把信息以参数的形式传递给函数,函数采用这些传递过来的值对表达式进行计算或者完成任务。简单地说,所谓函数就是易于返回和共享结果的自动化过程。
SQL Server提供了一些内置函数,比如GetDate、 DateAdd 和ObjectName等。这些内置函数很有用,但是你无论如何都无法修改它们的功能,这也正是为什么UDF具有如此强大性能和必要性的原因所在。
UDF可以让你针对特定应用程序问题提供解决方案。这些任务可以简单到计算一个值,也可能复杂到定义和实现数据表的约束。从技术上看,SQL Server
UDF都是经过封装的Transact-SQL(T-SQL)逻辑的子程序,你可以通过其他T-SQL代码调用这些子程序来返回单一的值或者数据表变量。
采用UDF主要有以下几条理由:
SQL Server 2000新采用了一种Table 数据类型,通过这种数据类型可以声明局部变量为table类型。table
类型只能通过UDF使用。
存储过程可以创建和移植数据表,但是数据表变量并不是物理上存在的表。假如你熟悉Access和ADO(ActiveX Data Object),你可以把数据表变量比拟为Recordset
对象。早期的SQL Server版本提供了临时的数据表,但是数据表变量的运行速度比临时表更快,除非你超越了它们的缓冲能力。
临时表分成两种类型:私有的private和全局的global。私有数据表只对创建表的连接可用。相反,全局临时表则对全体用户可用,但是,当最后一个用户退出数据表的时候全局临时表即被破坏了;这种行为是无法控制的。
数据表变量只能在函数有效范围内使用。换句话说,数据表变量只能由那些执行函数而且函数正处于使用状态的用户使用。函数的生存期控制着数据表变量的生存期。
通过SQL表达式执行UDF是SQL Server向前发展的一大步。你可以返回一个数据表变量并把数据传递给SELECT
(或者action关键词)表达式,形式如下:
SELECT * FROM user.udf_name()
SELECT *, user.udf_name() FROM user.table
同样的,你可以如下所示地连接UDF:
SELECT * FROM user.table WHERE user.table.column = user.udf_name.column
UDF也许会被看成存储过程,但它们两者实际上分别实现不同的功能。存储过程当然也是一种强大和灵活的工具,也具有等同于UDF的价值但它们是不同的。图A即列出了两者之间的差别。
图A
UDF无须费太大的精力就可以解决比较特殊的问题,但是它们的使用有一定的限制。最大的局限就是应用范围。和系统内置函数不同,各种数据库都可以使用内置函数,UDF则只能对在其中创建或者拷贝它们的数据库可用。此外,UDF还没有足够灵活到处理你需要它们完成的所有功能。特别是,UDF不能包含内置的、确定性的函数。为了了解确定和确定函数的基本信息你可以参看这个URL。
比方说,在UDF内采用GetDate() 会返回以下的错误:
Invalid use of 'getdate' within a function.
那是因为,非确定函数,比如GetDate,可以采用同样的参数返回不同的结果。 GetDate 有两个组件,实际的日期date和时间time。每次你调用该函数的时候,time组件就会改变。因为时间都是唯一的,所以你永远都不会返回完全一样的值。
比如说,以下的SQL可以在Query Analyzer中执行:
Select getdate()AS Date_One
Go
Select getdate() as Date_Two
即使是在同一文件中执行两个返回值也肯定不同:
2002-02-11 21:07:37.940
2002-02-11 21:07:37.950
可是,到目前为止,记住先前的定义也比确定函数是确定还是不确定要简单的多。现在,OBJECTPROPERTY 函数把这个过程进一步简化了。采用函数的IsDeterministic
属性如下:
SELECT OBJECTPROPERTY(OBJECT_ID('functionname'), 'IsDeterministic')
当函数是非确定函数的时候会返回0否则返回1。要记住这种特殊的属性IsDeterministic只能用于UDF。
你不能修改内置函数的确定性。相反,UDF在以下情况中是确定的: