我正在使用最新的MySQL(8.0.15),并且有一个递归查询来更新user
表,并且我想在我的user
表中有一个{{1}时运行它},INSERT
或UPDATE
查询针对它运行。
上下文:如您在代码片段中所看到的,我使用一种物化路径方法将分层数据存储在MySQL中。您可以通过查看数据来弄清楚问题所在。
因此,每次修改表时都需要运行此递归查询,以便保持正确的DELETE
和Lineage
。
当前问题是,在对原始查询进行一些故障排除后,我在this SO post上发现无法在表上调用Depth
,因为这会导致无限循环,因此我需要在列之前加上SET
。
我似乎无法弄清楚如何做到这一点,并且在下面的示例中提供了当前的尝试。
编辑:由于db-fiddle的限制,我更新了以下代码,删除了new
。
DELIMITTER
| version() | | :-------- | | 8.0.13 |
select version();
✓
CREATE TABLE user ( `Id` INT primary key, `Name` VARCHAR(55), `ManagerUserID` INTEGER, `Depth` INTEGER, `Lineage` VARCHAR(255) );
✓
INSERT INTO user ( `Id`, `Name`, `ManagerUserID`, `Depth`, `Lineage` ) VALUES ('1', 'User 1', NULL, 0, '1.'), ('2', 'User 2', '1', 1, '1.2.'), ('3', 'User 3', '4', 3, '1.2.4.3.'), ('4', 'User 4', '2', 2, '1.2.4.'), ('5', 'User 5', '2', 2, '1.2.5.');
Id | Name | ManagerUserID | Depth | Lineage -: | :----- | ------------: | ----: | :------- 1 | User 1 | null | 0 | 1. 2 | User 2 | 1 | 1 | 1.2. 3 | User 3 | 4 | 3 | 1.2.4.3. 4 | User 4 | 2 | 2 | 1.2.4. 5 | User 5 | 2 | 2 | 1.2.5.
SELECT * from user;
✓
CREATE TRIGGER after_user_update AFTER UPDATE ON user FOR EACH ROW BEGIN UPDATE user SET new.Lineage = CONCAT(Id, '.'), new.Depth = 0 WHERE new.ManagerUserID IS NULL; WITH RECURSIVE prev AS ( SELECT * FROM user WHERE new.ManagerUserID IS NULL UNION SELECT t.new.Id, t.new.Name, t.new.ManagerUserID, p.new.Depth + 1 as Depth, CONCAT(p.new.Lineage, t.new.Id, '.') FROM prev p JOIN user t ON t.new.ManagerUserID = p.new.Id ) UPDATE user t, prev p SET t.new.Depth = p.Depth, t.new.Lineage = p.Lineage WHERE t.new.Id = p.new.Id; END
Can't update table 'user' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
UPDATE user SET `ManagerUserID` = '1' WHERE (`Id` = '3');
Id | Name | ManagerUserID | Depth | Lineage -: | :----- | ------------: | ----: | :------- 1 | User 1 | null | 0 | 1. 2 | User 2 | 1 | 1 | 1.2. 3 | User 3 | 4 | 3 | 1.2.4.3. 4 | User 4 | 2 | 2 | 1.2.4. 5 | User 5 | 2 | 2 | 1.2.5.
db <>提琴here