我有这样的例子:
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个recods:
----------------
id parent_id
----------------
1 NULL
2 1
3 2
4 4
我发现在线发帖称MySQL不支持触发器中的回滚。这是一个问题,因为我想要这样的层次结构,其中没有行指向它自己和像ID=4
那样插入的工作正常。如何确保数据库中没有此类记录?
答案 0 :(得分:1)
嗯,问题在于auto_increment
,因为您在BEFORE INSERT
事件中尚未分配该值。另一方面,在AFTER INSERT
事件中你无法做任何事情。
如果您想使用auto_increment
id列,可能的解决方案是使用单独的表进行排序。
您的架构看起来像
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 演示。取消注释上一个插入语句。它不允许你制作这样的插页。