确定性函数和不确定性函数
只要使用特定的输入值集并且数据库具有相同的状态,那么不管何时调用,确定性函数始终都会返回相同的结果。即使访问的数据库的状态不变,每次使用特定的输入值集调用非确定性函数都可能会返回不同的结果。
有多种用户定义函数的属性可通过对调用函数的计算列进行索引或通过引用函数的索引视图,确定 SQL Server 数据库引擎为函数的结果建立索引的功能。函数的确定性是一个属性。例如,如果一个视图引用了任何不确定性函数,则无法对该视图创建聚集索引。有关函数属性(包括函数确定性)的详细信息,请参阅用户定义函数的设计指导原则。
本主题介绍了内置系统函数的确定性,以及在包含对扩展存储过程的调用时对用户定义函数的确定性的影响。
内置函数的确定性
用户无法影响任何内置函数的确定性。每个内置函数都根据 SQL Server 实现该函数的方式而分为确定性函数或非确定性函数。
所有聚合和字符串内置函数都是确定性函数。有关这些函数的列表,请参阅聚合函数 (Transact-SQL)和字符串函数 (Transact-SQL)。
除聚合函数和字符串函数之外,内置函数类别中的下列内置函数也始终是确定性函数。
ABS |
DATEDIFF |
POWER |
ACOS |
DAY |
RADIANS |
ASIN |
DEGREES |
ROUND |
ATAN |
EXP |
SIGN |
ATN2 |
FLOOR |
SIN |
CEILING |
ISNULL |
SQUARE |
COALESCE |
ISNUMERIC |
SQRT |
COS |
LOG |
TAN |
COT |
LOG10 |
YEAR |
DATALENGTH |
MONTH |
|
DATEADD |
NULLIF |
|
下列函数并非始终是确定性函数,但是在以确定性方式指定后,可用于索引视图或计算列的索引。
函数 |
注释 |
---|---|
CAST |
除非与 datetime、smalldatetime 或 sql_variant 一起使用,否则为确定性函数。 |
CONVERT |
除非存在下列条件,否则为确定性函数:
|
CHECKSUM |
确定性函数,CHECKSUM(*) 除外。 |
ISDATE |
只有与 CONVERT 函数一起使用、指定 CONVERT 样式参数并且样式不等于 0、100、9 或 109 时,才是确定性函数。 |
RAND |
仅当指定 seed 参数时,RAND 才是确定性函数。 |
所有配置、游标、元数据、安全和系统统计函数都是非确定性函数。有关这些函数的列表,请参阅配置函数 (Transact-SQL)、游标函数 (Transact-SQL)、元数据函数 (Transact-SQL)、安全函数 (Transact-SQL)和系统统计函数 (Transact-SQL)。
其他类别中的下列内置函数始终为非确定性函数。
@@CONNECTIONS |
@@TOTAL_WRITE |
@@CPU_BUSY |
CURRENT_TIMESTAMP |
@@DBTS |
GETDATE |
@@IDLE |
GETUTCDATE |
@@IO_BUSY |
GET_TRANSMISSION_STATUS |
@@MAX_CONNECTIONS |
MIN_ACTIVE_ROWVERSION |
@@PACK_RECEIVED |
NEWID |
@@PACK_SENT |
NEWSEQUENTIALID |
@@PACKET_ERRORS |
PARSENAME |
@@TIMETICKS |
RAND |
@@TOTAL_ERRORS |
TEXTPTR |
@@TOTAL_READ |
从函数中调用扩展存储过程
由于扩展存储过程会对数据库产生副面影响,因此调用扩展存储过程的函数为不确定性函数。负面影响为对数据库全局状态的更改,如更新表、更新文件或网络等外部资源;例如,修改文件或发送电子邮件。从用户定义函数中执行扩展存储过程时,不应该依靠返回一致的结果集。建议不要使用对数据库产生负面影响的用户定义函数。
从函数内部调用扩展存储过程时,该扩展存储过程不能向客户端返回结果集。任何向客户端返回结果集的开放式数据服务 API 将产生返回代码 FAIL。
扩展存储过程可以连接回 SQL Server。但是,该过程不能与调用扩展存储过程的原始函数联接同一事务。
类似于从批处理或存储过程中调用,扩展存储过程在运行 SQL Server 的 Microsoft Windows 安全帐户的上下文中执行。扩展存储过程的所有者在授予其他用户执行该过程的权限时应该考虑此问题。