确定性函数和非确定性函数

适用于: SQL Server Azure SQL 数据库 Azure SQL 托管实例

只要使用特定的输入值集并且数据库具有相同的状态,那么不管何时调用,确定性函数始终都会返回相同的结果。 即使访问的数据库的状态不变,每次使用特定的输入值集调用非确定性函数都可能会返回不同的结果。 例如,函数 AVG 对上述给定的限定条件始终返回相同的值,但返回当前 datetime 值的 GETDATE 函数始终会返回不同的结果。

有多个用户定义函数的属性,这些属性通过调用函数的计算列索引或通过引用函数的索引视图来确定 SQL Server 数据库引擎为函数的结果建立索引的功能。 函数的确定性是一个属性。 例如,假设某个视图引用了任何非确定性函数,则无法对该视图创建聚集索引。 有关函数属性(包括函数确定性)的详细信息,请参阅 用户定义函数

确定性函数必须是架构绑定的。 创建确定性函数时,请使用 SCHEMABINDING 子句。

本文介绍了内置系统函数的确定性,以及在包含对扩展存储过程的调用时对用户定义函数的确定性的影响。

确定函数是否为确定性的

可以通过查询函数的 is_deterministic 对象属性来检查函数是否为确定性的。 下面的示例确定函数 Sales.CalculateSalesTax 是否为确定性的。

SELECT OBJECTPROPERTY(OBJECT_ID('Sales.CalculateSalesTax'), 'IsDeterministic');

内置函数的确定性

用户无法影响任何内置函数的确定性。 每个内置函数都根据 SQL Server 实现该函数的方式而分为确定性函数或非确定性函数。 例如,在查询中指定 ORDER BY 子句不会更改查询中使用的函数的决定机制。

FORMAT 外,所有字符串内置函数都是确定性的。 有关这些函数的列表,请参阅 字符串函数 (Transact-SQL)

内置函数类别中除字符串函数以外的下列内置函数始终具有确定性。

  • ABS
  • ACOS
  • ASIN
  • ATAN
  • ATN2
  • CEILING
  • COALESCE
  • COS
  • COT
  • DATALENGTH
  • DATEADD
  • DATEDIFF
  • DAY
  • DEGREES
  • EXP
  • FLOOR
  • ISNULL
  • ISNUMERIC
  • LOG
  • LOG10
  • MONTH
  • NULLIF
  • POWER
  • RADIANS
  • ROUND
  • SIGN
  • SIN
  • SQRT
  • SQUARE
  • TAN
  • YEAR

下列函数并非始终是确定性函数,但是在以确定性方式指定后,可用于索引视图或计算列的索引。

函数 注释
所有聚合函数 除非用 OVER 和 ORDER BY 子句指定聚合函数,否则所有聚合函数都具有确定性。 有关这些函数的列表,请参阅 聚合函数 (Transact-SQL)
CAST 除非与 datetimesmalldatetimesql_variant一起使用,否则其他时候都是确定性的。
CONVERT 除非存在下列条件,否则为确定性函数:

源类型是 sql_variant

目标类型是 sql_variant ,其源类型不是确定性的。

源类型或目标类型是 datetimesmalldatetime,其他源类型或目标类型是字符串,并且指定了不确定的样式。 若要为确定样式,则样式参数必须是常量。 此外,除了样式 20 和 21,小于或等于 100 的样式都具有不确定性。 大于 100 的样式具有确定性,但样式 106、107、109 和 113 除外。
CHECKSUM 确定性,CHECKSUM(*) 除外。
ISDATE 只有与 CONVERT 函数一起使用、指定 CONVERT 样式参数并且样式不等于 0、100、9 或 109 时,才是确定性函数。
RAND 仅当指定 seed 参数时,RAND 才是确定性函数。

所有配置、游标、元数据、安全和系统统计函数都是非确定性函数。 可以看到这些函数的列表

其他类别中的下列内置函数始终为非确定性函数。

  • @@CONNECTIONS
  • @@CPU_BUSY
  • @@DBTS
  • @@IDLE
  • @@IO_BUSY
  • @@MAX_CONNECTIONS
  • @@PACKET_ERRORS
  • @@PACK_RECEIVED
  • @@PACK_SENT
  • @@TIMETICKS
  • @@TOTAL_ERRORS
  • @@TOTAL_READ
  • @@TOTAL_WRITE
  • AT TIME ZONE
  • CUME_DIST
  • CURRENT_TIMESTAMP
  • DENSE_RANK
  • FIRST_VALUE
  • FORMAT
  • GETDATE
  • GETUTCDATE
  • GET_TRANSMISSION_STATUS
  • LAG
  • LAST_VALUE
  • LEAD
  • MIN_ACTIVE_ROWVERSION
  • NEWID
  • NEWSEQUENTIALID
  • NEXT VALUE FOR
  • NTILE
  • PARSENAME
  • PERCENTILE_CONT
  • PERCENTILE_DISC
  • PERCENT_RANK
  • RAND
  • RANK
  • ROW_NUMBER
  • TEXTPTR

从函数中调用扩展存储过程

由于扩展存储过程会对数据库产生副面影响,因此调用扩展存储过程的函数为不确定性函数。 负面影响为对数据库全局状态的更改,如更新表、更新文件或网络等外部资源;例如,修改文件或发送电子邮件。 从用户定义函数中执行扩展存储过程时,不要依赖于返回一致的结果集。 建议不要使用对数据库产生负面影响的用户定义函数。

从函数内部调用扩展存储过程时,该扩展存储过程不能向客户端返回结果集。 任何向客户端返回结果集的开放式数据服务 API 都具有返回代码 FAIL。

扩展存储过程可以连接回 SQL Server。 但是,该过程不能与调用扩展存储过程的原始函数联接同一事务。

与通过批处理或存储过程进行调用相似,扩展存储过程在运行 SQL Server 的 Microsoft Windows 安全帐户的上下文中执行。 扩展存储过程的所有者在授予其他用户执行该过程的权限时,应该考虑此安全性上下文的权限。

另请参阅