与编程语言中的函数一样,SQL Server 用户定义的函数是接受参数的例程、执行作(例如复杂计算),并将该作的结果作为值返回。 返回值可以是单个标量值或结果集。
本主题内容
用户定义的函数优势
在 SQL Server 中使用用户定义的函数的好处包括:
它们允许模块化编程。
可以创建函数一次,将其存储在数据库中,并在程序中调用任意次数。 用户定义的函数可以独立于程序源代码进行修改。
它们允许更快地执行。
与存储过程类似,Transact-SQL 用户定义的函数通过缓存和重复使用计划来降低 Transact-SQL 代码的编译成本。 这意味着用户定义函数不需要重新分析和重新优化每次使用,因此执行时间要快得多。
CLR 函数在计算任务、字符串操作和业务逻辑方面,比 Transact-SQL 函数具有显著的性能优势。 Transact-SQL 函数更适用于数据访问密集型逻辑。
它们可以减少网络流量。
基于某些复杂约束进行数据筛选的操作,如果不能用单一的标量表达式来表示,那么可以通过函数来表达。 然后,该函数可以在 WHERE 子句中调用,以减少发送到客户端的数字或行。
注释
Transact-SQL 查询中的用户定义的函数只能在单个线程(串行执行计划)上执行。
函数类型
标量函数
用户定义的标量函数返回 RETURNS 子句中定义的类型的单个数据值。 对于内联标量函数,没有函数体;标量值是单个语句的结果。 对于多语句标量函数,函数体在BEGIN...END块中定义,并包含一系列Transact-SQL语句,这些语句返回单个值。 返回类型可以是除text、ntext、image、cursor和timestamp之外的任何数据类型。
Table-Valued 函数
用户定义的表值函数返回 table 数据类型。 对于内联表值函数,没有函数体;表是单个 SELECT 语句的结果集。
系统函数
SQL Server 提供了许多可用于执行各种作的系统函数。 无法修改它们。 有关详细信息,请参阅内置函数(Transact-SQL)、系统存储函数(Transact-SQL)和动态管理视图和函数(Transact-SQL)。
准则
Transact-SQL 导致语句终止并继续执行模块中下一个语句(如触发器或存储过程)的错误在函数内部以不同的方式处理。 在函数中,此类错误导致函数的执行停止。 这反过来会导致调用函数的语句被取消。
在 BEGIN...END 代码块中的语句不能产生任何副作用。 函数副作用是对具有函数外部范围的资源状态的任何永久更改,例如对数据库表的修改。 函数中的语句可以做出的唯一更改是对函数本地对象的更改,例如本地游标或变量。 对数据库表的修改、对非函数本地游标的操作、发送电子邮件、尝试修改目录以及生成返回给用户的结果集等操作,都是无法在函数中执行的例子。
注释
CREATE FUNCTION如果语句对发出语句时CREATE FUNCTION不存在的资源产生副作用,SQL Server执行该语句。 但是,SQL Server 在调用函数时不执行该函数。
实际执行的查询中指定的函数的次数可能因优化器生成的执行计划而异。 一个例子是子查询在 WHERE 子句中调用的函数。 执行子查询及其函数的次数因优化器选择的不同访问路径而异。
函数中的有效语句
函数中有效的语句类型包括:
DECLARE 语句可用于定义函数本地的数据变量和游标。
为函数局部对象的赋值,如使用 SET 为标量和表局部变量赋值。
函数中涉及的引用本地游标的操作,包括声明、打开、关闭和解除分配。 不允许向客户端返回数据的 FETCH 语句。 仅允许使用 INTO 子句将值赋给局部变量的 FETCH 语句。
除了 TRY...CATCH 语句之外的流控制语句。
SELECT 语句包含带有表达式的选择列表,这些表达式将值分配给函数的局部变量。
UPDATE、INSERT 和 DELETE 语句,这些语句修改函数的局部表变量。
执行调用扩展存储过程的语句。
内置系统函数
以下不确定的内置函数可用于 Transact-SQL 用户定义的函数。
| 当前时间戳 | @@MAX_CONNECTIONS |
| GET_TRANSMISSION_STATUS | @@包裹已接收 |
| GETDATE | @@PACK_SENT |
| 获取UTC日期 | @@PACKET_ERRORS |
| @@连接 | @@TIMETICKS |
| @@CPU_BUSY | @@TOTAL_ERRORS |
| @@DBTS | @@TOTAL_READ |
| @@IDLE | @@TOTAL_WRITE |
| @@IO_BUSY |
以下不确定的内置函数不能用于 Transact-SQL 用户定义的函数。
| NEWID | 兰德公司 (RAND Corporation) |
| NEWSEQUENTIALID | TEXTPTR |
有关确定性和非确定性内置系统函数的列表,请参阅 “确定性”和“不确定函数”。
Schema-Bound 函数
CREATE FUNCTION 支持 SCHEMABINDING 子句,该子句将函数绑定到它引用的任何对象的架构,例如表、视图和其他用户定义的函数。 尝试更改或删除架构绑定函数引用的任何对象失败。
必须满足这些条件,然后才能在以下项中 CREATE FUNCTION指定 SCHEMABINDING:
函数引用的所有视图和用户定义的函数都必须绑定到架构。
该函数引用的所有对象都必须与函数位于同一数据库中。 必须使用一段或两段名称对对象进行引用。
您必须对函数中引用的所有对象(表、视图和用户定义的函数)具有 REFERENCES 权限。
可使用 ALTER FUNCTION 删除架构绑定。 该 ALTER FUNCTION 语句应重新定义函数而不指定 WITH SCHEMABINDING。
指定参数
用户定义的函数采用零个或多个输入参数,并返回标量值或表。 函数最多可以有 1024 个输入参数。 如果函数的参数有默认值,则调用该函数时必须指定关键字 DEFAULT,才能获取默认值。 此行为不同于用户定义存储过程中的具有默认值的参数,其中省略该参数意味着使用默认值。 用户定义的函数不支持输出参数。
相关任务
| 任务说明 | 主题 |
| 介绍如何创建 Transact-SQL 用户定义函数。 | 创建用户定义的函数(数据库引擎) |
| 描述如何创建 CLR 函数。 | 创建 CLR 函数 |
| 介绍如何创建用户定义的聚合函数 | 创建用户定义的聚合 |
| 介绍如何修改 Transact-SQL 用户定义函数。 | 修改用户定义的函数 |
| 介绍如何删除用户定义的函数。 | 删除用户定义的函数 |
| 介绍如何执行用户定义的函数。 | 执行用户定义的函数 |
| 介绍如何重命名用户定义的函数 | 重命名用户定义的函数 |
| 介绍如何查看用户定义函数的定义。 | 查看用户定义的函数 |