触发器调用存储过程,如果我们进行选择,返回值是新的还是旧的?

Posted

技术标签:

【中文标题】触发器调用存储过程,如果我们进行选择,返回值是新的还是旧的?【英文标题】:Trigger calls Stored Procedure and if we we do a select will the return values be the new or old? 【发布时间】:2021-11-03 12:19:11 【问题描述】:

使用 MS SQL Server,触发器调用内部进行选择的存储过程,返回值是新的还是旧的?

我知道在触发器内部我可以通过FROM INSERTED i inner join DELETED 访问它们,但在这种情况下,我想重用(无法更改)现有存储过程,该存储过程在内部对触发的表进行选择并使用它们处理一些逻辑.我只是想知道我是否可以确定现有逻辑是否有效(通过访问新值)。

我可以简单地尝试通过一次更新来模拟它......但也许还有其他情况(例如:使用事务或其他东西)我可能不知道并且从不测试它可能会导致不同的情况。

我决定问其他可能更了解的人。谢谢。

【问题讨论】:

从触发器中调用过程通常是个坏主意。触发器对调用 DML 语句的影响应尽可能小。理想情况下,将程序需要使用的数据放入一个表中,然后让一个定期安排的任务执行该程序(它以基于集合的方式使用和使用该数据)。 @Larnu 我理解并且我同意你的看法......但是在这种特定情况下,现有的 SP 已经很复杂,我不希望其内部逻辑重复并且容易有人忘记更改如果我愿意听从你的建议,那就两次。 将调用放入过程中并不“正确”。事实上,如果程序很复杂(而且很慢?),那么这就是不将调用放入触发器的所有更多理由;你的表现会很糟糕。 无论你同意与否,我的问题仍然有效。 SP会获取新数据还是旧数据? 如果您要问的是,程序无法访问 inserteddeleted 对象,不。如果你问它是否会“看到”受 DML 语句影响的数据,那么是的,因为它在同一个事务范围内。您可以在沙盒环境中轻松地进行测试。 db<>fiddle 【参考方案1】:

AFTER 触发器(默认)在 DML 操作之后触发。当在触发器中调用 proc 时,表将反映触发触发器的语句所做的更改以及在调用 proc 之前触发器内所做的更改。

在触发器完成或显式事务稍后提交之前,未提交更改。

【讨论】:

【参考方案2】:

由于该过程与(可能是“后”)触发器在同一个事务中运行,它会看到未提交的数据。

我希望您能看到其中的含义:触发器作为 DML 语句启动的事务的一部分执行,导致它触发,因此存储过程是同一事务的一部分,因此是一个“复杂”的存储过程意味着事务保持打开的时间更长、持有锁的时间更长、对用户的响应更慢等等。

还有,你说

在内部对触发的表进行选择并用它们处理一些逻辑。

如果您的意思是该过程选择数据以进行一些复杂的处理,然后将其写入数据库中的其他位置,好吧,这不是很好(出于上面给出的原因),但它会“工作” .

但以防万一您的意思是您正在对过程中的数据进行一些处理,然后将其返回给客户端应用程序,Don't do that

从触发器返回结果的功能将在 SQL Server 的未来版本中删除。返回结果集的触发器可能会导致非设计用于使用它们的应用程序中出现意外行为。避免在新开发工作中从触发器返回结果集,并计划修改当前执行的应用程序。要防止触发器返回结果集,请将 disallow results from triggers 选项设置为 1。

【讨论】:

以上是关于触发器调用存储过程,如果我们进行选择,返回值是新的还是旧的?的主要内容,如果未能解决你的问题,请参考以下文章

c#中两种不同的存储过程调用与比较

专业实习日志08

Python Pandas:更改格式,其中索引和列名以及相应的值是新的行值

sparkRDD操作

触发器

sql触发器