【问题标题】:SQL Server 2008 The transaction ended in the trigger. The batch has been abortedSQL Server 2008 事务在触发器中结束。该批次已中止
【发布时间】:2011-06-15 15:53:26
【问题描述】:

我得到了这个存储过程:

CREATE PROCEDURE getManagerSalary 
(
@Emp_id         INT,
@ManagerSalary  MONEY OUTPUT
)
AS
SELECT @ManagerSalary = es.Salary
FROM [outdoorparadise].[dbo].[Employee] AS e 
INNER JOIN 
    [outdoorparadise].[dbo].[Employee] AS m
    ON e.Manager_id = m.Emp_id
INNER JOIN
    [outdoorparadise].[dbo].[Employee_staff] AS es
    ON e.Manager_id = es.Emp_staff_code
WHERE e.Emp_id = @Emp_id;

我得到了这个触发器:

CREATE TRIGGER checkSalary ON Employee_staff
AFTER UPDATE
AS
    DECLARE
    @Emp_id INT,
    @NewSalary MONEY,
    @ManagerSalary MONEY;

    SELECT @NewSalary = Salary
    FROM inserted;

    SELECT @Emp_id = Emp_staff_code
    FROM inserted;

    EXEC getManagerSalary @Emp_id = @Emp_id, 
        @ManagerSalary = @ManagerSalary OUTPUT;

    IF @NewSalary > @ManagerSalary
        BEGIN
        RAISERROR 60000 'Salary cannot be higher than the salary of the manager!'
        ROLLBACK TRANSACTION;
        END
    ELSE
        COMMIT TRANSACTION;

当我将薪水更新为高于经理薪水的值时,我收到加薪错误 + 此错误:事务在触发器中结束。该批次已中止。

当我尝试将薪水更新为低于经理薪水的值时,我仍然得到以下信息:事务在触发器中结束。该批次已中止。

谁能告诉我如何解决这个问题? 我搜索了,但找不到任何东西。

谢谢, 龙拳

PS:这是我的第一篇文章,也许我没有正确粘贴代码,所以我很抱歉。

【问题讨论】:

  • 我需要对您的触发器发表评论 - 您犯了一个会导致问题的错误。触发器在 SQl 服务器中批量操作,您不能假设只会发送 1 条记录(即使您认为是所有将被发送的,它不会随着时间的推移而成立)。除非它是表变量,否则不应将值从插入的变量设置为变量。

标签: sql-server transactions batch-file triggers


【解决方案1】:

放弃扳机。将其替换为检查约束和标量函数。

CREATE FUNCTION dbo.GetManagerSalary(@Emp_id int) RETURNS money
AS
BEGIN
    RETURN
        SELECT es.Salary
        FROM [dbo].[Employee] e 
        JOIN [dbo].[Employee] m ON m.Emp_id = e.Manager_id
        JOIN [dbo].[Employee_staff] es ON es.Emp_staff_code = e.Manager_id
        WHERE e.Emp_id = @Emp_id;
END

GO

ALTER TABLE Employee_staff
    ADD CONSTRAINT CK_Salary
    CHECK (ISNULL([Salary], 0) <= ISNULL(dbo.GetManagerSalary([Salary]), 1e9)))

【讨论】:

  • 我认为通过这种方式,OP不需要在触发器中强加验证,因为约束正在做所有事情。这太好了 +1。
  • 我会确保测试被插入的人是顶级经理的边缘情况。
  • @hlgem 我想到了。这就是 ISNULL 和
  • @Anthony Faull,我同意它应该,我只是想让 OP 知道他需要测试它以确保它按他预期的方式工作。特别是因为他可能会为他拥有的某些特定业务规则创建不同的功能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多