使用RAND()在SQL Server中创建非确定性函数

使用RAND()在SQL Server中创建非确定性函数,sql,function,non-deterministic,Sql,Function,Non Deterministic,搜索和阅读文档后,很明显,您可以在SQL Server中编写用户定义的函数,这些函数根据主体中使用的内置函数标记为确定性函数或非确定性函数 RAND()列在非确定性函数下(请参阅)。那么为什么我不能在函数中使用它呢?因为它有副作用 函数中不允许使用具有副作用的构造。它的副作用是更改一些内部状态,以跟踪最后发出的rand()值 我认为您可以通过将其包含在视图定义中,然后从视图中进行选择来绕过它。使用视图可能适合您。 从 该视图是必需的,因为正如您已经发现的那样,UDF不能使用rand()函数,因为

搜索和阅读文档后,很明显,您可以在SQL Server中编写用户定义的函数,这些函数根据主体中使用的内置函数标记为确定性函数或非确定性函数


RAND()列在非确定性函数下(请参阅)。那么为什么我不能在函数中使用它呢?

因为它有副作用

函数中不允许使用具有副作用的构造。它的副作用是更改一些内部状态,以跟踪最后发出的
rand()


我认为您可以通过将其包含在视图定义中,然后从视图中进行选择来绕过它。

使用视图可能适合您。

该视图是必需的,因为正如您已经发现的那样,UDF不能使用rand()函数,因为这会使函数不具有确定性。您可以使用视图欺骗UDF接受随机数

CREATE FUNCTION RandNumber()
RETURNS float
AS
  BEGIN
  RETURN (SELECT RandNumber FROM vRandNumber)
  END
最后,您可以在任何SELECT中使用此函数,现在每行返回0到1之间的随机数:

SELECT dbo.RandNumber(), *
FROM Northwind..Customers
我发现这无法创建视图:

基本上:

而不是

SET @R = Rand()
使用

在我的例子中,我想要一个介于1和10之间的数字:

ROUND(((10 - 1 -1) * ( ABS(CHECKSUM(PWDENCRYPT(N''))) / 2147483647.0) + 1), 0))

ROUND(((@max - @lower -1) * ( ABS(CHECKSUM(PWDENCRYPT(N''))) / 2147483647.0) + @lower), 0))

如果您需要完整的解释:

+1查看技巧。我还记得那件事。但这并不是因为决定论<函数中允许使用code>getdate()。显然,该函数不能用于需要确定性函数(如持久化计算列)的情况。这是因为副作用。引发的错误是“在函数中无效使用有副作用的运算符“rand”。谢谢!我听说过这样做是为了解决NEWID()函数的问题,但没想到它也适用于RAND()。啊,我现在明白了!我没有考虑最后一个随机数的内部存储。我可以看出这是如何将它与其他非确定性函数区分开来的。谢谢看看吧,它告诉你如何做到这一点。
SET @R = ABS(CHECKSUM(PWDENCRYPT(N''))) / 2147483647.0
ROUND(((10 - 1 -1) * ( ABS(CHECKSUM(PWDENCRYPT(N''))) / 2147483647.0) + 1), 0))

ROUND(((@max - @lower -1) * ( ABS(CHECKSUM(PWDENCRYPT(N''))) / 2147483647.0) + @lower), 0))