我可以在 MySQL 触发器中使用类似事务的功能吗

发布于 2025-01-05 02:53:27 字数 258 浏览 1 评论 0原文

我有一个插入触发器,它从表 A 中的行中获取一组列值,并将其中一些值插入表 B 中并保留在表 C 中。我需要此操作成为一个事务,其中如果在插入数据时出现一些错误表B而不是C,整个插入操作应该回滚。

我研究了手册,它在this 触发器中不允许事务的页面

有没有办法在mysql中实现我想要的。

I have an insert trigger which takes a set of column values from rows in table A and inserts some of them in table B and remaining in table C. I need this operation to be a transaction wherein if there is some error whilst data is inserted in table B and not C, the entire insertion operation should be rolled back.

I studied the manual and it says at the last of this page that transaction is not allowed in triggers

Is there a way to achieve what I want in mysql.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

別甾虛僞 2025-01-12 02:53:27

是的,您可以,但具体操作方式取决于您的版本。

首先,触发器本身是事务性的;在您的情况下,您有一个插入触发器可以执行两次进一步的插入。如果其中之一失败,您将获得所需的效果。

考虑以下示例:

CREATE TABLE a (colA INT);
CREATE TABLE b (colB INT);
CREATE TABLE c (colC INT);
delimiter :
CREATE TRIGGER testtrig BEFORE INSERT ON a
  FOR EACH ROW BEGIN
    INSERT INTO b(colB) VALUES(NEW.colA);
    INSERT INTO c(banana) VALUES (NEW.colA); -- note the faulty column name
END;:
delimiter ;

现在,当我运行失败的插入时,会发生这种情况:

mysql> INSERT INTO a VALUES (5);
ERROR 1054 (42S22): Unknown column 'banana' in 'field list'
mysql> SELECT * FROM a;
Empty set (0.00 sec)

这与您想要的结果相匹配。

更一般地说,如果您在尝试插入之前有可用于验证数据的逻辑,则可以通过不同的方式使触发器失败:

  • 在 MySQL 5.5 中,您可以使用 SIGNAL 机制从触发器引发错误,从而导致整个插入失败。
  • 在 MySQL 5.5 之前,您可以故意生成错误以使触发器失败。

我猜您正在问题中的链接中使用 5.0,因此如果需要,您可以执行故意错误,例如故意插入无效列,以使触发器失败。但是,您在问题中描述的情况已经通过事务处理,如我的答案开头所述。

Yes you can, but how you do it depends on your version.

First of all, triggers are themselves transactional; in your situation, you have an insert trigger that performs two further inserts. If one of those fails, you will get your desired effect.

Consider the following example:

CREATE TABLE a (colA INT);
CREATE TABLE b (colB INT);
CREATE TABLE c (colC INT);
delimiter :
CREATE TRIGGER testtrig BEFORE INSERT ON a
  FOR EACH ROW BEGIN
    INSERT INTO b(colB) VALUES(NEW.colA);
    INSERT INTO c(banana) VALUES (NEW.colA); -- note the faulty column name
END;:
delimiter ;

Now, when I run an insert that fails, this happens:

mysql> INSERT INTO a VALUES (5);
ERROR 1054 (42S22): Unknown column 'banana' in 'field list'
mysql> SELECT * FROM a;
Empty set (0.00 sec)

This matches your desired result.

More generally, if you have logic you can use to validate your data before attempting the insert, you can fail the trigger in different ways:

  • In MySQL 5.5, you can use the SIGNAL mechanism to raise an error from your trigger, thus causing it to fail the whole insert.
  • Prior to MySQL 5.5, you can generate a deliberate error to fail the trigger.

I'm guessing you're using 5.0 from the link in your question, so if you need to, you can perform a deliberate error, for example deliberately insert into an invalid column, to fail a trigger. However, the situation you describe in your question is already handled transactionally, as described at the start of my answer.

蓝海 2025-01-12 02:53:27

默认情况下,您会得到您所要求的内容——触发器中的任何错误都会导致语句失败。因此,如果该语句上存在事务,您就会将数据回滚到该语句之前的位置。如果没有交易,那么就没有。

这可能就是为什么触发器中不允许创建或结束事务的原因。

所以不需要存储过程。事实上,如果您从触发器调用的存储过程尝试创建事务,则可能会导致错误。

但在执行导致触发的操作之前,请随意使用存储过程来启动事务。

You get what you asked for by default -- any error in a trigger causes the statement to fail. So if there is a transaction on the statement, you get a rollback of the data to just before that statement. If there is no transaction, then you don't.

Which is probably why creating or ending a transaction is not allowed in a trigger.

So no need for a stored procedure. In fact, the stored procedure you call from the trigger might cause an error if it tries to create a transaction.

But feel free to use a stored procedure to start a transaction before doing the action that causes the trigger.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文