MySQL : 级联更新相同 table
MySQL : Cascade update on same table
我有一个 MySQL table,其中每个记录都引用其 parent_id :
| id | Summary | parent_id | hidden |
-------------------------------------
| 1 | First | NULL | 0 |
| 2 | Hello | 1 | 0 |
| 3 | john | 1 | 0 |
| 4 | Second | NULL | 0 |
| 5 | World | 2 | 0 |
| 6 | Doe | 4 | 0 |
我想级联更新,这样如果第 1 行被隐藏,它的子项(第 2 行)和它的子项的子项(第 5 行)也会被隐藏。
MySQL是否可行。
我已经有一个 DELETE ON CASCADE
constraint 可以正常工作。
CONSTRAINT FK_ID_With_CascadeDelete FOREIGN KEY (parent_id) REFERENCES MyTable (id) ON DELETE CASCADE
我认为你根本做不到。即使使用 UPDATE TRIGGER,您也无法更新同一 table 上的其他行。
也许这不是您期望的答案,但您最好的选择可能是使用这样的过程:
DELIMITER //
CREATE PROCEDURE UpdateHiden(IN pid INT, IN phidden INT)
BEGIN
UPDATE mytable
SET HIDDEN = phidden
WHERE ID = pid OR parent_id = pid;
END; //
DELIMITER ;
查看 DB 上的示例 Fiddle here
您可以按如下方式使用存储过程。
DELIMITER $$
DROP PROCEDURE IF EXISTS `update_node`$$
CREATE PROCEDURE `update_node`(IN p_id INT)
proc: BEGIN
DECLARE e_no_id CONDITION FOR SQLSTATE '45000';
IF ( p_id IS NULL ) THEN
SIGNAL e_no_id SET MESSAGE_TEXT = 'The id cannot be empty.';
LEAVE proc;
END IF;
DROP TEMPORARY TABLE IF EXISTS del_temp_table;
CREATE TEMPORARY TABLE IF NOT EXISTS del_temp_table(
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
delids INTEGER UNSIGNED NOT NULL,
node INTEGER DEFAULT 0
);
SET @rept := @loopcount := 1;
INSERT INTO del_temp_table (delids, node) SELECT p_id, @rept;
myloop: WHILE (1 = 1)
DO
SELECT COUNT(id) AS cnt FROM test WHERE `parent_id` IN ( SELECT DISTINCT(delids) FROM del_temp_table WHERE node = @rept ) INTO @loopcount;
IF (@loopcount = 0) THEN
LEAVE myloop;
ELSE
SET @rept := @rept + 1;
SELECT GROUP_CONCAT(d1.delids) INTO @wherein FROM ( SELECT DISTINCT(delids) FROM del_temp_table WHERE node = (@rept - 1) ) AS d1;
INSERT INTO del_temp_table (delids, node) SELECT id, @rept FROM test WHERE FIND_IN_SET( parent_id, @wherein ) > 0;
END IF ;
END WHILE myloop;
UPDATE test SET hidden = 1 WHERE id IN ( SELECT delids FROM del_temp_table );
END$$
DELIMITER ;
在这里,我使用临时 table 来存储递归节点,并通过使用 table 每次迭代来获取下一个子节点并将其插入到相同的 table.
我相信这可以帮助你。 将 table 姓名 test
替换为您的 table 姓名
我有一个 MySQL table,其中每个记录都引用其 parent_id :
| id | Summary | parent_id | hidden |
-------------------------------------
| 1 | First | NULL | 0 |
| 2 | Hello | 1 | 0 |
| 3 | john | 1 | 0 |
| 4 | Second | NULL | 0 |
| 5 | World | 2 | 0 |
| 6 | Doe | 4 | 0 |
我想级联更新,这样如果第 1 行被隐藏,它的子项(第 2 行)和它的子项的子项(第 5 行)也会被隐藏。
MySQL是否可行。
我已经有一个 DELETE ON CASCADE
constraint 可以正常工作。
CONSTRAINT FK_ID_With_CascadeDelete FOREIGN KEY (parent_id) REFERENCES MyTable (id) ON DELETE CASCADE
我认为你根本做不到。即使使用 UPDATE TRIGGER,您也无法更新同一 table 上的其他行。 也许这不是您期望的答案,但您最好的选择可能是使用这样的过程:
DELIMITER //
CREATE PROCEDURE UpdateHiden(IN pid INT, IN phidden INT)
BEGIN
UPDATE mytable
SET HIDDEN = phidden
WHERE ID = pid OR parent_id = pid;
END; //
DELIMITER ;
查看 DB 上的示例 Fiddle here
您可以按如下方式使用存储过程。
DELIMITER $$
DROP PROCEDURE IF EXISTS `update_node`$$
CREATE PROCEDURE `update_node`(IN p_id INT)
proc: BEGIN
DECLARE e_no_id CONDITION FOR SQLSTATE '45000';
IF ( p_id IS NULL ) THEN
SIGNAL e_no_id SET MESSAGE_TEXT = 'The id cannot be empty.';
LEAVE proc;
END IF;
DROP TEMPORARY TABLE IF EXISTS del_temp_table;
CREATE TEMPORARY TABLE IF NOT EXISTS del_temp_table(
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
delids INTEGER UNSIGNED NOT NULL,
node INTEGER DEFAULT 0
);
SET @rept := @loopcount := 1;
INSERT INTO del_temp_table (delids, node) SELECT p_id, @rept;
myloop: WHILE (1 = 1)
DO
SELECT COUNT(id) AS cnt FROM test WHERE `parent_id` IN ( SELECT DISTINCT(delids) FROM del_temp_table WHERE node = @rept ) INTO @loopcount;
IF (@loopcount = 0) THEN
LEAVE myloop;
ELSE
SET @rept := @rept + 1;
SELECT GROUP_CONCAT(d1.delids) INTO @wherein FROM ( SELECT DISTINCT(delids) FROM del_temp_table WHERE node = (@rept - 1) ) AS d1;
INSERT INTO del_temp_table (delids, node) SELECT id, @rept FROM test WHERE FIND_IN_SET( parent_id, @wherein ) > 0;
END IF ;
END WHILE myloop;
UPDATE test SET hidden = 1 WHERE id IN ( SELECT delids FROM del_temp_table );
END$$
DELIMITER ;
在这里,我使用临时 table 来存储递归节点,并通过使用 table 每次迭代来获取下一个子节点并将其插入到相同的 table.
我相信这可以帮助你。 将 table 姓名 test
替换为您的 table 姓名