用户定义的函数

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例Microsoft Fabric 中的 SQL 分析终结点Microsoft Fabric 中的仓库

与编程语言中的函数类似,SQL Server 用户定义函数是接受参数、执行操作(例如复杂计算),并将操作结果以值的形式返回的例程。 返回值可以是单个标量值或结果集。

用户定义函数的优点

为什么使用用户定义函数 (UDF)?

  • 模块化编程。 只需创建一次函数并将其存储在数据库中,以后便可以在程序中调用任意次。 用户定义函数可以独立于程序源代码进行修改。

  • 执行速度更快。 与存储过程相似,Transact-SQL 用户定义函数通过缓存计划并在重复执行时重用它来降低 Transact-SQL 代码的编译开销。 这意味着每次使用用户定义函数时均无需重新解析和重新优化,从而缩短了执行时间。

    和用于计算任务、字符串操作和业务逻辑的 Transact-SQL 函数相比,CLR 函数具有显著的性能优势。 Transact-SQL 函数更适用于数据访问密集型逻辑。

  • 减少网络流量。 基于某种无法用单一标量的表达式表示的复杂约束来过滤数据的操作,可以表示为函数。 然后,此函数便可以在 WHERE 子句中调用,以减少发送至客户端的行数。

重要

查询中的 Transact-SQL UDF 只能针对单个线程执行(串行执行计划)。 因此,使用 UDF 会阻止并行查询处理。 有关并行查询处理的详细信息,请参阅查询处理体系结构指南

函数类型

标量函数

用户定义标量函数返回在 RETURNS 子句中定义的类型的单个数据值。 对于内联标量函数,返回的标量值是单个语句的结果。 对于多语句标量函数,函数体可以包含一系列返回单个值的 Transact-SQL 语句。 返回类型可以是除 textntextimagecursortimestamp外的任何数据类型。 例如,请参阅创建用户定义函数(数据库引擎)

表值函数

用户定义表值函数 (TVF) 返回 table 数据类型。 对于内联表值函数,没有函数主体;表是单个 SELECT 语句的结果集。 例如,请参阅创建用户定义函数(数据库引擎)

系统函数

SQL Server 提供了许多系统函数,可用于执行各种操作。 无法修改这些函数。 有关详细信息,请参阅内置函数 (Transact-SQL)系统存储函数 (Transact-SQL)动态管理视图和函数 (Transact-SQL)

指南

在函数中,将会区别处理导致语句被取消并继续执行模块(如触发器或存储过程)中的下一个语句的 Transact-SQL 错误。 在函数中,上述错误会导致停止执行函数。 接下来该操作导致取消调用该函数的语句。

BEGIN...END 块中的语句不能有任何副作用。 函数副作用是指对具有函数外作用域(例如数据库表的修改)的资源状态的任何永久性更改。 函数中的语句唯一能做的更改是对函数上的局部对象(如局部游标或局部变量)的更改。 不能在函数中执行的操作包括:对数据库表的修改,对不在函数上的局部游标进行操作,发送电子邮件,尝试修改目录,以及生成返回至用户的结果集。

如果 CREATE FUNCTION 语句对在发出 CREATE FUNCTION 语句时不存在的资源产生副作用,SQL Server 将执行该语句。 但在调用函数时,SQL Server 不执行此函数。

在查询中指定的函数的执行次数在优化器生成的执行计划间可能不同。 示例为 WHERE 子句中的子查询调用的函数。 子查询及其函数执行的次数会因优化器选择的访问路径的不同而异。

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

有关用户定义函数的详细信息和性能注意事项,请参阅创建用户定义函数(数据库引擎)

函数中的有效语句

函数中的有效语句的类型包括:

  • DECLARE 语句,该语句可用于定义函数局部的数据变量和游标。

  • 为函数局部对象的赋值,如使用 SET 为标量和表局部变量赋值。

  • 游标操作,该操作引用在函数中声明、打开、关闭和释放的局部游标。 不允许使用 FETCH 语句将数据返回到客户端。 仅允许使用 FETCH 语句通过 INTO 子句给局部变量赋值。

  • TRY...CATCH 语句以外的控制流语句。

  • SELECT 语句,该语句包含具有为函数的局部变量赋值的表达式的选择列表。

  • UPDATEINSERTDELETE 语句,这些语句修改函数的局部表变量。

  • EXECUTE 语句,该语句调用扩展存储过程。

内置系统函数

下列具有不确定性的内置函数可以在 Transact-SQL 用户定义函数中使用。

  • CURRENT_TIMESTAMP
  • GET_TRANSMISSION_STATUS
  • GETDATE
  • GETUTCDATE
  • @@CONNECTIONS
  • @@CPU_BUSY
  • @@DBTS
  • @@IDLE
  • @@IO_BUSY
  • @@MAX_CONNECTIONS
  • @@PACK_RECEIVED
  • @@PACK_SENT
  • @@PACKET_ERRORS
  • @@TIMETICKS
  • @@TOTAL_ERRORS
  • @@TOTAL_READ
  • @@TOTAL_WRITE

下列不确定性内置函数不能在 Transact-SQL 用户定义函数中使用。

  • NEWID
  • NEWSEQUENTIALID
  • RAND
  • TEXTPTR

有关确定性和不确定性的内置系统函数的列表,请参阅确定性和不确定性的函数

绑定到架构的函数

CREATE FUNCTION 支持 SCHEMABINDING 子句,后者可将函数绑定到它引用的任何对象(如表、视图和其他用户定义函数)的架构。 尝试更改或删除绑定到架构的函数所引用的任何对象失败。

必须满足以下条件才能在 CREATE FUNCTION 中指定 SCHEMABINDING

  • 该函数引用的所有视图和用户定义函数必须是绑定到架构的视图和函数。

  • 该函数引用的所有对象必须与该函数位于同一数据库中。 必须使用由一部分或两部分构成的名称来引用对象。

  • 必须具有该函数中引用的所有对象(表、视图和用户定义函数)的 REFERENCES 权限。

可使用 ALTER FUNCTION 删除架构绑定。 ALTER FUNCTION 语句会在不指定 WITH SCHEMABINDING 的情况下重新定义函数。

指定参数

用户定义函数采用零个或多个输入参数并返回标量值或表。 一个函数最多可以有 1024 个输入参数。 如果函数的参数有默认值,则调用该函数时必须指定 DEFAULT 关键字,才能获取默认值。 此行为与在用户定义存储过程中具有默认值的参数不同,在后一种情况下,忽略参数同样意味着使用默认值。 用户定义函数不支持输出参数。

另请参阅