Hier ist eine hierarchische Abfrage auf sys.foreign_keys, die Sie ziemlich nah an was Sie suchen.
WITH cte AS (
-- find tables that are parents, but are not children themselves
SELECT [fk].[referenced_object_id] AS [child_id],
NULL AS [parent_id],
CAST(CONCAT('/', [fk].[referenced_object_id], '/') AS VARCHAR(MAX)) AS h,
1 AS l
FROM sys.[foreign_keys] AS [fk]
WHERE [fk].[referenced_object_id] NOT IN (
SELECT [parent_object_id]
FROM sys.[foreign_keys]
)
UNION ALL
SELECT child.[parent_object_id],
[child].[referenced_object_id] AS [parent_id],
CAST(CONCAT(parent.[h], child.[parent_object_id], '/') AS VARCHAR(MAX)) AS [h],
parent.l + 1 AS l
FROM cte AS [parent]
JOIN sys.[foreign_keys] AS [child]
ON [parent].[child_id] = child.[referenced_object_id]
),
hier AS (
SELECT DISTINCT
OBJECT_NAME([cte].[child_id]) AS [child],
object_name([cte].[parent_id]) AS [parent],
h,
--CAST([cte].[h] AS HIERARCHYID) AS h
l
FROM cte
)
SELECT [hier].[child] ,
[hier].[parent] ,
[hier].[h]--.ToString()
FROM [hier]
ORDER BY
l, h -- breadth-first search
--h, l -- depth-first search
--h.GetLevel(), h -- breadth-first search; hierarchyid
--h, h.GetLevel() -- depth-first search; hierarchyid
Sie werden feststellen, dass ich zwei Order by Klauseln enthalten. Jeder hat seine Verwendung. Angenommen, Sie haben die folgenden getrennten Diagramme von Fremdschlüsseln: (a → b → c), (d → e → f). Wenn Sie die Klausel "order by order" verwenden, werden Zeilen in der folgenden Reihenfolge zurückgegeben: a, d, b, e, c, f. Das heißt, alle Elemente der obersten Ebene zuerst, gefolgt von den Elementen der Ebene zwei usw. Die Klausel zweiter Ordnung by gibt sie in der Reihenfolge a, b, c, d, e, f (oder vielleicht d, e zurück , f, a, b, c, abhängig von den Objekt-IDs für a und d). Die Idee hier ist, dass Sie einen getrennten Graphen vollständig erschöpfen, bevor Sie zum nächsten gehen.
Eine Anmerkung ist, dass ich ziemlich sicher bin, dass das oben genannte nicht selbstreferenzielle Fremdschlüssel berücksichtigt. Wenn das für Sie wichtig ist, würde ich diese als separate Aktion behandeln (d. H. Füllen Sie diese zuerst vollständig aus und suchen Sie dann die nicht-selbstreferenziellen Beziehungen mit dem oben genannten).
Ich habe auch ein oder zwei Kommentare da drin, um eine Hierarchie-Lösung funktionieren zu lassen. Verwenden Sie in der hier
cte das Casting von h
zu hierarchyid statt h und verwenden Sie dann die order by-Klauseln, die davon profitieren. Nichts davon ist notwendig, aber könnte eine gute erste Exposition gegenüber der Hierarchie sein.
Sie müssen ein Netzwerkproblem lösen, um dies zu erreichen, und ich denke, es ist alles andere als trivial. –