背景:                 
[本书目录] [图书首页] [本书讨论区]  
链接地址:http://www.17xie.com/read-39361.html    注册17xie 一起来写书 实现您的出书梦想!

2.4  逐行调用UDF

不确定性函数是这样一种函数,当用相同的输入多次调用它时,它不保证返回相同的输出。当你在查询中调用内置的不确定性函数时(比如RAND和GETDATE),这些函数在整个查询中只被调用一次,而不是每行都调用。唯一的例外是NEWID函数,它生成一个全球唯一的标识符(GUID)。NEWID是唯一的每行都调用的内置不确定性函数。

为演示不确定性函数的这种行为,运行下面的代码,它将查询Northwind数据库中的Orders表,并调用RAND、GETDATE 和 NEWID,生成的输出以简化形式显示在表6-11中。

USE Northwind;

SELECT RAND() AS rnd, GETDATE() AS dt, NEWID() AS guid, OrderID AS oid

FROM dbo.Orders;

表6-11  调用不确定性函数的查询输出 (被简化)

rnd

dt

guid

oid

0.23575580157313

2005-12-19 14:18:00.157

10249

0.23575580157313

2005-12-19 14:18:00.157

10251

0.23575580157313

2005-12-19 14:18:00.157

10258

0.23575580157313

2005-12-19 14:18:00.157

10260

0.23575580157313

2005-12-19 14:18:00.157

10265

0.23575580157313

2005-12-19 14:18:00.157

10267

0.23575580157313

2005-12-19 14:18:00.157

10269

0.23575580157313

2005-12-19 14:18:00.157

10270

0.23575580157313

2005-12-19 14:18:00.157

10274

0.23575580157313

2005-12-19 14:18:00.157

10275

你会看到RAND 和 GETDATE在整个查询中只被调用了一次,它们的结果被复制到所有行。而NEWID每行都被调用,每行都生成不同的值。

如果为每一行调用RAND函数。你可能已经想到从UDF中调用RAND并在外部查询中调用UDF,因为UDF是每行都调用的。下面的代码尝试创建名为fn_rand的UDF。

IF OBJECT_ID('dbo.fn_rand') IS NOT NULL

  DROP FUNCTION dbo.fn_rand;

GO

CREATE FUNCTION dbo.fn_rand() RETURNS FLOAT

AS

BEGIN

  RETURN RAND();

END

GO

然而,尝试将失败并产生下面的错误。

Msg 443, Level 16, State 1, Procedure fn_rand, Line 6

Invalid use of side-effecting or time-dependent operator in 'rand' within a function.

这个错误表示函数不允许产生副作用,RAND函数可以改变内部状态。

不过有一个后门可以让你在UDF中显式地调用RAND。创建一个视图,该视图调用RAND,然后在UDF中查询该视图,就像这样:

IF OBJECT_ID('dbo.fn_rand') IS NOT NULL

  DROP FUNCTION dbo.fn_rand;

GO

IF OBJECT_ID('dbo.VRand') IS NOT NULL

  DROP VIEW dbo.VRand;

GO

CREATE VIEW dbo.VRand AS SELECT RAND() AS r;

GO

CREATE FUNCTION dbo.fn_rand() RETURNS FLOAT

AS

BEGIN

  RETURN (SELECT r FROM dbo.VRand);

END

GO

你可以在查询Orders时调用fn_rand UDF以测试该函数,它产生的输出以简化形式显示在表6-12中。

SELECT dbo.fn_rand() AS rnd, OrderID AS oid FROM dbo.Orders;

表6-12  调用fn_rand UDF 的查询的输出(被简化)

rnd

oid

0.126413837261193

10248

0.222567782284458

10249

0.475723707976473

10250

0.57880518253848

10251

0.169390263927576

10252

0.337301740768919

10253

0.489646055111808

10254

0.826464402198423

10255

0.232679419042244

10256

0.152765690787598

10257

SQL Server 2000不允许在UDF中调用不确定函数。SQL Server 2005检查UDF的属性以区分它是否会产生副作用,从这一点来看,SQL Server 2005更宽容些。例如,在SQL Server 2000中你不能在UDF中调用GETDATE函数,但SQL Server 2005中就可以:

IF OBJECT_ID('dbo.fn_getdate') IS NOT NULL

  DROP FUNCTION dbo.fn_getdate;

GO

CREATE FUNCTION dbo.fn_getdate() RETURNS DATETIME

AS

BEGIN

  RETURN GETDATE();

END

GO

When you're done, run the following code for cleanup:

IF OBJECT_ID('dbo.fn_rand') IS NOT NULL

  DROP FUNCTION dbo.fn_rand;

GO

IF OBJECT_ID('dbo.VRand') IS NOT NULL

  DROP VIEW dbo.VRand;

GO

IF OBJECT_ID('dbo.fn_getdate') IS NOT NULL

  DROP FUNCTION dbo.fn_getdate;

GO


字数:2997    最后更新:8个月以前 [03-18 15:26]happyskynet 修改
本页编辑者:happyskynet  
[前一页]:2.3 表值UDF  [后一页]:2.5 结论
[在本页中加入书签] [收藏本书] [推荐本书]
  17xie论坛 > 本书讨论区 > 本页评论   (共0条)
发表评论

用户名称 匿名发表
评论内容
验证码

关于我们 | 版权声明 | 免责声明 | 诚聘英才 | 联系我们 | 合作伙伴 | 友情链接 | 广告合作 | 提交意见
Copyright © 2007 17xie.com 互联网协同写书平台 京ICP备08002671号