mysql - 在同一表上触发更新和选择 - 错误 1235 (42000)

标签 mysql triggers

我正在尝试实现 Table with multiple incrementing columns which doesn't reuse deleted column values .此帖子被标记为已被 How auto-increment within a subset of the table MYSQL 回答,但是,引用的帖子不符合规定的要求,因为它允许子集递增的键被复制。在第一个帖子中,给出了评论:

Create a table that will store last AI numbers per type. Use a trigger to increment it on every insert and copy to the original table. – Paul Spiegel

我认为这是个好主意,并实现了它。

-- MySQL Script generated by MySQL Workbench
-- 02/19/17 08:53:34
-- Model: New Model    Version: 1.0
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `mydb` ;

-- -----------------------------------------------------
-- Table `mydb`.`t1`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t1` (
  `pk1` INT NOT NULL,
  `pk2` INT NOT NULL,
  `id2` INT NOT NULL DEFAULT 0,
  PRIMARY KEY (`pk1`, `pk2`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `mydb`.`t2`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`t2` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `id2` INT NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;


SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
USE `mydb`;

DELIMITER $$
USE `mydb`$$
CREATE TRIGGER `t2_BINS` BEFORE INSERT ON `t2` FOR EACH ROW
begin
UPDATE t1 SET id2=id2+1 WHERE pk1=NEW.pk1 AND pk2=NEW.pk2;
SET NEW.id2=(SELECT id2 FROM t1 WHERE pk1=NEW.pk1 AND pk2=NEW.pk2);
end$$


DELIMITER ;

然而,当执行脚本时,我收到以下错误:

ERROR 1235 (42000) at line 68: This version of MySQL doesn't yet support 'multiple triggers with the same action time and event for one table'

我正在使用 MySQL 5.5.54。是否有新版本可以做到这一点?

是否有任何变通方法可以实现此目的?

最佳答案

您可能已经在一张表上定义了两个 BEFORE INSERT 触发器。至少那是错误消息所说的。取消注释 this demo 中的第二个触发器你会得到同样的错误信息

This version of MySQL doesn't yet support 'multiple triggers
with the same action time and event for one table'

第二个错误是您在错误的表上定义了触发器(或者您混淆了触发器中的表)。您的触发器在 t2 上,但您正在尝试从 t1 (NEW.pk1) 访问列。所以你会收到以下错误信息:

Unknown column 'pk1' in 'NEW'

http://sqlfiddle.com/#!9/1515abb (取消注释触发器中的行。)

但是 - 即使解决了这个问题,逻辑看起来也不正确。您可能想要的工作版本可能是:

CREATE TABLE IF NOT EXISTS `t1` (
  `pk1` INT NOT NULL,
  `pk2` INT NOT NULL DEFAULT 0,
  PRIMARY KEY (`pk1`, `pk2`))
ENGINE = InnoDB;

CREATE TABLE IF NOT EXISTS `t2` (
  `pk1` INT NOT NULL,
  `last_pk2` INT NOT NULL,
  PRIMARY KEY (`pk1`))
ENGINE = InnoDB;

DELIMITER //

CREATE TRIGGER `t1_BINS` BEFORE INSERT ON `t1` FOR EACH ROW
begin
  UPDATE t2 SET last_pk2=last_pk2 + 1 WHERE pk1=NEW.pk1;
  SET NEW.pk2=(SELECT last_pk2 FROM t2 WHERE pk1=NEW.pk1);
end//

DELIMITER ;

正如您在 demo 中看到的那样,第二个插入没有指定 pk2,但它在结果中增加了。

然而,如果您插入一个未在 t2 中注册的 pk1 值,这将失败。 (取消注释 demo 中的最后一行)在这种情况下,必须将新行插入到 t2 中。由于 pk1t2 中的 PRIMARY KEY,我们可以使用 INSERT .. ON DUPLICATE KEY UPDATE .. 语法:

CREATE TRIGGER `t1_BINS` BEFORE INSERT ON `t1` FOR EACH ROW
begin
  INSERT INTO t2 (pk1, last_pk2) values (NEW.pk1, 1)
    ON DUPLICATE KEY UPDATE last_pk2 = last_pk2 + 1;
  SET NEW.pk2=(SELECT last_pk2 FROM t2 WHERE pk1=NEW.pk1);
end//

http://sqlfiddle.com/#!9/79eeea/1

现在最后一步是让它并发保存。我们必须防止两个并发线程/ session 为 t2.last_pk2 读取相同的值。因此,写作和阅读应该在一个语句中完成。我们可以使用 session 变量或 LAST_INSERT_ID() 来做到这一点:

CREATE TRIGGER `t1_BINS` BEFORE INSERT ON `t1` FOR EACH ROW
begin
  INSERT INTO t2 (pk1, last_pk2) values (NEW.pk1, @last_pk2 := 1)
    ON DUPLICATE KEY UPDATE last_pk2 = @last_pk2 := (last_pk2 + 1);
  SET NEW.pk2 = @last_pk2;
end//

http://sqlfiddle.com/#!9/dc235a/1

CREATE TRIGGER `t1_BINS` BEFORE INSERT ON `t1` FOR EACH ROW
begin
  INSERT INTO t2 (pk1, last_pk2) values (NEW.pk1, LAST_INSERT_ID(1))
    ON DUPLICATE KEY UPDATE last_pk2 = LAST_INSERT_ID(last_pk2 + 1);
  SET NEW.pk2 = LAST_INSERT_ID();
end//

http://sqlfiddle.com/#!9/86ed740/1

关于mysql - 在同一表上触发更新和选择 - 错误 1235 (42000),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42330198/

相关文章:

mysql - 在 SELECT 中设置一个包含 2 个元素的 var

mysql - 无法更新在 AFTER INSERT 中执行触发器的表

mysql - 如何将变量设置为触发器 MYSQL 中存储过程的结果?

mysql - 将表 1 中的 2 列连接到表 2

mysql - 问题 - TABLE_SCHEMA 中的 AUTO_INCREMENT 值未更新

Mysql 替换搜索中的一部分(按模式替换)

wpf - Blend KeyTrigger 多次触发

具有多个查询的 php/mysql

c# - 处理与 MySql 的连接丢失

mysql - 使用 MySQL 触发器替换输入