【问题标题】:Can altering a computed column definition cause an update trigger to fire?更改计算列定义会导致触发更新触发器吗?
【发布时间】:2022-01-11 23:25:39
【问题描述】:

场景:

  1. 表有 1 个或多个计算列。这些列仅根据表中其他列的值进行简单计算。列被标记为 PERSISTED。
  2. 表有一个 AFTER INSERT、UPDATE 触发器来插入或 UPDATE 行到第二个表。
  3. 第二个表架构相同,但没有计算列。
  4. 部署和表使用后(表现在有生产数据),确定计算有误,需要更正。

开发人员预计更改计算列的计算会导致触发器触发(基本上是 DML 操作)。观察到的更像是 DDL 操作。源表显示了计算更改的正确结果,但第二个表没有。计算的列值已得到纠正这一事实使开发人员得出结论,这些更改将反映在另一个表中。

我断言这样的表更改类似于更改列的类型。它是一个 DDL 操作,不属于会导致 DML 触发器触发的操作。问题是我是根据经验推断出这个结果。我还没有找到说明这应该是预期结果的文档。谁能赐教?

谢谢

【问题讨论】:

  • 您不能更改计算列;如果你需要,你必须DROP说专栏然后重新ADD它。这两个都是ALTER TABLE 语句的一部分,它是一个DDL 语句。 [table] TRIGGER 出现在创建它的表上的 INSERTUPDATE 和/或 DELETE 语句之后; ALTER TABLE 声明不是这些。
  • 补充以上内容,如果一个动作的结果不清楚,通常会发生什么是你在开发中首先测试它;模拟相同的场景(尽管可能有一个与生产相同的开发服务器)并测试删除和添加新计算列的结果需要很少的努力,这样做会表明表上的任何触发器都不会火。所说的“开发人员”需要学习良好的做法。
  • 如您所见,触发器未触发dbfiddle.uk/…
  • 更好的问题是为什么另一个表也没有计算列
  • @Charlieface 第二张表因为 DRY 而没有计算。它是用于特定目的的航路点,仅用于反映原始表格的内容。重复代码意味着下次它必须在两倍的地方修复。

标签: sql triggers sql-server-2016 calculated-columns


【解决方案1】:

alter不是数据update,因此定义为在update上触发的触发器不会在@ 987654324@被执行。

你必须刷新第二个表:

delete from table2;
insert into table2 select * from table1;

【讨论】:

  • 是的,这就是证据所暗示的。我希望有人知道一些神奇的 MS 文档,它明确地说,似乎更新数据的东西,实际上并没有按照开发人员预期的方式这样做。至少他会知道它是否会再次发生。
  • @Bryant 尝试更新所有行,但不更改数据:update table1 set someColumn = someColumn
  • @Bryant 改变 DML 操作的定义本身并不是 DML;这是 DDL。
【解决方案2】:

documentation for CREATE TRIGGER 中写着:(我的粗体字)

创建 DML、DDL 或登录触发器。触发器是一种特殊类型的存储过程,当数据库服务器中发生事件时会自动运行。 DML 触发器在用户尝试通过数据操作语言 (DML) 事件修改数据时运行。 DML 事件是表或视图上的INSERTUPDATEDELETE 语句。这些触发器在任何有效事件触发时触发,无论表行是否受到影响。如需更多信息,请参阅DML Triggers

DDL 触发器运行以响应各种数据定义语言 (DDL) 事件。这些事件主要对应于 Transact-SQL CREATEALTERDROP 语句,以及执行类似 DDL 操作的某些系统存储过程。

在那篇链接的文章中it says

DML 触发器的类型

AFTER 触发器
AFTER 触发器在执行INSERTUPDATEMERGEDELETE 语句 的操作后执行... .

您可以清楚地看到, 触发 DML 触发器的操作是那些用于语句的操作。 ALTER 会触发 DDL 触发器,这是非常不同的。

您可以从db<>fiddle 中的这个快速模型中看到情况就是这样。

【讨论】:

  • 我很清楚触发器的工作原理以及 DDL 和 DML 之间的区别,并且从 v6.1 开始就一直如此。您能否为我加粗,它说 DML 操作(在计算列中执行计算是 DML 操作)似乎会更改数据(通常是 DML 操作,您可以在 SSMS 中看到它发生),实际上是不是 DML 操作,所以我不应该期望执行基于 DML 的触发器?这是我正在为最近的实习生寻找的特定文档。
  • 我完全不明白你在说什么。如何更新计算列?看到这个小提琴dbfiddle.uk/…。 “执行计算列”我假设您的意思是SELECT 它,为什么会是 DML?它不会改变任何数据,它只是一个计算。 SSMS 有哪些变化?只有更新基列才会改变它。您用于修改计算列定义的操作是 ALTER 语句,我显示的是明确的 not DML 语句并且不会触发 DML 触发器
  • 计算列“值”在其所基于的列的值发生更改时发生更改。我以为这很清楚。如果计算列基于另外 2 个列的添加,那么您可以在 SSMS(或您选择的其他工具)中观察到对基础列的更改会改变计算列的值。鉴于定义计算列的计算被定义为 DML 操作,像我这样的白痴可能会认为它是 DML 操作。我正在寻找的只是说明这不是 DML 操作的文档。
  • 抱歉,我的印象是您正在运行 DROPADD 来更改计算列定义。正如我所展示的,那不会是 DML,因为它不是这四个操作之一。如果您对基本列执行UPDATE,那么是的,is 是 DML 操作并且触发触发器。实际执行了什么?
猜你喜欢
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
  • 2011-01-15
  • 1970-01-01
  • 2016-07-02
  • 1970-01-01
  • 2021-09-08
相关资源
最近更新 更多