下面的SQL根据表之间的关系将它们分开。问题出在3000系列中排序的表。属于外键并使用外键的表。任何人最好有一些聪明的递归CTE或存储过程来进行必要的排序?程序与数据库的连接不被视为解决方案。
编辑:我在第一个解决方案的基础上将答案发布在“答案”中,任何人都可以将自己的“正确”答案重新发布为免费!
WITH AllTables(TableName) AS ( SELECT OBJECT_SCHEMA_NAME(so.id) +'.'+ OBJECT_NAME(so.id) FROM dbo.sysobjects so INNER JOIN sys.all_columns ac ON so.ID = ac.object_id WHERE so.type = 'U' AND ac.is_rowguidcol = 1 ), Relationships(ReferenceTableName, ReferenceColumnName, TableName, ColumnName) AS ( SELECT OBJECT_SCHEMA_NAME (fkey.referenced_object_id) + '.' + OBJECT_NAME (fkey.referenced_object_id) AS ReferenceTableName ,COL_NAME(fcol.referenced_object_id, fcol.referenced_column_id) AS ReferenceColumnName ,OBJECT_SCHEMA_NAME (fkey.parent_object_id) + '.' + OBJECT_NAME(fkey.parent_object_id) AS TableName ,COL_NAME(fcol.parent_object_id, fcol.parent_column_id) AS ColumnName FROM sys.foreign_keys AS fkey INNER JOIN sys.foreign_key_columns AS fcol ON fkey.OBJECT_ID = fcol.constraint_object_id ), NotReferencedOrReferencing(TableName) AS ( SELECT TableName FROM AllTables EXCEPT SELECT TableName FROM Relationships EXCEPT SELECT ReferenceTableName FROM Relationships ), OnlyReferenced(Tablename) AS ( SELECT ReferenceTableName FROM Relationships EXCEPT SELECT TableName FROM Relationships ), -- These need to be sorted based on theire internal relationships ReferencedAndReferencing(TableName, ReferenceTableName) AS ( SELECT r1.Tablename, r2.ReferenceTableName FROM Relationships r1 INNER JOIN Relationships r2 ON r1.TableName = r2.ReferenceTableName ), OnlyReferencing(TableName) AS ( SELECT Tablename FROM Relationships EXCEPT SELECT ReferenceTablename FROM Relationships ) SELECT TableName, 1000 AS Sorting FROM NotReferencedOrReferencing UNION SELECT TableName, 2000 AS Sorting FROM OnlyReferenced UNION SELECT TableName, 3000 AS Sorting FROM ReferencedAndReferencing UNION SELECT TableName, 4000 AS Sorting FROM OnlyReferencing ORDER BY Sorting
感谢您提供有效的解决方案NXC。您使我走上了正确的道路,以使用递归CTE解决问题。
WITH TablesCTE(TableName, TableID, Ordinal) AS ( SELECT OBJECT_SCHEMA_NAME(so.id) +'.'+ OBJECT_NAME(so.id) AS TableName, so.id AS TableID, 0 AS Ordinal FROM dbo.sysobjects so INNER JOIN sys.all_columns ac ON so.ID = ac.object_id WHERE so.type = 'U' AND ac.is_rowguidcol = 1 UNION ALL SELECT OBJECT_SCHEMA_NAME(so.id) +'.'+ OBJECT_NAME(so.id) AS TableName, so.id AS TableID, tt.Ordinal + 1 AS Ordinal FROM dbo.sysobjects so INNER JOIN sys.all_columns ac ON so.ID = ac.object_id INNER JOIN sys.foreign_keys f ON (f.parent_object_id = so.id AND f.parent_object_id != f.referenced_object_id) INNER JOIN TablesCTE tt ON f.referenced_object_id = tt.TableID WHERE so.type = 'U' AND ac.is_rowguidcol = 1 ) SELECT DISTINCT t.Ordinal, t.TableName FROM TablesCTE t INNER JOIN ( SELECT TableName as TableName, Max (Ordinal) as Ordinal FROM TablesCTE GROUP BY TableName ) tt ON (t.TableName = tt.TableName AND t.Ordinal = tt.Ordinal) ORDER BY t.Ordinal, t.TableName
为了使自己想知道这有什么用:我将使用它来安全地清空数据库,而不会违反任何外键关系。(通过降序截断)我还可以通过按升序填充表来安全地用来自另一个数据库的数据填充表。