如何创建一个 CROSS APPLYs 一系列内联表值 UDF 的视图?

Posted

技术标签:

【中文标题】如何创建一个 CROSS APPLYs 一系列内联表值 UDF 的视图?【英文标题】:How to create a view that CROSS APPLYs a series of inline table-valued UDFs? 【发布时间】:2018-10-26 02:26:51 【问题描述】:

这是我正在查看的代码结构:

CREATE VIEW [dbo].[View1]

    AS SELECT t1.[ID]        ,
              udf1.[Column1] ,
              udf1.[Column2] ,
              udf1.[Column3]

        FROM [Table1] t1
            CROSS APPLY [dbo].[UDF1] ( [dbo].[UDF2] ( t1.[ID] ) ) udf1

GO

[dbo].[UDF1][dbo].[UDF2] 都是内联表值函数。

我不记得确切的细节,但是当我尝试使用 JOIN 时 SSMS 给了我错误,所以告诉我我需要使用 CROSS APPLY 来修复它 - 我认为这是正确的选择吗?

无论如何,我现在的主要问题是:

找不到列“dbo”或用户定义的函数或聚合“dbo.UDF2”,或者名称不明确。

...尽管UDF2 显然存在:我可以在 SSMS 中看到它。

我怀疑真正的问题是UDF2 作为参数传递到UDF1 的方式。UDF2 返回一个表,并且列与为UDF1 定义的表值参数完全匹配。

但我认为 SQL Server 不支持这种语法? 是否需要将视图转换为多行表值函数,声明一个表变量以接收UDF2 的结果,然后将该表变量传递给UDF1

(P.S. SQL Server 的错误是我见过的最没有帮助的错误,在任何语言中......)

【问题讨论】:

哎呀,这会表现得很糟糕。 @ErikPhilips 有没有更好的替代方案?我想我认为内联函数在这种情况下表现得很好......但我不太了解CROSS APPLY,所以...... 不要使用 UDF。 @ErikPhilips(另外,我觉得我应该提一下,这是在内存中的 OLTP 数据上运行,而不是在硬盘上运行。所以性能不会像 相当看起来很糟糕。) 【参考方案1】:

这可能会有很差的性能,但我认为您需要为每个表值函数使用单独的 CROSS APPLY。我认为在 UDF1 中使用 UDF2 返回的内容是不可能的,因为 UDF1 需要一个 Table Type 的参数,而 UDF2 返回的是 Table 而不是 Table Type。

函数不能返回表类型,因此您可能不得不寻找其他解决方案。您可以创建另一个函数,将 UDF2 的结果插入到表类型中,然后调用 UDF1。

如果你能做到,它看起来像:

CREATE VIEW [dbo].[View1]
    AS SELECT t1.[ID]        ,
              udf1.[Column1] ,
              udf1.[Column2] ,
              udf1.[Column3]
        FROM [Table1] t1
            CROSS APPLY [dbo].[UDF2] ( t1.[ID] ) udf2
            CROSS APPLY [dbo].[UDF1] ( udf2 ) udf1
GO

要创建“另一个包装函数”,它看起来像:

CREATE FUNCTION [dbo].[UDF3](
    @id INT -- data type for t1.ID
) RETURNS @t TABLE (
    -- ... Your columns here ...
) 
AS
BEGIN
    -- Your user defined Table Type
    DECLARE @udf2 UDF2_TABLE 
    INSERT @udf2 (... columns ...)
    SELECT udf2.* -- try to use exact column names instead of *
      FROM [Table1] t1
         CROSS APPLY [dbo].[UDF2]( t1.[ID] )

    -- I'm not really sure this is possible either
    INSERT @t (... columns ...)
    SELECT udf1.*
      FROM [dbo].[UDF1](@udf2) udf1

    RETURN;
END

【讨论】:

我就是这么想的。凉爽的。 (另外,我觉得我应该提一下,这是在内存中的 OLTP 数据上运行,而不是在硬盘上。所以性能不会像看起来那样相当。)

以上是关于如何创建一个 CROSS APPLYs 一系列内联表值 UDF 的视图?的主要内容,如果未能解决你的问题,请参考以下文章

AWS Cloudformation - Cross Stack 学习总结

AWS Cloudformation - Cross Stack 学习总结

内联表值 UDF 与视图 - 使用哪个?

Firefox 中一个 Cross-mmap 溢出的利用

高级T-SQL进阶系列 :使用 CROSS JOIN 介绍高级T-SQL

如何使用内联变量创建多行 Python 字符串?