Find circular references in single table

,

The objective is to find circular references in a single table related to itself. The script deals with a sample table Skills that have a SkilGUID (primary key) field and a SkilParentGUID field which is a foreign key to the record's parent from the same table. The number of levels in the hierarchy is not limited. Of course, the highest object in a hierarchy will have NULL in ParentGUID field. Here the datatype for GUIDs is uniqueidentifier but it may as well be an int or whatever.

The script is rather straightforward and simple - it just returns the GUIDs engaged in circular references. Of course it may be enhanced in many possible ways.

SET NOCOUNT ON

DECLARE 
@BaseGUID uniqueidentifier,
@NextGUID uniqueidentifier,
@ParentGUID uniqueidentifier

CREATE TABLE #Temp 
(GUID uniqueidentifier)
CREATE TABLE #CircularGUIDS 
(CircGUID uniqueidentifier)

DECLARE TCursor CURSOR FAST_FORWARD LOCAL FOR
SELECT SkilGUID FROM Skills WHERE SkilGUID IS NOT NULL
OPEN TCursor

FETCH NEXT FROM TCursor INTO @BaseGUID
WHILE @@FETCH_STATUS = 0
	BEGIN
		TRUNCATE TABLE #Temp

		SELECT @ParentGUID = SkilParentGUID FROM Skills WHERE SkilGUID = @BaseGUID
		INSERT INTO #Temp (GUID) VALUES (@ParentGUID)
		SET @NextGUID = @ParentGUID

NextIteration:
		SELECT @ParentGUID = SkilParentGUID FROM Skills WHERE SkilGUID = @NextGUID
		IF @ParentGUID NOT IN (SELECT GUID FROM #Temp) AND @ParentGUID IS NOT NULL
			BEGIN
				SET @NextGUID = @ParentGUID
				INSERT INTO #Temp (GUID) VALUES (@ParentGUID)
				GOTO NextIteration
			END

		IF @ParentGUID IN (SELECT GUID FROM #Temp)
			BEGIN
				INSERT INTO #CircularGUIDS (CircGUID) VALUES (@ParentGUID)
			END

		 FETCH NEXT FROM TCursor INTO @BaseGUID

	END

CLOSE TCursor
DEALLOCATE TCursor

SELECT * FROM #CircularGUIDS

DROP TABLE #Temp
DROP TABLE #CircularGUIDS

Rate

3.67 (3)

Share

Share

Rate

3.67 (3)