【问题标题】:Why would I update a value in a view? [closed]为什么要更新视图中的值? [关闭]
【发布时间】:2014-08-05 10:28:33
【问题描述】:

关于我的 MCSA SQL Server 2012 课程的快速问题。

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

在我知道它们是什么之前就使用过视图,但我不知道为什么视图不会在默认情况下首先停止更改。

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

2) 另外,如果我在视图上更新了一个值,是否会对其进行更改以反映基表中的内容,如果是的话,什么时候会发生这种情况?即一夜之间刷新,对基表有任何更改吗?

谢谢:)

【问题讨论】:

标签: sql sql-server


【解决方案1】:

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

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

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

这是无与伦比的优势之一。有很多很多有用的功能需要使用 before 触发器。有时您只是真的想在数据进入表格之前以某种方式对其进行操作。一些 DBMS,甚至像 SQL Server 这样的主要参与者,只有 after 触发器。好痛啊。

但是在表格前面有一个视图,在视图上写一个触发器,et voila,即时 before 触发器。这对于像 Oracle 这样的其他 DBMS 来说甚至很方便,因为触发器可以更新同一个表中的其他关联行,而不会与变异表条件发生冲突。我此时正在为一个视图编写一个触发器,该触发器必须在每次执行任何插入或删除(有时是更新)时更新几行中的值。没有视图几乎不可能完成的任务——它必须使用存储过程而不是“直接”DML 来完成。对我很方便,对应用程序很方便。生活是美好的!

另外,考虑由于试图保持两个表彼此同步而导致的循环条件。在任一表中所做的任何更改都应发送到另一个表。但是两个表上的触发器只是将操作镜像到另一个表将创建一个无限循环,因为该触发器转身并立即将其发送回来。但是正面视图上的触发器可以在其基础表和镜像表上执行 DML。镜像表上的视图做同样的事情。但由于两个视图都直接对表进行操作,因此不会陷入无限循环条件。

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

【讨论】:

  • +1 有很好的理由。 更不用说让圣诞老人回答你的问题有多棒了。 :) --- 胡须很棒!
【解决方案2】:

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

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.

【讨论】:

  • 谢谢大家。我明白了,在练习中我使用“INSTEAD OF”来停止任何更新。我只是好奇为什么存在在视图中编辑值(未出现在两个连接的基表中)的选项?我想知道是否有一个现实生活中的场景可能想要这样做,或者它是否是一个聪明的解决方案来做一些其他方式无法完成的事情?但是感谢所有的答案和 cmets :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多