0

我有这样的例子:

CREATE TABLE a(
    id INT PRIMARY KEY AUTO_INCREMENT,
    parent_id INT,
    FOREIGN KEY (parent_id) REFERENCES a(id)
);

DELIMITER ;;

CREATE TRIGGER a_insert BEFORE INSERT ON a
FOR EACH ROW
BEGIN
    SIGNAL SQLSTATE '01431' SET MESSAGE_TEXT = 'The foreign data source you are trying to reference does not exist.';
END;;

DELIMITER ;


INSERT INTO a(parent_id) VALUES (NULL);
INSERT INTO a(parent_id) VALUES (1);
INSERT INTO a(parent_id) VALUES (2);
INSERT INTO a(parent_id) VALUES (4);
INSERT INTO a(parent_id) VALUES (999);

SELECT * FROM a

这最终有 4 条记录:

----------------
id     parent_id
----------------
1      NULL
2      1
3      2
4      4

我在网上发现 MySQL 不支持触​​发器中的回滚。这是一个问题,因为我想要这样的层次结构,其中没有行指向它自己,并且像插入的那样ID=4工作得很好。如何确保数据库中没有此类记录?

4

1 回答 1

1

好吧,问题在于auto_increment,因为BEFORE INSERT如果您还没有分配该值。另一方面,AFTER INSERT如果你不能用它做任何事情。

如果要使用auto_incrementid 列,可能的解决方案是使用单独的表进行排序。

您的架构看起来像

CREATE TABLE a_seq(
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE a(
  id INT NOT NULL PRIMARY KEY DEFAULT 0,
  parent_id INT,
  FOREIGN KEY (parent_id) REFERENCES a(id)
);

还有你的触发器

DELIMITER $$
CREATE TRIGGER a_insert 
BEFORE INSERT ON a
FOR EACH ROW
BEGIN
  INSERT INTO a_seq VALUES(NULL);
  SET NEW.id = LAST_INSERT_ID();
  IF NEW.id = NEW.parent_id THEN
    SET NEW.id = NULL;
  END IF;
END$$
DELIMITER ;

如果id=parent_id触发器故意违反NOT NULL分配 NULL 值的约束。因此不会插入此记录。

这是SQLFiddle演示。取消注释最后一个插入语句。它不允许您进行此类插入。

于 2013-06-01T20:47:31.020 回答