在MySQL(在任何版本中)是否可以声明并使用具有引用同一表的AUTO_INCREMENT主键的自引用(而非空)外键列的表?
基本上,我想创建下表,其中的行代表树木森林。我希望层次结构中的根节点由行的parent_id
指示等于id
(而不是允许parent_id
中的NULL来指示根)。< / p>
e.g。
CREATE TABLE forest (
id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
parent_id BIGINT NOT NULL,
CONSTRAINT fk_forest_parent_id FOREIGN KEY(parent_id) REFERENCES forest(id),
name VARCHAR(20) NOT NULL UNIQUE
);
创建此表有效(5.0.44sp1-enterprise-gpl-nt-log MySQL Enterprise Server(GPL))。但是,似乎不可能使用LAST_INSERT_ID()来插入parent_id
根节点(这并不奇怪)。以下内容不起作用:
INSERT INTO forest(parent_id, name) VALUES (LAST_INSERT_ID(), "root 1");
以下工作正常,但不再使用自动增量:
INSERT INTO forest(id, parent_id, name) VALUES (1234, 1234, "root 1");
有没有办法使用以这种方式定义的表,同时仍然依赖于自动生成的PK,同时还保留所有约束(NOT NULL和FOREIGN KEY)?
更新 - 可能的解决方案:
START TRANSACTION;
SET FOREIGN_KEY_CHECKS = 0;
INSERT INTO forest(parent_id, name) VALUES (0, "root X");
UPDATE forest SET parent_id = LAST_INSERT_ID() WHERE id = LAST_INSERT_ID();
SET FOREIGN_KEY_CHECKS = 1; /* This seems to be important. */
COMMIT;
答案 0 :(得分:2)
在id
完成之前,无法知道行的INSERT
是什么,因此在没有LAST_INSERT_ID()
的情况下调用INSERT
不会任何东西。相反,您需要两个单独的语句(可以作为存储过程中的事务或者您拥有的事务运行)。
INSERT INTO forest(name) VALUES ("root 1");
UPDATE forest SET parent_id = LAST_INSERT_ID() WHERE id = LAST_INSERT_ID();
但是,我不认为根节点将自己引用为父节点是有意义的。只是说。