SQL Server中的标量,表值和聚合函数之间的区别?

Ehs*_*ani 47 t-sql sql-server sqlclr function aggregate-functions

SQL Server中的标量值,表值和聚合函数有什么区别?从查询中调用它们需要一种不同的方法,还是以同样的方式调用它们?

Sol*_*zky 63

标量函数

标量函数(有时称为用户定义函数/ UDF)返回单个值作为返回值,而不是结果集,并且可以在查询或SET语句中的大多数位置使用,除了FROM子句(可能还有其他)地方呢?).此外,标量函数可以EXEC像存储过程一样调用,但是没有多少时间可以使用此功能(有关此功能的更多详细信息,请参阅我对DBA.StackExchange上的以下问题的回答:为什么标量值函数需要执行权限而不是选择?).这些可以在T-SQL和SQLCLR中创建.

  • T-SQL(UDF):

    • 在SQL Server 2019之前:这些标量函数通常是性能问题,因为它们通常针对返回(或扫描)的每一行运行,始终禁止并行执行计划.
    • 从SQL Server 2019开始:可以内联某些T-SQL标量UDF ,即将它们的定义直接放入查询中,使得查询不会调用UDF(类似于iTVF的工作方式(见下文)).有一些限制可以防止UDF被内联(如果之前不是一个字,现在是这样),并且由于几个因素,可以内联的UDF不会总是内联.可以在数据库,查询和单个UDF级别禁用此功能.有关这个非常酷的新功能的更多信息,请参阅:标量UDF内联(请务必查看"要求"部分).
  • SQLCLR(UDF):这些标量函数通常也会按返回或扫描的每一行运行,但与T-SQL UDF相比有两个重要的好处:

    • 从SQL Server 2012开始,如果UDF不进行任何数据访问,并且标记了返回值,则返回值可以恒定地折叠到执行计划中IsDeterministic = true.在这种情况下,每行都不会运行该函数.
    • 如果SQLCLR标量函数不进行任何数据库访问,它们可以在并行计划()中工作.

表值函数

表值函数(TVF)返回结果集,可以在任何查询的FROM子句,JOINCROSS APPLY/ OUTER APPLY中使用,但与简单视图不同,它不能是任何DML语句(INSERT/ UPDATE/ DELETE)的目标.这些也可以在T-SQL和SQLCLR中创建.

  • T-SQL MultiStatement(TVF):顾名思义,这些TVF可以有多个语句,类似于存储过程.它们要返回的结果是否存储在表变量中并在最后返回; 意思是,在函数完成处理之前不会返回任何内容.报告给查询优化器(影响执行计划)的估计返回行数取决于SQL Server的版本:

    • 在SQL Server 2014之前:这些总是报告1(是,仅1)行.
    • SQL Server 2014和2016:这些始终报告100行.
    • 从SQL Server 2017开始:默认是报告100行,但在某些情况下,由于新的交错执行功能,行计数将相当准确(基于当前统计信息).
  • T-SQL Inline(iTVF):这些TVF只能是单个语句,而且该语句是完整查询,就像View一样.实际上,Inline TVF本质上是一个View,它接受用于查询的输入参数.它们也不会缓存自己的查询计划,因为它们的定义被放置在使用它们的查询中(与此处描述的其他对象不同),因此它们可以比其他类型的TVF()更好地优化.如果可以在单个查询中处理逻辑,则这些TVF执行得非常好并且是优选的.

  • SQLCLR(TVF):这些TVF类似于T-SQL MultiStatement TVF,它们在内存中构建整个结果集(即使它是交换/页面文件),然后在最后释放它们.报告给查询优化器(影响执行计划)的估计返回行数始终为1000行.鉴于固定行数远非理想,请支持我的请求以允许指定行数:允许TVF(T-SQL和SQLCLR)提供用户定义的行估计以查询优化器

  • SQLCLR Streaming(sTVF):这些TVF允许复杂的C#/ VB.NET代码,就像常规的SQLCLR TVF一样,但它们的特殊之处在于它们在生成()时将每一行返回到调用查询.此模型允许调用查询在发送第一个结果后立即开始处理结果,因此查询在查看任何结果之前无需等待函数的整个过程完成.并且它需要更少的内存,因为在过程完成之前结果不会存储在内存中.报告给查询优化器(影响执行计划)的估计返回行数始终为1000行.鉴于固定行数远非理想,请支持我的请求以允许指定行数:允许TVF(T-SQL和SQLCLR)提供用户定义的行估计以查询优化器

聚合函数

用户定义聚合(UDA)类似于聚集体SUM(),COUNT(),MIN(),MAX()等,并且通常需要一个GROUP BY子句.这些只能在SQLCLR中创建,并且该功能是在SQL Server 2005中引入的.此外,从SQL Server 2008开始,UDA已得到增强,允许多个输入参数().一个特别的缺点是不知道组内的行排序,因此创建一个运行总计,如果可以保证订购则相对容易,在SAFE组件中是不可能的.


还请看:


小智 7

标量函数返回单个值.它甚至可能与数据库中的表无关.

tabled-valued函数返回表中符合您选择条件的行的指定列.

聚合值函数返回表中各行的计算 - 例如求和值.