下面举几个例子,以防万一:

内联表值

CREATE FUNCTION MyNS.GetUnshippedOrders()
RETURNS TABLE
AS 
RETURN SELECT a.SaleId, a.CustomerID, b.Qty
    FROM Sales.Sales a INNER JOIN Sales.SaleDetail b
        ON a.SaleId = b.SaleId
        INNER JOIN Production.Product c ON b.ProductID = c.ProductID
    WHERE a.ShipDate IS NULL
GO

多语句表取值

CREATE FUNCTION MyNS.GetLastShipped(@CustomerID INT)
RETURNS @CustomerOrder TABLE
(SaleOrderID    INT         NOT NULL,
CustomerID      INT         NOT NULL,
OrderDate       DATETIME    NOT NULL,
OrderQty        INT         NOT NULL)
AS
BEGIN
    DECLARE @MaxDate DATETIME

    SELECT @MaxDate = MAX(OrderDate)
    FROM Sales.SalesOrderHeader
    WHERE CustomerID = @CustomerID

    INSERT @CustomerOrder
    SELECT a.SalesOrderID, a.CustomerID, a.OrderDate, b.OrderQty
    FROM Sales.SalesOrderHeader a INNER JOIN Sales.SalesOrderHeader b
        ON a.SalesOrderID = b.SalesOrderID
        INNER JOIN Production.Product c ON b.ProductID = c.ProductID
    WHERE a.OrderDate = @MaxDate
        AND a.CustomerID = @CustomerID
    RETURN
END
GO

使用一种类型(内联或多语句)是否比另一种有优势?是否存在一个比另一个更好的情况,或者这种差异纯粹是句法上的?我意识到这两个示例查询正在做不同的事情,但有一个原因我将以这种方式编写它们吗?

读到它们,它们的优点/区别并没有真正被解释清楚。


当前回答

在内部,SQL Server像对待视图一样对待内联表值函数,像对待存储过程一样对待多语句表值函数。

当内联表值函数作为外部查询的一部分使用时,查询处理器将扩展UDF定义,并使用这些对象上的索引生成访问底层对象的执行计划。

For a multi-statement table valued function, an execution plan is created for the function itself and stored in the execution plan cache (once the function has been executed the first time). If multi-statement table valued functions are used as part of larger queries then the optimiser does not know what the function returns, and so makes some standard assumptions - in effect it assumes that the function will return a single row, and that the returns of the function will be accessed by using a table scan against a table with a single row.

当多语句表值函数返回大量行并在外部查询中连接时,它们的性能可能会很差。性能问题主要是由于这样一个事实:优化器将生成一个假设返回一行的计划,而这个计划不一定是最合适的计划。

根据经验,我们发现,由于这些潜在的性能问题,在可能的情况下,应该优先使用内联表值函数而不是多语句函数(当UDF将被用作外部查询的一部分时)。

其他回答

如果你要做一个查询,你可以在你的内联表值函数中加入:

SELECT
    a.*,b.*
    FROM AAAA a
        INNER JOIN MyNS.GetUnshippedOrders() b ON a.z=b.z

它将产生很少的开销,并且运行良好。

如果你试图在类似的查询中使用你的多语句表值,你会有性能问题:

SELECT
    x.a,x.b,x.c,(SELECT OrderQty FROM MyNS.GetLastShipped(x.CustomerID)) AS Qty
    FROM xxxx   x

由于您将对返回的每一行执行函数1次,因此随着结果集变得越来越大,它将运行得越来越慢。

我认为你的例子很好地回答了这个问题。第一个函数可以作为一个单独的选择来完成,这是使用内联样式的一个很好的理由。第二种方法可能可以作为一条语句来完成(使用子查询来获得最大日期),但一些编码器可能会发现,像您这样在多条语句中完成它更容易阅读或更自然。有些函数不能在一条语句中完成,因此需要多语句版本。

我建议尽可能使用最简单的(内联),并在必要时(显然)或当个人偏好/可读性使它与额外的类型时使用多语句。

看看比较内联和多语句表值函数,你可以找到很好的描述和性能基准

也许是以一种非常简洁的方式。 ITVF(内联TVF):如果你是DB人,是一种参数化的视图,取一个SELECT st

MTVF(多语句TVF):开发人员,创建并加载表变量。

在内部,SQL Server像对待视图一样对待内联表值函数,像对待存储过程一样对待多语句表值函数。

当内联表值函数作为外部查询的一部分使用时,查询处理器将扩展UDF定义,并使用这些对象上的索引生成访问底层对象的执行计划。

For a multi-statement table valued function, an execution plan is created for the function itself and stored in the execution plan cache (once the function has been executed the first time). If multi-statement table valued functions are used as part of larger queries then the optimiser does not know what the function returns, and so makes some standard assumptions - in effect it assumes that the function will return a single row, and that the returns of the function will be accessed by using a table scan against a table with a single row.

当多语句表值函数返回大量行并在外部查询中连接时,它们的性能可能会很差。性能问题主要是由于这样一个事实:优化器将生成一个假设返回一行的计划,而这个计划不一定是最合适的计划。

根据经验,我们发现,由于这些潜在的性能问题,在可能的情况下,应该优先使用内联表值函数而不是多语句函数(当UDF将被用作外部查询的一部分时)。