2012-12-12 25 views
5

मुझे अपने डेटाबेस में स्वयं निर्भर संस्थाएं (ए) मिल गई हैं, जिन्हें किसी अन्य इकाई (बी) से संदर्भित किया गया है, और एक विशिष्ट (बी) इकाई दी गई है, मुझे सभी को प्राप्त करने की आवश्यकता है (ए) इकाइयों की जरूरत है। ये कई मैपिंग के लिए बहुत सारे हैं, इसलिए मेरे पास एक अलग मैपिंग टेबल है। मुझे लगता है कि एक सीटीई के साथ एक पुनरावर्ती चयन मेरी सबसे अच्छी शर्त है, लेकिन मैं एक समस्या में भाग रहा हूं:टी-एसक्यूएल रिकर्सिव सर्कुलर निर्भरता का चयन करें

This Fiddle मेरी समस्या का वर्णन करता है। यदि कुछ उपयोगकर्ता एक परिपत्र संदर्भ प्रस्तुत करते हैं, तो मेरा रिकर्सिव चयन एक डरावना ठहराव के लिए पीसता है। मैं इसे ठीक करने के लिए कुछ रास्ता खोजने का प्रयास करने के लिए अपने मस्तिष्क को तोड़ रहा हूं। यह ध्यान दिया जाना चाहिए कि हालांकि मैंने बेवकूफ़ों में विदेशी कुंजी पेश की है, लेकिन विदेशी कुंजी को वास्तव में उस सिस्टम द्वारा सम्मानित नहीं किया जाता है जिसका उपयोग मैं कर रहा हूं (डीबीए के साथ लंबे समय तक तर्क) - मैंने उन्हें डेटा प्रवाह को और स्पष्ट करने के लिए पेश किया।

पुनरावर्ती पूछताछ, जो बेला के लिए क्लिक करने के लिए के माध्यम से नहीं करना चाहते हैं के लिए:

WITH recur(objID) AS (
    SELECT usesObjID 
     FROM #otherObj 
     WHERE otherObjID = 1 
    UNION ALL 
    SELECT slaveObjID 
     FROM #objMap 
      INNER JOIN recur 
       on #objMap.masterObjID = recur.objID 
)SELECT objID from recur 

किसी भी वहाँ विचार? यह डिज़ाइन उत्पादन में नहीं है, इसलिए मैं कुछ हद तक स्कीमा बदल सकता हूं, लेकिन मैं प्रविष्टि पर परिपत्र संदर्भों की खोज पर भरोसा नहीं करना चाहता, जब तक यह टी-एसक्यूएल द्वारा नहीं किया जा सकता।

+0

इस FXN इस्तेमाल कभी नहीं किया है, लेकिन तुम सिर्फ यह नहीं कह 'objMap.masterObjID = recur.objID और recur.objID <> # otherobj.usesObjID' पर हैं? या वह गुंजाइश से बाहर है? – Beth

उत्तर

8

सीटीई के MAXRECURSION सेट करना संभव है, जो अनंत लूप को रोक देगा, लेकिन आपको अभी भी अजीब परिणाम मिलेंगे क्योंकि अधिकतम रिकर्सन हिट होने तक क्वेरी लूप में चलती रहेगी।

चुनौती यह है कि लूप में कई कदम शामिल हैं, इसलिए आप यह निर्धारित करने के लिए कि आप लूप में हैं या नहीं, आप केवल बच्चे के तत्काल माता-पिता की जांच नहीं कर सकते हैं।

इसे संभालने का एक तरीका सीटीई में एक अतिरिक्त कॉलम जोड़ना होगा ... यह नया कॉलम, tree, अब तक शामिल सभी आईडी ट्रैक करता है, और आईडी दोहराने पर रोकता है।

WITH recur(objID, Tree) AS (
    SELECT 
     usesObjID, 
     CAST(',' + CAST(usesObjID AS VARCHAR) + ',' AS VARCHAR) AS Tree 
    FROM otherObj 
    WHERE otherObjID = 1 
    UNION ALL 
    SELECT 
     slaveObjID, 
     CAST(recur.Tree + CAST(slaveObjID AS VARCHAR) + ',' AS VARCHAR) AS Tree 
    FROM objMap 
     INNER JOIN recur 
      ON objMap.masterObjID = recur.objID 
    WHERE recur.Tree NOT LIKE '%,' + CAST(slaveObjID AS VARCHAR) + ',%' 
)SELECT objID from recur 

Sql Fiddle Link

+0

यह बहुत अच्छा है! क्या आपको लगता है कि यह अन्य कामों के साथ-साथ ओबज से कई मैपिंग के लिए भी काम करेगा? (एक और मैपिंग टेबल की आवश्यकता) – FrankieTheKneeMan

+0

@ फ्रैंकी TheKneeMan मुझे लगता है कि यह भी काम करेगा। असल में आप अभी भी उन आईडी को ट्रैक कर रहे हैं जिन्हें आप अभी तक शामिल कर चुके हैं, और जब आप डुप्लिकेट देखते हैं तो रोकें। –

+0

http://sqlfiddle.com/#!3/c1e62/3 <- मुझे उपयोगकर्ताओं पर भरोसा नहीं है। अगर वे संरचना को पूरी तरह से तैयार करते हैं, तो मैं यह परिणाम प्राप्त कर सकता हूं। मैं अलग-अलग मूल्य प्राप्त करने के लिए एक विशिष्ट का उपयोग कर सकता हूं (वैसे भी एक शुरुआत), लेकिन क्या ऐसा करने का एक बेहतर तरीका है? – FrankieTheKneeMan