【发布时间】:2016-04-17 17:13:09
【问题描述】:
SQL Server 中的标量值、表值和聚合函数有什么区别?从查询中调用它们是否需要不同的方法,还是我们以相同的方式调用它们?
【问题讨论】:
-
select get_turnover()和select * from get_all_orders()有什么区别
标签: sql-server function tsql aggregate-functions sqlclr
SQL Server 中的标量值、表值和聚合函数有什么区别?从查询中调用它们是否需要不同的方法,还是我们以相同的方式调用它们?
【问题讨论】:
select get_turnover()和select * from get_all_orders()有什么区别
标签: sql-server function tsql aggregate-functions sqlclr
标量函数返回单个值。它甚至可能与您数据库中的表无关。
表值函数返回表中满足选择条件的行的指定列。
聚合值函数返回跨表行的计算——例如求和值。
【讨论】:
标量函数(有时称为用户定义函数/UDF)返回单个值作为返回值,而不是作为结果集,并且可以在查询或SET 语句中的大多数地方使用,除了FROM 子句(可能还有其他地方?)。此外,可以通过EXEC 调用标量函数,就像存储过程一样,尽管使用此功能的场合并不多(有关此功能的更多详细信息,请参阅我在 DBA.StackExchange 上对以下问题的回答: Why scalar valued functions need execute permission rather than select?)。这些可以在 T-SQL 和 SQLCLR 中创建。
T-SQL (UDF):
SQLCLR (UDF):这些标量函数通常也针对返回或扫描的每一行运行,但与 T-SQL UDF 相比有两个重要优势:
IsDeterministic = true,则返回值可以常量折叠到执行计划中。在这种情况下,该函数不会按每一行运行。表值函数 (TVF) 返回结果集,可用于任何查询的FROM 子句、JOIN 或CROSS APPLY / OUTER APPLY,但与简单视图不同,不能作为目标任何 DML 语句 (INSERT / UPDATE / DELETE)。这些也可以在 T-SQL 和 SQLCLR 中创建。
T-SQL MultiStatement (TVF):这些 TVF,顾名思义,可以有多个语句,类似于存储过程。他们将返回的任何结果都存储在表变量中并在最后返回;意思是,在函数完成处理之前什么都不返回。报告给查询优化器(影响执行计划)的估计返回行数取决于 SQL Server 的版本:
T-SQL 内联 (iTVF): 这些 TVF 只能是单个语句,并且该语句是完整的查询,就像视图一样。事实上,内联 TVF 本质上是一个视图,它接受用于查询的输入参数。它们也不缓存自己的查询计划,因为它们的定义被放置在使用它们的查询中(与此处描述的其他对象不同),因此它们可以比其他类型的 TVF (?) 优化得更好。这些 TVF 执行得非常好,如果可以在单个查询中处理逻辑,则它们是首选。
SQLCLR (TVF):这些 TVF 与 T-SQL MultiStatement TVF 相似,因为它们在之前将整个结果集构建在内存中(即使是交换/页面文件)在最后释放所有这些。他们将返回的估计行数,报告给查询优化器(这会影响执行计划)总是 1000 行。鉴于固定行数远非理想,请支持我的请求以允许指定行数:Allow TVFs (T-SQL and SQLCLR) to provide user-defined row estimates to query optimizer
SQLCLR 流 (sTVF): 这些 TVF 允许像常规 SQLCLR TVF 一样复杂的 C#/VB.NET 代码,但特殊之处在于它们将每一行返回给调用查询它们被生成(?)。此模型允许调用查询在发送第一个查询后立即开始处理结果,因此查询无需等待函数的整个过程完成即可看到任何结果。而且它需要更少的内存,因为在过程完成之前结果不会存储在内存中。他们将返回的估计行数,报告给查询优化器(这会影响执行计划)总是 1000 行。鉴于固定行数远非理想,请支持我的请求以允许指定行数:Allow TVFs (T-SQL and SQLCLR) to provide user-defined row estimates to query optimizer
用户定义的聚合 (UDA) 是类似于 SUM()、COUNT()、MIN()、MAX() 等的聚合,通常需要 GROUP BY 子句。这些只能在 SQLCLR 中创建,并且该功能是在 SQL Server 2005 中引入的。此外,从 SQL Server 2008 开始,UDA 得到了增强,以允许多个输入参数 (?)。一个特殊的缺陷是不知道组内的行排序,因此在 SAFE 程序集中创建运行总计(如果可以保证排序会相对容易)是不可能的。
另请参阅:
【讨论】:
标量函数
返回单个值。这就像在其他编程语言中使用T-SQL 语法编写函数一样。
表值函数
与上面的有点不同。返回一个表值。在此函数的主体中,您编写一个将返回确切表的查询。 例如:
CREATE FUNCTION <function name>(parameter datatype)
RETURN table
AS
RETURN
(
-- *write your query here* ---
)
注意这里没有BEGIN & END 语句。
聚合函数
包括与GROUP 子句一起使用的内置函数。例如:SUM(),MAX(),MIN(),AVG(),COUNT() 是聚合函数。
【讨论】:
聚合函数和标量函数都返回单个值,但标量函数基于单个输入 值 参数运行,而聚合函数基于单个输入运行一组值(集合或列名)。标量函数的示例有字符串函数、ISNULL、ISNUMERIC,聚合函数的示例有 AVG、MAX 等,您可以在 Microsoft 网站的Aggregate Functions 部分找到。
无论是否存在任何输入参数,表值函数都会返回一个表。通过将它们用作常规物理表来执行此功能,例如:SELECT * FROM fnGetMulEmployee()
以下链接对于理解差异非常有用:https://www.dotnettricks.com/learn/sqlserver/different-types-of-sql-server-functions
【讨论】: