Jus*_*ner 7 sql-server function deferred-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
Run Code Online (Sandbox Code Playgroud)
请注意,该表xxx不存在.当我执行上述CREATE语句时,我收到以下消息:
消息208,级别16,状态1,过程f2,行4 [批次开始行22]
无效的对象名称"xxx".
似乎SQL Server立即找到了不存在的表xxx,并证明Deferred Name Resolution它不起作用functions.但是,当我稍微改变它如下:
create or alter function f1(@i int)
returns int
as
begin
declare @x int;
select @x = fff from xxx;
return @x
end
go
Run Code Online (Sandbox Code Playgroud)
我可以成功执行它:
Commands completed successfully.
Run Code Online (Sandbox Code Playgroud)
执行以下语句时:
select dbo.f1(3)
Run Code Online (Sandbox Code Playgroud)
我收到了这个错误:
消息208,级别16,状态1,行34
无效的对象名称'xxx'.
所以这里似乎xxx推迟了表格的分辨率.这两种情况最重要的区别是返回类型.但是我无法解释什么时候Deferred Name Resolution可以用于函数,什么时候不用.任何人都可以帮我理解这个吗?提前致谢.
感觉就像是在寻找理解为什么你的特定例子不起作用.Quassnoi的答案是正确的但没有提供理由所以我去搜索并找到了这个由Erland Sommarskog撰写的MSDN社交答案.有趣的部分:
但是,它不会扩展到视图和内联表函数.对于存储过程和标量函数,数据库中的所有SQL Server存储都是模块的文本.但是对于视图和内联表函数(由另一个名称作为参数化视图),SQL Server存储有关列等的元数据.如果表缺失,则无法实现.
希望有助于理解原因:-)
编辑:
我确实花了一些时间来确认Quassnoi的评论,sys.columns以及其他几个表确实包含有关内联函数的一些元数据,所以我不确定是否有其他元数据没有写入.但是我想我会添加一些我能够找到的其他注释,可以帮助解释.
首先引自Wayne Sheffield的博客:
在MTVF中,您只能看到一个名为"表值函数"的操作.它所做的一切本质上都是一个黑盒子 - 正在发生的事情,并返回数据.对于MTVF,SQL无法"看到"MTVF正在执行的操作,因为它在单独的上下文中运行.这意味着SQL必须在编写时运行MTVF,而无法在查询计划中进行任何优化以优化它.
然后从Itzik Ben-Gan的SQL Server 2016考试70-761(技能3.1):
它被称为内联函数的原因是因为SQL Server内联或扩展了内部查询定义,并直接针对基础表构造内部查询.
因此,似乎内联函数本质上返回一个查询,并且能够使用外部查询对其进行优化,不允许使用黑盒方法,因此不允许延迟名称解析.
你的第一个例子中有一个内联函数(它没有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
Run Code Online (Sandbox Code Playgroud)
,它会在运行时编译正常并失败(如果xxx不存在),与存储过程或标量UDF相同.
所以是的,DNR确实适用于所有多语句函数(带有BEGIN/END),无论它们的返回类型如何.
| 归档时间: |
|
| 查看次数: |
719 次 |
| 最近记录: |