【问题标题】:SQL Server 2012 using SELECT in trigger breaks tableSQL Server 2012 在触发器中断表中使用 SELECT
【发布时间】:2013-05-21 14:27:18
【问题描述】:

首先让我承认我是 SQL Server 新手。

这是交易:我正在尝试在 SQL Server 2012 中的表上创建触发器,并且每当我在触发器中尝试任何类型的 SELECT 语句时,该表都会停止工作(因为没有什么可以插入,直到触发器被删除)。我一放下扳机,一切就又开始工作了。如果我不做任何SELECTs,一切都很美好。是否有许可或我遗漏的地方?

例子:

CREATE TRIGGER sometrigger
ON sometable
FOR INSERT
AS
BEGIN
    SELECT * FROM inserted
END
GO

命令成功完成,但表格如上所述冻结。

CREATE TRIGGER sometrigger
ON sometable
FOR INSERT
AS
BEGIN
    EXEC msdb.dbo.sp_send_dbmail
    @recipients = N'someaddress@somedomain.com',
    @subject = 'test',
    @body = 'test body',
    @profile_name = 'someprofile'
END
GO

像魅力一样工作。

【问题讨论】:

  • 您为什么要从触发器中执行select *?谁会看到结果集?
  • 您是如何尝试插入“停止工作”的?是来自隐藏异常/错误消息的东西吗?
  • @Andomar 我不会,这只是详细说明我的问题的一个简单示例。
  • @Damien_The_Unbeliever 插入来自使用数据库作为事件日志的系统。我只是通过登录/退出该系统或任何其他将事件添加到表中的方式来生成它们。该系统上没有显示任何错误。
  • 尝试自己编写一个INSERT 语句并在查询分析器中运行它,看看是否有错误消息。

标签: sql sql-server select triggers sql-server-2012


【解决方案1】:

您可能会因为将 disallow results from triggers 选项设置为 1 而犯规,因为它应该是。

注意该页面上的警告:

此功能将在 Microsoft SQL Server 的下一版本中删除。不要在新的开发工作中使用此功能,并尽快修改当前使用此功能的应用程序。我们建议您将此值设置为 1。

我怀疑无论您在哪里运行插入,都会隐藏错误消息或异常,因为您应该得到:

消息 524,级别 16,状态 1,过程,行

“触发器返回了一个结果集,并且服务器选项 'disallow_results_from_triggers' 为真。”


或者,在另一种情况下,您正在使用一个数据库层,该层将所有插入包装在事务中,如果发生任何意外情况(例如接收结果集或什至只是一个额外的信息消息说@),它将回滚事务987654322@.

但这一切都围绕着主要问题展开——您不应该发出一个尝试从触发器内部返回结果的选择。如果你真的告诉我们你想要达到的目标,我可能会提供更多帮助。

如果是第二种情况,并且由于(x rows affected) 消息而绊倒,可以通过将SET NOCOUNT ON 放在触发器顶部来解决。

【讨论】:

  • 好的,我正在尝试在没有任何错误报告的系统上生成错误电子邮件通知。我唯一能想到的是有一个触发器来检查刚刚添加到数据库中的事件的严重级别,并在出现严重级别“错误”时发送电子邮件。
  • 禁止结果选项设置为 0,我已经有 SET NOCOUNT ON。我只是想从inserted 表中提取一些值,将它们分配给变量,然后通过电子邮件发送它们。例如:DECLARE @EventID int ... SELECT @EventID = [EventID] FROM inserted ... EXEC msdb.dbo.sp_send_dbmail ... @body = @EventID。我怎样才能做到这一点而不返回结果??
  • @Bodacious:在 SQL Server 中,使用 SELECT 检索行与使用它分配变量有些不同,SQL Server 不允许混合这两者。所以我的问题是,您是否真的尝试过SELECT @EventID = [EventID] FROM ...,即变量赋值语法,而不是SELECT [EventID] FROM ...或任何其他类型的数据检索语法?另外,您是否尝试过仅在连接中使用 inserted 作为过滤器,并从实际表(插入的目标)中读取数据?
【解决方案2】:

无论如何,您都不应该从触发器返回数据,主要是出于简单和维护的原因。令人困惑:我做了一个 INSERT 但得到了一个结果集。

如果您需要获取刚刚插入的值,您可以use the OUTPUT clause

INSERT sometable (...)
OUTPUT INSERTED.*
VALUES (...);

这至少告诉你 INSERT 给出了结果。

它也可以嵌套,比如SQL Server concurrent transaction issue

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-04
    相关资源
    最近更新 更多