我可以创建一个这样的表:
CREATE TABLE Test
(
ID INT
)
然后创建一个视图来引用此表:
CREATE VIEW vwTest
AS
SELECT * FROM Test
然后我可以从视图中选择
SELECT * FROM vwTest
,这将返回ID
列
然后我可以修改基础表:
ALTER TABLE Test
ADD SomethingElse NVARCHAR(10)
然后当我再次从视图中选择时,我仍然只能看到ID列。
这让我相信视图是在创建时编译的,这是正确的吗?我认为这对性能更好?
SQL Server如何存储此编译?它是否在一个系统数据库中的某处保留了所有编译对象的定义?
答案 0 :(得分:3)
创建视图时,SQL-server
会将视图信息存储在三个单独的sys
表格中:sys.views
,sys.columns
和sys.sql_expression_dependencies
。
更改基础表设计时,视图不会自动更新。您可以使用三种方法之一来更新视图信息:
Drop/Create
视图。sp_refreshview 'ViewName'
sp_refreshsqlmodule 'ViewName'
查看Microsoft Documentation,您可以看到:
如果视图依赖于已删除的表或视图,则当有人尝试使用该视图时,数据库引擎会生成错误消息。如果创建了新表或视图,并且表结构未从先前的基表更改以替换已删除的表,则视图将再次变为可用。如果新表或视图结构发生更改,则必须删除并重新创建视图。
如果未使用SCHEMABINDING子句创建视图,则应在对视图下方影响视图定义的对象进行更改时运行sp_refreshview。否则,查询时视图可能会产生意外结果。
创建视图时,有关视图的信息存储在以下目录视图中:sys.views,sys.columns和sys.sql_expression_dependencies。 CREATE VIEW语句的文本存储在sys.sql_modules目录视图中。
现在回答你的问题:
SQL Server如何存储此编译?
它将它们存储在以下目录视图中:sys.views
,sys.columns
和sys.sql_expression_dependencies
。
是否在其中一个系统数据库中保留了所有编译对象的定义?
是的,确实如此。这就是为什么除非您再次删除/创建视图或仅运行:sp_refreshview 'ViewName'
,否则您无法获得更新的表格设计。
说完之后,按照你的例子。我创建了表和视图。以下是目录视图中的信息:
select v.name,
v.object_id,
v.type_desc,
col.name,
col.column_id,
sed.referenced_class_desc,
sed.referenced_entity_name
FROM sys.views as v
inner join sys.columns as col
on col.object_id = v.object_id
inner join sys.sql_expression_dependencies as sed
on sed.referencing_id = v.object_id
where v.name = 'vwTest'
我们得到了下一个结果:
name object_id type_desc name column_id referenced_class_desc referenced_entity_name
--------- ----------- ----------- -------------- ----------- ----------------------- -----------------------
vwTest 581577110 VIEW ID 1 OBJECT_OR_COLUMN Test
然后,您可以使用sp_refreshview 'ViewName'
刷新视图,执行后,上面的查询将返回:
name object_id type_desc name column_id referenced_class_desc referenced_entity_name
--------- ----------- ----------- -------------- ----------- ----------------------- -----------------------
vwTest 581577110 VIEW ID 1 OBJECT_OR_COLUMN Test
vwTest 581577110 VIEW SomethingElse 2 OBJECT_OR_COLUMN Test
正如@Gareth Lyons所提到的,sp_refreshsqlmodule 'ViewName'
也是一个选项,它将刷新视图细节。