SQL Server 为啥我必须在表更改后刷新视图

Posted

技术标签:

【中文标题】SQL Server 为啥我必须在表更改后刷新视图【英文标题】:SQL Server why must I refresh views after table changesSQL Server 为什么我必须在表更改后刷新视图 【发布时间】:2015-02-17 03:13:26 【问题描述】:

这个问题来自我以前的帖子/解决方案:

adding a field somehow effects a views results

IMO 它应该有自己的帖子。使用 SQL Server 2008 R2。

为什么在向视图中引用的表添加列后必须刷新视图?虽然不是直接需要回答这个帖子/问题,但我的特定场景的场景/行为在上面链接的帖子中进行了解释。

我不是观点的忠实拥护者。老实说,我创建它们非常罕见,我正在使用我最初没有编写的代码。假设您有 70 多个视图,这些视图不是您最初编写的,因此每次添加数据库列时都不知道哪些视图需要刷新。坦率地说,我应该能够随时添加任何列任何表格而不会产生任何影响。业务部门可以提出任何类型的更改请求,可能需要随时添加任意数量的字段。

肯定还有其他方法可以解决这个问题吗?

【问题讨论】:

视图不仅仅是一个查询,每次调用时都会动态地重新组织自己。它使用模式、列等实例化。在许多情况下(例如您引用的链接中的情况),向结果集中添加其他列可能会出现意外行为。虽然这种方式与您想要的更宽松的实现相反,但也可以使用 SCHEMABINDING 选项声明视图,该选项禁止对底层对象进行模式更改。但是,正如在几个地方所指出的那样,如果您希望架构选择新列,则必须使用 sp_refreshview 感谢您的宝贵时间。虽然我不喜欢它,但它是有道理的。我确实意识到视图具有资源效率优势。这就是说,我很确定我现在更不喜欢它们了。由于向表中添加列,我今天看到的最终用户体验非常不稳定 浏览量并不总是坏的。它们非常适合简化复杂查询,标准化查询中的业务规则,这些查询可以跨应用程序或存储过程共享,使您能够编写重命名字段或简化对第三方数据库的查询(尤其是具有过时名称的遗留数据库,例如 AE1401 作为表名称与字段 FN144 等),当应用程序共享一个表时,如果基础表字段必须更改,视图名称可以保持不变,而不会强制您更改多个应用程序。 视图还可以在某些场景中提供显着的性能改进,在这些场景中,您可以索引和具体化返回视图的数据,或者合并由于性能问题和表大小而可能在多个表中水平分片的数据。 【参考方案1】:

使用动态管理视图来确定哪些视图受到了表更改的影响,然后遍历受影响视图的结果以使用动态 sql 调用 sp_refreshview (https://msdn.microsoft.com/en-us/library/ms187821(v=sql.105).aspx)

这是一个快速脚本,您可以根据需要适应存储过程:

DECLARE @TableName VARCHAR(500) = 'dbo.Accounts'

DECLARE @ViewsToUpdate TABLE (ViewName VARCHAR(500))
    INSERT @ViewsToUpdate
        SELECT
            Views.TABLE_SCHEMA + '.' + Views.TABLE_NAME
        FROM INFORMATION_SCHEMA.TABLES [Views]
            INNER JOIN sys.dm_sql_referencing_entities(@TableName, 'OBJECT') DependingViews
                ON DependingViews.referencing_schema_name = Views.TABLE_SCHEMA
                    AND DependingViews.referencing_entity_name = Views.TABLE_NAME
        WHERE [Views].TABLE_TYPE = 'View'

WHILE EXISTS (SELECT * FROM @ViewsToUpdate) BEGIN
    DECLARE @ViewName VARCHAR(500) = (SELECT TOP 1 ViewName FROM @ViewsToUpdate)
    DECLARE @Sql NVARCHAR(1000) = 'EXEC sp_refreshview ''' + @ViewName + ''''
    EXEC sys.sp_executesql @Sql
    DELETE @ViewsToUpdate WHERE ViewName = @ViewName
END

【讨论】:

添加代码示例以自动刷新与所选表相关的视图 感谢您的宝贵时间。我需要等待批准才能重现该问题,然后运行/测试它,但它确实看起来是一个很好的解决方案来扫描所有必要的视图! 我刚刚想到的另一个功能,如果它像批发引用表格一样简单,它可能是 hepful,是 SYNONYM 功能。顾名思义,这只是为一个表创建一个别名,该表直接将您的查询发送到它同义的对象(这是一个词吗?)。然后,如果您向该对象添加一列,它会自动包含在内,因为它基本上是基础对象。 以前从未使用过同义词。刚刚阅读,看起来确实是抽象服务器和/或数据库位置的好方法。但是,我不明白添加新字段后如何有效地“刷新”我的视图

以上是关于SQL Server 为啥我必须在表更改后刷新视图的主要内容,如果未能解决你的问题,请参考以下文章

必须更改语言后刷新导航返回按钮的标题

更改 SQL Server 2008 中在表的计算列中引用的标量函数

是否可以在 SQL Server 中使用 nolock 更改视图?

为啥.cshtml更改后刷新页面不更新

为啥 spring-vaadin 忘记了我设置的 locale,但在页面刷新后突然记住了?

编辑后不刷新 ALV。为啥?