mysql和触发器的使用问题

发布于 2024-09-05 03:28:39 字数 747 浏览 1 评论 0原文

我遇到的情况是,如果满足特定条件,我不希望发生插入(事务应该回滚)。我可以在应用程序代码中编写此逻辑,但由于某种原因,它必须用 MySQL 本身编写(假设用不同语言编写的客户端将插入到此 MySQL InnoDB 表中)[这是一个单独的讨论]。

表定义:

CREATE TABLE table1(x int NOT NULL);

触发器看起来像这样:

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW
  IF (condition) THEN
    NEW.x = NULL;
  END IF;
END;

我猜它也可以写成(未经测试):

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW
  IF (condition) THEN
    ROLLBACK;
  END IF;
END;

但是,这不起作用:

CREATE TRIGGER t1 BEFORE INSERT ON table1 ROLLBACK;

您可以保证:

  1. 您的数据库将始终是 MySQL
  2. 表类型将始终是 InnoDB
  3. 那不是NULL 列将始终保持原样 问题

:您认为第一种方法有什么令人反感的地方吗?

I have a situation in which I don't want inserts to take place (the transaction should rollback) if a certain condition is met. I could write this logic in the application code, but say for some reason, it has to be written in MySQL itself (say clients written in different languages will be inserting into this MySQL InnoDB table) [that's a separate discussion].

Table definition:

CREATE TABLE table1(x int NOT NULL);

The trigger looks something like this:

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW
  IF (condition) THEN
    NEW.x = NULL;
  END IF;
END;

I am guessing it could also be written as(untested):

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW
  IF (condition) THEN
    ROLLBACK;
  END IF;
END;

But, this doesn't work:

CREATE TRIGGER t1 BEFORE INSERT ON table1 ROLLBACK;

You are guaranteed that:

  1. Your DB will always be MySQL
  2. Table type will always be InnoDB
  3. That NOT NULL column will always stay the way it is

Question: Do you see anything objectionable in the 1st method?

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

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

发布评论

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

评论(2

赠意 2024-09-12 03:28:39

来自触发文档

触发器不能使用显式或隐式开始或结束事务的语句,例如 START TRANSACTION、COMMIT 或 ROLLBACK

无法创建您的第二个选项。然而:

触发器失败会导致语句失败,因此触发器失败也会导致回滚。

因此,Eric 建议使用保证会导致错误的查询,这是下一个选择。然而,MySQL 没有能力引发自定义错误——您将需要处理误报。由于缺乏自定义错误处理,封装在存储过程中不会更好...

如果我们了解有关您的条件的更多详细信息,则可能可以通过约束来处理它。

更新


我已经确认,虽然 MySQL 有 CHECK 约束语法,但它不是由任何引擎强制执行的。如果锁定对表的访问,则可以在存储过程中处理限制逻辑。以下触发器不起作用,因为它正在引用要插入的表:

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW

  DECLARE num INT;
  SET num = (SELECT COUNT(t.col)
              FROM your_table t
             WHERE t.col = NEW.col);

  IF (num > 100) THEN
    SET NEW.col = 1/0;
  END IF;

END;

..导致 MySQL 错误 1235。

From the trigger documentation:

The trigger cannot use statements that explicitly or implicitly begin or end a transaction such as START TRANSACTION, COMMIT, or ROLLBACK.

Your second option couldn't be created. However:

Failure of a trigger causes the statement to fail, so trigger failure also causes rollback.

So Eric's suggestion to use a query that is guaranteed to result in an error is the next option. However, MySQL doesn't have the ability to raise custom errors -- you'll have false positives to deal with. Encapsulating inside a stored procedure won't be any better, due to the lack of custom error handling...

If we knew more detail about what your condition is, it's possible it could be dealt with via a constraint.

Update


I've confirmed that though MySQL has CHECK constraint syntax, it's not enforced by any engine. If you lock down access to a table, you could handle limitation logic in a stored procedure. The following trigger won't work, because it is referencing the table being inserted to:

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW

  DECLARE num INT;
  SET num = (SELECT COUNT(t.col)
              FROM your_table t
             WHERE t.col = NEW.col);

  IF (num > 100) THEN
    SET NEW.col = 1/0;
  END IF;

END;

..results in MySQL error 1235.

百善笑为先 2024-09-12 03:28:39

您是否尝试过引发错误以强制回滚?例如:

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW
  IF (condition) THEN
    SELECT 1/0 FROM table1 LIMIT 1
  END IF;
END;

Have you tried raising an error to force a rollback? For example:

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW
  IF (condition) THEN
    SELECT 1/0 FROM table1 LIMIT 1
  END IF;
END;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文