首页 > 解决方案 > SQL Server中视图和标量函数的循环引用

问题描述

在我的 SQL Server 2012 数据库中,我有一个表MyTable、一个视图MyView和一个标量函数MyFun

视图将MyFun如下图所示:

CREATE VIEW [dbo].[MyView]
AS
    SELECT dbo.MyFun(Age) AS Expr1
    FROM dbo.MyTable

而函数将引用MyView,如下所示:

CREATE FUNCTION [dbo].[MyFun] (@Age int)
RETURNS int
WITH EXECUTE AS CALLER
AS
BEGIN     
     SET @Age = (SELECT COUNT(*) FROM [db].[MyView]);
     RETURN (@Age + 1);
END;

既然MyFunMyView会导致循环引用,那么应该先创建哪一个呢?我找不到这方面的任何文件。

我做了一个测试。

首先,我将数据库导出为脚本。然后我在脚本中发现,函数是先创建的,如下:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[MyFun] (@Age int)
RETURNS int
WITH EXECUTE AS CALLER
AS
BEGIN     
     SET @Age = (SELECT COUNT(*) FROM [db].[MyView]);
     RETURN(@Age + 1);
END;
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MyTable]
(
    [Name] [nchar](10) NULL,
    [Age] [int] NULL
) ON [PRIMARY]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE VIEW [dbo].[MyView]
AS
    SELECT dbo.MyFun(Age) AS Expr1
    FROM dbo.MyTable
GO

但是,如果我修改脚本并在视图创建之后放置函数创建,如下所示:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[MyTable]
(
    [Name] [nchar](10) NULL,
    [Age] [int] NULL
) ON [PRIMARY]
GO

CREATE VIEW [dbo].[MyView]
AS
    SELECT dbo.MyFun(Age) AS Expr1
    FROM dbo.MyTable
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[MyFun] (@Age int)
RETURNS int
WITH EXECUTE AS CALLER
AS
BEGIN     
     SET @Age = (SELECT COUNT(*) FROM [db].[MyView]);
     RETURN(@Age + 1);
END;
GO

然后创建视图会报如下错误:

消息 4121,级别 16,状态 1,过程 MyView,第 3 行 [批处理开始第 17 行]
找不到列“dbo”或用户定义的函数或聚合“dbo.MyFun”,或者名称不明确。

所以根据测试,对于循环引用,函数应该在视图之前创建,函数可以引用尚未创建的对象。

但是其他对象呢,比如默认值、触发器、表值函数、存储过程等,如果是循环引用,那么应该先创建哪个,以后再创建哪个呢?

标签: sql-serverfunctiontsqlstored-procedurescircular-reference

解决方案


推荐阅读