【问题标题】:Difference between scalar, table-valued, and aggregate functions in SQL server?SQL Server 中标量、表值和聚合函数之间的区别?
【发布时间】:2016-04-17 17:13:09
【问题描述】:

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

【问题讨论】:

  • select get_turnover()select * from get_all_orders()有什么区别

标签: sql-server function tsql aggregate-functions sqlclr


【解决方案1】:

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

表值函数返回表中满足选择条件的行的指定列。

聚合值函数返回跨表行的计算——例如求和值。

【讨论】:

  • 我明白了聚合和标量的意思。但是您能否为表值提供更多定义。并举一个简单的例子
  • @EhsanJeihani 表值函数或多或少是一个带参数的视图。有两种类型 - 内联和多语句。 stackoverflow.com/questions/2554333/…
  • 典型的数据库查询会产生一组行。在一个简单的情况下,它们是从一个表中提取的。在您的查询中,您指定要检索表中的哪些列,并且您的 WHERE 子句指定给定表行需要满足的条件才能包含在结果行集中。
【解决方案2】:

标量函数

标量函数(有时称为用户定义函数/UDF)返回单个值作为返回值,而不是作为结果集,并且可以在查询或SET 语句中的大多数地方使用,除了FROM 子句(可能还有其他地方?)。此外,可以通过EXEC 调用标量函数,就像存储过程一样,尽管使用此功能的场合并不多(有关此功能的更多详细信息,请参阅我在 DBA.StackExchange 上对以下问题的回答: Why scalar valued functions need execute permission rather than select?)。这些可以在 T-SQL 和 SQLCLR 中创建。

  • T-SQL (UDF):

    • 在 SQL Server 2019 之前:这些标量函数通常是一个性能问题,因为它们通常针对返回(或扫描)的每一行运行并且始终禁止并行执行计划。
    • 从 SQL Server 2019 开始:某些 T-SQL 标量 UDF 可以内联,也就是说,将它们的定义直接放入查询中,这样查询就不会调用 UDF(类似于iTVF 工作(见下文))。有一些限制可以防止 UDF 可内联(如果以前不是这样的话,现在是),并且由于多种因素,可以内联的 UDF 并不总是内联。可以在数据库、查询和单个 UDF 级别禁用此功能。有关这个非常酷的新功能的更多信息,请参阅:Scalar UDF Inlining(请务必查看“要求”部分)。
  • 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 行,但在某些情况下,由于新的 Interleaved Execution 功能,行数将相当准确(基于当前统计数据)。
  • 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 程序集中创建运行总计(如果可以保证排序会相对容易)是不可能的。


另请参阅:

【讨论】:

    【解决方案3】:

    标量函数

    返回单个值。这就像在其他编程语言中使用T-SQL 语法编写函数一样。

    表值函数

    与上面的有点不同。返回一个表值。在此函数的主体中,您编写一个将返回确切表的查询。 例如:

    CREATE FUNCTION <function name>(parameter datatype)
    
    RETURN table
    
    AS
    
    RETURN
    
    (
    
    -- *write your query here* ---
    
    )
    

    注意这里没有BEGIN & END 语句。

    聚合函数

    包括与GROUP 子句一起使用的内置函数。例如:SUM(),MAX(),MIN(),AVG(),COUNT() 是聚合函数。

    【讨论】:

      【解决方案4】:

      聚合函数和标量函数都返回单个值,但标量函数基于单个输入 参数运行,而聚合函数基于单个输入运行一组值(集合或列名)。标量函数的示例有字符串函数、ISNULL、ISNUMERIC,聚合函数的示例有 AVG、MAX 等,您可以在 Microsoft 网站的Aggregate Functions 部分找到。

      无论是否存在任何输入参数,表值函数都会返回一个表。通过将它们用作常规物理表来执行此功能,例如:SELECT * FROM fnGetMulEmployee()

      以下链接对于理解差异非常有用:https://www.dotnettricks.com/learn/sqlserver/different-types-of-sql-server-functions

      【讨论】:

        猜你喜欢
        • 2017-12-05
        • 1970-01-01
        • 1970-01-01
        • 2021-06-14
        • 1970-01-01
        • 2013-08-21
        • 2013-08-14
        • 1970-01-01
        • 2011-02-18
        相关资源
        最近更新 更多