【问题标题】:Creating Nondeterministic functions in SQL Server using RAND()使用 RAND() 在 SQL Server 中创建非确定性函数
【发布时间】:2011-04-01 16:20:03
【问题描述】:

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

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

【问题讨论】:

    标签: sql function non-deterministic


    【解决方案1】:

    使用视图可能对您有用。
    来自Returning Random Numbers from a select statement

    CREATE VIEW vRandNumber
    AS
    SELECT RAND() as RandNumber
    

    视图是必要的,因为正如您已经发现的那样,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
    

    【讨论】:

    • +1 用于查看技巧。我也只记得那件事。但这不是因为决定论。函数中允许使用getdate()。显然,该函数不能用于需要确定性函数的地方,例如持久计算列。这是因为副作用。引发的错误是“在函数中无效使用副作用运算符 'rand'。”
    • 谢谢!我听说这样做是为了解决 NEWID() 函数,但没有意识到它也适用于 RAND()。
    【解决方案2】:

    因为它有副作用。

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

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

    【讨论】:

    • 啊,我明白了!我没有考虑最后一个随机数的内部存储。我可以看到这如何将它与其他非确定性函数区分开来。谢谢!
    • 查看sqlfascination.com/tag/randomstring 它会告诉您具体的操作方法。
    【解决方案3】:

    我发现这个solution 没有创建视图:

    基本上:

    代替

    SET @R = Rand()
    

    使用

    SET @R = ABS(CHECKSUM(PWDENCRYPT(N''))) / 2147483647.0
    

    就我而言,我想要一个介于 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))
    

    如需完整说明:Using (Or Simulating) Rand() In A T-Sql User-Defined Function

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多