如果我的表定义更新,为什么视图不会更新?

时间:2015-02-17 13:47:50

标签: sql sql-server sql-server-2008

假设我有一个表格作为下面的定义:

CREATE TABLE Test
(
    a INT,
    b INT
)

之后,我正在桌面上创建一个视图,

CREATE VIEW ViewTest
AS
SELECT * FROM Test

之后,当我在视图上运行查询时,它会返回两列,即A & B

之后我更新了table的定义并在其中插入了一个新列:

ALTER TABLE Test ADD c INT

但是,现在当我运行视图时它再次返回视图语句,它返回相同数量的列,现在是三列。

我只是想知道为什么?因为我使用了Select *语句,所以每次它都应该返回整个列。

4 个答案:

答案 0 :(得分:1)

当您向Test添加新列时,ViewTest已经存在,并且只有A列和B列。您必须删除ViewTest并为“SELECT *”语句重新创建它以检索新列C. / p>

答案 1 :(得分:1)

创建视图时,它将视图定义作为元数据存储在系统表中。即使您使用SELECT * FROM,它也会存储确切的列名,例如SELECT a, b FROM

如果您随后更新基表,则视图的元数据定义仍然保持不变,因此不会拾取任何新列。

您需要删除并重新创建视图,或运行sp_refreshview以更新定义

答案 2 :(得分:1)

当您第一次遇到它时,这似乎是意外的行为。它有很好的记录。例如,在CREATE VIEW的文档中:

  

如果未使用SCHEMABINDING子句创建视图,则为sp_refreshview   应该在对视图下面的对象进行更改时运行   这会影响视图的定义。否则,视图可能会   查询时会产生意想不到的结果。

重新编译很容易。 。 。您可以使用alter viewsp_refreshview(记录here)。

这两个选项是:

  • 使用SCHEMABINDING定义视图,以阻止对视图中使用的表进行更改。
  • 在表格更改后手动修改视图。

我怀疑这是SQL Server中的优化,因此当您使用视图时,引擎只需插入已编译的代码,而不是对正在使用的表进行一堆完整性检查。此优化对于事务处理中使用的视图很重要。如果您通过视图运行更复杂的查询,则不是那么重要。但是,这并不能解释为什么在基础表发生变化时没有完成检查。

过去,当基础表发生变化并且生成的select错误的列偏移时,我一直被这种方式所困扰。请注意,仅通过避免select *就可以解决此问题 ,尽管这通常是一种很好的做法。

此外,如果您有一个定期运行的大型系统(例如,每周或每天),您可能希望放入一个重新编译系统中所有视图的作业。这还可确保其执行计划正在更新以获取有关表的最新统计信息。并且,如果您真的要小心,请使用SCHEMABINDING,因此需要对基础表进行任何更改。

答案 3 :(得分:0)

来自MSDN文档:

<强> View Definition

创建一个虚拟表,其内容(列和行)由查询定义。使用此语句可以在数据库的一个或多个表中创建数据视图。例如,视图可用于以下目的:

  • 关注,简化和自定义每个用户对数据库的感知。
  • 作为一种安全机制,允许用户通过视图访问数据,而不授予用户直接访问底层基表的权限。
  • 提供向后兼容的接口,以模拟其架构已更改的表。

来自View Definition文档的这棵树应该回答你的原因。最精确的是它的3个。

使用select *创建视图也不是一个好的实践,因为您或其他任何查看视图的人都不会知道它具有哪些列。

还有关于该文档的说明:

注意

  

直接对视图的基础表执行的任何更新都不会针对视图进行验证,即使指定了CHECK OPTION也是如此。