【问题标题】:Where is the definition of the view stored in SQL ServerSQL Server中存储的视图定义在哪里
【发布时间】:2018-02-17 15:12:03
【问题描述】:

我可以这样创建一个表:

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 如何存储此编译?它是否将所有编译对象的定义保存在某个系统数据库中的某个位置?

【问题讨论】:

  • 您可以运行存储过程“刷新视图元数据”以更新视图以反映对基础表的更改。事实上,在您显着更改表模式时执行此操作是一个好主意(如果由于重命名或删除视图显式引用的列而导致视图现在无效,则会引发错误)。以 EXEC sp_refreshview 'vwTest' 为例。
  • 您不能运行视图 - 您可以视图中选择,因为视图几乎就像一个表(不是存储过程)。
  • 抱歉,措辞不佳

标签: sql-server sql-server-2012


【解决方案1】:

TL;DR;

当您创建视图时,SQL-server 会将视图信息存储在三个单独的 sys 表中:sys.viewssys.columnssys.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.viewssys.columnssys.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' 也是一个选项,它将刷新视图详细信息。

【讨论】:

  • 当底层架构更改时,您无需再次删除/创建视图。只需运行 EXEC sp_refreshview 'ViewName' 存储过程即可刷新指定视图的元数据。我有一个我运行的脚本,它针对数据库中的每个非模式绑定视图运行它。
  • 是的,仍在编辑并获取示例。好点子。
  • sp_refreshsqlmodule 也是一个选项。
  • "CREATE VIEW 语句的文本存储在 sys.sql_modules 目录视图中"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-02
  • 1970-01-01
  • 1970-01-01
  • 2013-12-22
  • 2011-01-15
相关资源
最近更新 更多