2012-12-12 31 views
5

Veritabanımdaki (a) başka bir varlıktan (b) başvurulan ve belirli bir (b) varlık verilen kendiliğinden bağımlı varlıklarım var. a) Gerekli olan varlıklar. Bunlar birçok eşleştirmedir, bu yüzden ayrı bir eşleme tablosuna sahibim. CTE ile özyinelemeli bir seçmemin en iyi seçim olduğunu düşünüyorum, ancak bir sorunla karşılaşıyorum:T-SQL Recursive Seç Dairesel bağımlılık

This Fiddle Sorunumu gösterir. Bazı kullanıcılar döngüsel bir referans sunuyorsa, özyinelemeli seçimim bir çığlık atmaya öğütülür. Bunu düzeltmek için bir yol bulmaya çalışmak için beynimi karıştırıyorum. Unutulmamalıdır ki yabancı klavyeleri kemanda tanıttığım halde, yabancı anahtarlar kullandığım sistem tarafından gerçekten onurlandırılamaz (DBA'larla uzun süredir devam eden argüman) - veri akışını daha açık hale getirmek için onları tanıttım.

keman tıklama yoluyla istemeyen kişiler için özyinelemeli sorgu,: Orada

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 

Herhangi Fikirler? Bu tasarım üretimde değil, bu yüzden şemayı biraz değiştirebilirim, ancak T-SQL tarafından yapılmadığı sürece, ekleme sırasında döngüsel referansları keşfetmeye güvenmemek isterim.

+0

bu FXN hiç kullanmadım, ama sadece objMap.masterObjID = recur.objID ve recur.objID <> # otherobj.usesObjID' üzerinde 'öyle değil mi? ya da kapsam dışı mı? – Beth

cevap

8

Sonsuz döngüyü engelleyen CTE'nin MAXRECURSION ayarını yapmak mümkündür, ancak sorgunun maksimum yineleme gerçekleşene kadar döngüde çalışmaya devam etmesi nedeniyle yine de garip sonuçlar elde edersiniz.

Buradaki zorluk, döngünün birden çok adım içermesidir, bu nedenle, bir döngü içinde olup olmadığınızı belirlemek için çocuğun annesini kontrol edemezsiniz.

Bunu işlemenin bir yolu, CTE'ye ek bir sütun eklemek olacaktır ... Bu yeni sütun, tree, şu ana kadar içerilen tüm kimlikleri izler ve bir ID tekrarlandığında durur.

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

Bu harika! Sizce bu, diğerObj'den Obj'e kadar birçok haritalama için işe yarayacak mı? (Başka bir haritalama tablosunu gerekli kılar) – FrankieTheKneeMan

+0

@FrankieTheKneeMan Aynı zamanda çalışacağını düşünüyorum. Temel olarak, şu ana kadar katıldığınız kimlikleri izlemektesiniz ve bir kopya gördüğünüzde durmaya devam edersiniz. –

+0

http://sqlfiddle.com/#!3/c1e62/3 <- Kullanıcılara güvenmiyorum. Eğer yapıyı tamamen koparsa, bu sonucu alabilirim. Farklı değerler elde etmek için farklı bir yol kullanabilirim (bir başlangıç), ancak bunu yapmanın daha iyi bir yolu var mı? – FrankieTheKneeMan