【问题标题】:copy rows from one table to another triggered by insert on a 3rd table将行从一个表复制到另一个由第三个表上的插入触发
【发布时间】:2019-06-14 16:52:07
【问题描述】:

在我的数据库中有四个表:tasktasknotestask_archivetasknotes_archive。当一个条目从task 表复制到task_archive 表时,我想使用触发器来执行以下操作:

  1. tasknotes表中的相关任务说明复制到tasknotes_archive表中。
  2. 删除我刚刚复制到task_archivetask表中的条目
  3. tasknotes 中删除我刚刚复制到tasknotes_archive 的条目

与数据库接口的应用程序是使用 JDBC 在 Java 中构建的。我可以通过对数据库的一系列调用或作为事务来实现上述结果。但是,使用初始插入语句似乎比将行从任务复制到 task_archive 触发其余事件更有效。我最初通过查看是否可以获得触发器来根据插入到 task_archive 中删除任务表中的条目来测试这一点。这似乎工作正常。但是,当我开始尝试添加脚本以使数据库从 tasknotes 复制到 tasknotes_archive 时,我收到错误消息,指出它在第一个 where 子句中无法识别 task_archive.task_id。重要的是,tasknotes 和 tasknotes_archive 具有完全相同的表结构,因此应该可以使用此插入方法,如该问题的答案中所述:MYSQL: How to copy an entire row from one table to another in mysql with the second table having one extra column?。然后,我尝试根据堆栈上其他问题的答案将其更改为 new.task_id。仍然收到错误消息。以下代码是task_archive中包含的插入触发器,我应该尝试开发它来对tasknotes_archive和task执行上述操作:

CREATE
TRIGGER `myDB`.`task_archive_AFTER_INSERT`
AFTER INSERT ON `myDB`.`task_archive`
FOR EACH ROW
BEGIN
INSERT INTO tasknotes_archive
SELECT tasknotes.* FROM tasknotes
WHERE tasknotes.task_id = task_archive.task_id;

DELETE FROM task
USING task, task_archive
WHERE task.task_id = task_archive.task_id;
END

我的问题是,是否可以按照所述将多个事件作为触发器运行?我是否正确假设这是一种更有效的执行方式,而不是在 java 中多次调用数据库?最后,写这个触发器的正确​​方法是什么?

【问题讨论】:

  • 您正在复制从tasknotestasknotes_archive 的所有行,而不仅仅是与当前任务相关的行。
  • 您的DELETE 语法完全错误。您需要使用JOIN,而不是USINGDELETE task, tasknotes FROM task JOIN tasknotes ON ... WHERE ...
  • 两个查询都需要一个使用NEW.task_idWHERE 子句。查找与正在归档的当前行相关的行。
  • @Barmar 当删除之前的 INSERT 语句时,DELETE 语句本身可以正常工作。如果它有效,为什么它是错误的,或者更确切地说,为什么它是错误的方法?
  • 啊,我看到USINGDELETE 中的替代语法。

标签: mysql database database-trigger


【解决方案1】:

您需要使用NEW.task_id来获取与触发器当前行相关的任务。

如果您使用 CLI 执行此操作,则需要 DELIMITER 语句,以便在触发器中的语句之间使用 ;

DELIMITER $$

CREATE
TRIGGER `myDB`.`task_archive_AFTER_INSERT`
AFTER INSERT ON `myDB`.`task_archive`
FOR EACH ROW
BEGIN
    INSERT INTO tasknotes_archive
    SELECT tasknotes.* FROM tasknotes
    WHERE tasknotes.task_id = NEW.task_id;

    DELETE task, tasknotes
    FROM task JOIN tasknotes USING (task_id)
    WHERE task.task_id = NEW.task_id;
END
$$
DELIMITER ;

【讨论】:

  • 感谢以上。我可以遵循逻辑,但我仍然遇到错误。需要明确的是,触发器代码附加到我的 task_archive 表上的插入,并且应该在将新任务复制到其中时触发。我认为以上假设触发器在 tasknotes_archive 表上?插入代码失败并显示错误消息 Incorrect integer value: 'john smith' for column 'task_id' at 第 19 行。我想要实现的是'获取与刚刚在 task_archive 中插入的条目的 task_id 关联的任务注释并复制将 tasknotes 中具有相同 task_id 的条目放入 tasknotes_archive。'
  • 听起来这两个表中的列顺序不同。如果您使用INSERT INTO table1 SELECT * FROM table2,它们必须完全匹配。如果没有,您需要使用INSERT INTO table1 (col1, col2, col3, ...) SELECT col1, col2, col3, ... FROM table2
  • 或者更改存档表,使其列与原始表的顺序相同。
  • 我在DELETE 查询中确实有一个错误,我有JOIN task_archive 应该是JOIN tasknotes
  • 这是我能想到的唯一原因,为什么它说john smithtask_id 的错误值,因为tasknotes 表的用户名应该是任务ID 列。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-06
  • 1970-01-01
  • 2014-05-22
  • 2016-08-10
  • 2018-01-10
  • 1970-01-01
相关资源
最近更新 更多