假设我有一个表格作为下面的定义:
CREATE TABLE Test
(
a INT,
b INT
)
之后,我正在桌面上创建一个视图,
CREATE VIEW ViewTest
AS
SELECT * FROM Test
之后,当我在视图上运行查询时,它会返回两列,即A & B
。
之后我更新了table的定义并在其中插入了一个新列:
ALTER TABLE Test ADD c INT
但是,现在当我运行视图时它再次返回视图语句,它返回相同数量的列,现在是三列。
我只是想知道为什么?因为我使用了Select *语句,所以每次它都应该返回整个列。
答案 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 view
或sp_refreshview
(记录here)。
这两个选项是:
我怀疑这是SQL Server中的优化,因此当您使用视图时,引擎只需插入已编译的代码,而不是对正在使用的表进行一堆完整性检查。此优化对于事务处理中使用的视图很重要。如果您通过视图运行更复杂的查询,则不是那么重要。但是,这并不能解释为什么在基础表发生变化时没有完成检查。
过去,当基础表发生变化并且生成的select
错误的列偏移时,我一直被这种方式所困扰。请注意,仅通过避免select *
就可以解决此问题 ,尽管这通常是一种很好的做法。
此外,如果您有一个定期运行的大型系统(例如,每周或每天),您可能希望放入一个重新编译系统中所有视图的作业。这还可确保其执行计划正在更新以获取有关表的最新统计信息。并且,如果您真的要小心,请使用SCHEMABINDING
,因此需要对基础表进行任何更改。
答案 3 :(得分:0)
来自MSDN文档:
<强> View Definition 强>
创建一个虚拟表,其内容(列和行)由查询定义。使用此语句可以在数据库的一个或多个表中创建数据视图。例如,视图可用于以下目的:
来自View Definition文档的这棵树应该回答你的原因。最精确的是它的3个。
使用select *
创建视图也不是一个好的实践,因为您或其他任何查看视图的人都不会知道它具有哪些列。
还有关于该文档的说明:
注意强>
直接对视图的基础表执行的任何更新都不会针对视图进行验证,即使指定了CHECK OPTION也是如此。