यदि आप MySQL 8.0 का उपयोग करते हैं या MariaDB 10.2 (या उच्चतर) आप पुनरावर्ती सीटीई (सामान्य तालिका भाव) को आजमा सकते हैं ।
निम्न स्कीमा और डेटा को मानते हुए:
CREATE TABLE `list_relation` (
`child_id` int unsigned NOT NULL,
`parent_id` int unsigned NOT NULL,
PRIMARY KEY (`child_id`,`parent_id`)
);
insert into list_relation (child_id, parent_id) values
(2,1),
(3,1),
(4,2),
(4,3),
(5,3);
अब आप child_id = 1
. के साथ एक नई पंक्ति डालने का प्रयास करें और parent_id = 4
. लेकिन इससे चक्रीय संबंध बनेंगे (1->4->2->1 और 1->4->3->1 ), जिसे आप रोकना चाहते हैं। यह पता लगाने के लिए कि क्या कोई उल्टा संबंध पहले से मौजूद है, आप निम्न क्वेरी का उपयोग कर सकते हैं, जो सूची 4 के सभी माता-पिता को दिखाएगा। (विरासत में मिले/सकर्मक माता-पिता सहित):
set @new_child_id = 1;
set @new_parent_id = 4;
with recursive rcte as (
select *
from list_relation r
where r.child_id = @new_parent_id
union all
select r.*
from rcte
join list_relation r on r.child_id = rcte.parent_id
)
select * from rcte
परिणाम होगा:
child_id | parent_id
4 | 2
4 | 3
2 | 1
3 | 1
आप परिणाम में देख सकते हैं कि सूची 1 सूची 4 . के माता-पिता में से एक है , और आप नया रिकॉर्ड नहीं डालेंगे।
चूंकि आप केवल यह जानना चाहते हैं कि क्या सूची 1 परिणाम में है, आप अंतिम पंक्ति को
. में बदल सकते हैंselect * from rcte where parent_id = @new_child_id limit 1
या करने के लिए
select exists (select * from rcte where parent_id = @new_child_id)
BTW:आप निरर्थक संबंधों को रोकने के लिए उसी क्वेरी का उपयोग कर सकते हैं। मान लें कि आप child_id = 4
के साथ रिकॉर्ड सम्मिलित करना चाहते हैं। और parent_id = 1
. यह अनावश्यक होगा, क्योंकि सूची 4 सूची 1 . को पहले से ही इनहेरिट किया गया है सूची 2 . से अधिक और सूची 3 . निम्नलिखित प्रश्न आपको दिखाएगा कि:
set @new_child_id = 4;
set @new_parent_id = 1;
with recursive rcte as (
select *
from list_relation r
where r.child_id = @new_child_id
union all
select r.*
from rcte
join list_relation r on r.child_id = rcte.parent_id
)
select exists (select * from rcte where parent_id = @new_parent_id)
और आप सभी विरासत में मिली वस्तुओं को प्राप्त करने के लिए एक समान क्वेरी का उपयोग कर सकते हैं:
set @list = 4;
with recursive rcte (list_id) as (
select @list
union distinct
select r.parent_id
from rcte
join list_relation r on r.child_id = rcte.list_id
)
select distinct i.*
from rcte
join item i on i.list_id = rcte.list_id