我最近遇到了这个问题,想知道我的理解是否正确。我是 DNA 后端开发人员(不是 DBA),但经常与 SQL 交互。我创建了两个相同的函数(从结果数据的角度来看),并将它们按创建脚本的顺序排列:
CREATE FUNCTION dbo.get_names_udf (@user_id nvarchar(24))
RETURNS NVARCHAR(500)
AS
BEGIN
DECLARE
RETURN SELECT dbo.usernames(@user_id))
END
GO
CREATE FUNCTION dbo.get_names_itvf (@user_id nvarchar(24))
RETURNS TABLE
AS
RETURN
(SELECT name = SELECT dbo.usernames(@user_id))
GO
-- dbo.usernames is a simple scalar function which is defined after both the functions above
这就是我为我的数据库创建所有功能的方式:
我放弃了所有的功能
sysobjects
我再次重新创建所有功能。
“该
usernames()
功能是在上述两者之后创建的”。
当我尝试执行所有函数创建脚本时 - 似乎我的 iTVF 创建失败,因为它报告该usernames()
函数不存在(这是预期的,因为对象被删除,正如我上面提到的)。
Msg 4121, Level 16, State 1, Server XXXXXXXXX, Procedure get_names_itvf, Line 5
Cannot find either column "dbo" or the user-defined function or aggregate "dbo.usernames", or the name is ambiguous.
但对于 UDF 函数,它不会遇到此错误。
这是因为内联 TVF 如何看待内部结果?或者是如何解决 UDF 和 iTVF 的依赖关系?
我不确定为什么会这样,所以最好能得到一些指导/建议。
韩国,
当您创建标量函数时,您定义返回类型
在这种情况下是 NVARCHAR(500),只要知道返回类型,SQL Server 就不需要检查引用函数/表的底层结构。
如果 usernames 函数(在本例中)将返回 NVARCHAR(500) 之外的其他内容,则它将无法执行,这是预期的
另一方面
正如指定的那样,返回表因此 SQL 服务器检查表的底层结构,因为它需要知道开始返回哪种表。它有多少列,如果任何列没有名称(在聚合情况下)并通知您。如果用户名表没有指定的列名,您可以通过运行上面的查询而不引用列名('as user name')来测试这一点。
注意:我不得不稍微调整这两个函数,使它们起作用。
希望这能为您阐明幕后发生的事情
如果这是一个问题,您可以编写脚本来创建某些对象的虚拟或占位符版本,例如内部没有任何工作部件的过程。然后,在该过程的后期,将虚拟对象替换为工作对象。
如果我希望在测试或生产环境中多次尝试定义一个对象来做我想做的事情,我可以像这样编写脚本:
注意到 S4V1N 的建议,针对您的情况的脚本可能应该在第一次指定对象的输入和输出格式。