为什么我要更新视图中的值?

时间:2014-08-05 10:28:34

标签: sql sql-server

关于我的MCSA SQL Server 2012课程的一个简单问题。

作为练习的一部分,我被要求创建一个触发器来停止对视图的任何更新,我首先检查了我确实可以更改视图中列的值。

在我知道它们是什么之前已经处理了视图,但我不知道为什么一个视图默认情况下不会在默认情况下停止改变。

1)为什么我要更改视图表中的值?

2)此外,如果我更新了视图上的值,是否会将其更改为反映基表中的内容,如果是,那么何时可能发生?,即夜间刷新,对基表的任何更改?< / p>

谢谢:)

2 个答案:

答案 0 :(得分:1)

您的问题似乎更关注“为什么”而不是“如何”。为什么DML会针对视图执行而不是直接针对表执行?答案几乎无法在这里列出,但这里只是几个较大的答案。

对于初学者,当我设计数据库时,几乎每个表都至少有一个为其定义的视图。如果不止一个,一个通常是DML视图,其他是只读(触发器什么也不做)。没有面向外的,很少有内向的应用程序可以直接访问表。一切都必须通过观点。

为什么呢?因为这会在应用程序和基础表之间构建一个抽象墙。然后我可以不断调整和调整表格,很少对应用程序进行任何更改。我可以添加或删除列,更改列的数据类型,将表合并在一起或将表拆分为两个或三个单独的表,但视图将所有内容重新组合到应用程序期望看到它的方式。他们甚至不必知道有任何改变。应用程序可以将数据写入他们所看到的单个“表”,并且视图触发器将数据分配给正确的表。视图触发了解实际数据的存储方式,应用程序无需知道。

这是一个无与伦比的优势。有许多有用的函数需要在触发器之前使用。有时你真的想在它进入表之前以某种方式操纵数据。一些DBMS,甚至像SQL Server这样的主要参与者,只有触发后。这样的痛苦。

但是在视图前面,在视图上写一个触发器, et voila ,在触发之前立即。这对于像Oracle这样的其他DBMS来说甚至很方便,因为触发器可以更新同一个表中的其他相关行,而不会违反变异表条件。我就是在这个时刻在一个视图上写一个触发器,每次执行任何Insert或Delete时都必须更新几行中的值,有时候还要更新。几乎不可能没有视图的任务 - 它必须使用存储过程而不是“直接”DML。方便我,方便的应用程序。生活很美好!

此外,采取由于尝试保持两个表彼此同步而导致的循环条件。在任一表中进行的任何更改都应发送到另一个表。但是两个表上的触发器只是将操作镜像到另一个表将创建一个无限循环,因为该触发器转向并向右发送它。但是面向视图的触发器可以在其基础表和镜像表上执行DML。镜像表上的视图也是一样的。但由于两个视图都直接在表上运行,因此不存在无限循环条件。

所以我的问题更像是:为什么我们希望用户直接访问表而不是让他们浏览视图?

答案 1 :(得分:0)

要回答有关如何使用触发器完成此操作的问题,您可以使用以下内容:

CREATE TRIGGER dbo.demo_trigger ON dbo.demo_view
INSTEAD OF UPDATE --The "INSTEAD OF" is probably why the question is in the course, outside of a view or procedure this is tends to be "BEFORE"
AS
BEGIN
    SET NOCOUNT ON 
    ROLLBACK
    RAISERROR (50005,10,1,N'abcde')
END
GO

我添加了一个自定义错误:

sp_addmessage @msgnum = 50005
, @severity = 10
, @msgtext = N'Not allowed';
GO

可以使用此功能将其删除:

sp_dropmessage @msgnum = 50005;

现在尝试更新视图会产生以下结果:

Not allowed
Msg 3609, Level 16, State 1, Line 1
The transaction ended in the trigger. The batch has been aborted.