簡體   English   中英

如何在MySQL中查找所有子行?

[英]How to find all child rows in MySQL?

我有一個層次結構系統設置程序,用於在數據庫中存儲項目的級別和父ID。 我要弄清楚的是,如何找到用戶選擇的所有子行。 這是表結構的示例:

+----+---------+----------+-------+
| Id |  label  | parentid | level |
+----+---------+----------+-------+
|  1 | honda   |        0 |     1 |
|  2 | accord  |        1 |     2 |
|  3 | civic   |        1 |     2 |
|  4 | element |        1 |     2 |
|  5 | v4      |        2 |     3 |
|  6 | v6      |        2 |     3 |
+----+---------+----------+-------+

因此,如果有人刪除honda ,我將如何刪除層次結構中的所有內容? 數據庫將只能降級到3級。

參考, 帶關系innoDB的遞歸MySQL查詢

我昨天發布了同樣的答案

更新:

以下是基於以上鏈接的function ,但已根據您的DELETE要求進行了量身定制

CREATE PROCEDURE `delete_relations`(`_id` INT)
BEGIN
DECLARE  delete_row_ids varchar(200);
DECLARE id, id2 varchar(200);
DECLARE rows_affected int;

SET delete_row_ids  = _id;
SET id              = _id;
SET id2             = id;

WHILE id2 IS NOT NULL DO 
    SET id = NULL;
    SELECT GROUP_CONCAT( hierarchical_data.id ), CONCAT( GROUP_CONCAT( hierarchical_data.ID ),',',delete_row_ids) INTO id, delete_row_ids FROM hierarchical_data WHERE FIND_IN_SET( parentid , id2 ) GROUP BY parentid ;
    SET id2 = id;
END WHILE;  

DELETE FROM hierarchical_data where FIND_IN_SET(hierarchical_data.id, delete_row_ids);
SELECT row_count() INTO rows_affected;

if rows_affected > 0 THEN
SELECT delete_row_ids as row_ids_deleted;
ELSE
SELECT 'NO_ROWS_DELETED';
END IF;

END//

SQLFiddle

采用

CALL delete_relations(1)

刪除id = 1 honda所有條目及其關系

希望對您有所幫助

:id替換為以下要刪除的根條目ID:

DELETE FROM table
WHERE
   id = :id 
   OR id IN (  
-- first level
SELECT DISTINCT id sid
FROM table
WHERE parentid = :id
-- second level
UNION
SELECT DISTINCT t2.id sid
FROM table t1
INNER JOIN table t2
ON t1.id = t2.parentid
WHERE t1.parentid = :id
-- third level
UNION
SELECT DISTINCT t3.id sid
FROM table t1
INNER JOIN table t2
ON t1.id = t2.parentid
INNER JOIN table t3
ON t2.id = t3.parentid
WHERE t1.id = :id
)

請注意,您有3個級別,但是根節點占據了其中一個級別,這意味着您實際上只需要選擇子級和孫級。 上面的查詢會再執行一個級別(第3個級別),因此您可以將第-- third level之后的部分刪除到右括號。

假設您使用的是具有觸發器的MySQL 5,則可以在刪除觸發器之前編寫一個小的觸發器,以輕松實現此目的。 我沒有完全檢查語法,但是將與以下內容大致匹配:

CREATE TRIGGER tr_tablename_bd BEFORE DELETE ON tablename
  FOR EACH ROW BEGIN
    DELETE FROM tablename WHERE parentID = deleted.id
END;

上面的代碼還將適用於無限級別,而不僅僅是3個級別。 您將需要刪除一行,觸發器將刪除以下級別的數據行或將已刪除的行標記為parentID的行。

但是,我隱約記得MySQL的一個問題,即它無法啟動級聯觸發器。 意味着MySQL由於觸發另一個觸發器而未能觸發觸發器。 如果您正在使用的MySQL版本(甚至最新版本)中仍然存在該錯誤,則此代碼將不起作用。 但是,從理論上講,這是完全可以的,並且可以在肯定有觸發器的所有其他數據庫上工作。 對於MySQL,您只需要檢查他們是否能夠解決該錯誤!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM