SQL Server延迟名称解析是否适用于函数?

时间:2017-11-06 14:21:40

标签: sql-server function name-resolution

SQL Server具有Deferred Name Resolution功能,请阅读此处了解详细信息: https://msdn.microsoft.com/en-us/library/ms190686(v=sql.105).aspx

在该页面中,它所说的都是存储过程,因此看起来Deferred Name Resolution仅适用于存储过程而不适用于函数,我做了一些测试。

create or alter function f2(@i int)
returns table
as
    return (select fff from xxx)
go

请注意,表xxx不存在。当我执行上面的CREATE语句时,我收到以下消息:

  

Msg 208,Level 16,State 1,Procedure f2,Line 4 [Batch Start line 22]
  无效的对象名称' xxx'。

似乎SQL Server立即找到了不存在的表xxx,并证明Deferred Name Resolutionfunctions不起作用。但是当我稍微改变它时如下:

create or alter function f1(@i int)
returns int
as 
begin
    declare @x int;
    select @x = fff from xxx;
    return @x
end
go

我可以成功执行它:

Commands completed successfully.

执行以下声明时:

select dbo.f1(3)

我收到了这个错误:

  

Msg 208,Level 16,State 1,Line 34
  无效的对象名称' xxx'。

所以这里似乎推迟了表xxx的分辨率。这两种情况最重要的区别是返回类型。但是,我无法解释Deferred Name Resolution何时适用于函数,何时不适用。任何人都可以帮我理解这个吗?提前致谢。

2 个答案:

答案 0 :(得分:6)

感觉您正在寻找理解为什么您的特定示例无法正常工作。 Quassnoi的回答是正确的,但没有提供理由,所以我去搜索并找到了Erland Sommarskog的MSDN Social answer。有趣的部分:

  

但是,它不会扩展到视图和内联表函数。对于   存储过程和标量函数,所有SQL Server存储在   database是模块的文本。但对于视图和内联表   函数(由另一个名称参数化的视图)SQL Server   存储有关列等的元数据。如果是,则无法实现   桌子不见了。

希望有助于理解原因: - )

编辑:

我确实花了一些时间来确认Quassnoi的评论sys.columns以及其他几个表确实包含有关内联函数的一些元数据,所以我不确定是否有其他元数据没有写入。但是我想我会添加一些其他可以帮助解释的其他注释。

首先引自Wayne Sheffield's blog

  

在MTVF中,您只看到一个名为“表值函数”的操作。它所做的一切本质上都是一个黑盒子 - 正在发生的事情,并返回数据。对于MTVF,SQL无法“看到”MTVF正在执行的操作,因为它在单独的上下文中运行。这意味着SQL必须在编写时运行MTVF,而无法在查询计划中进行任何优化以优化它。

然后从SQL Server 2016 Exam 70-761 by Itzik Ben-Gan (Skill 3.1)

  

它被称为内联函数的原因是因为SQL Server内联或扩展了内部查询定义,并直接针对基础表构造内部查询。

所以看起来内联函数本质上返回一个查询,并且能够使用外部查询对其进行优化,不允许使用黑盒方法,因此不允许延迟名称解析。

答案 1 :(得分:5)

第一个示例中的内容是内联函数(它没有BEGIN/END)。

内联函数只能是表值。

如果您为第一个示例使用了多语句表值函数,请执行以下操作:

CREATE OR ALTER FUNCTION
        fn_test(@a INT)
RETURNS @ret TABLE
        (
        a INT
        )
AS
BEGIN
        INSERT
        INTO    @ret
        SELECT  a
        FROM    xxx
        RETURN
END

,它会在运行时编译正常并失败(如果xxx不存在),与存储过程或标量UDF相同。

所以是的,DNR适用于所有多语句函数(具有BEGIN/END的函数),无论它们的返回类型如何。