以下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
NTDLS.. 14
我的演绎中等调整:这个是SQL-2005 +,适用于没有"rowguidcol"的数据库:
WITH TablesCTE(SchemaName, TableName, TableID, Ordinal) AS ( SELECT OBJECT_SCHEMA_NAME(so.object_id) AS SchemaName, OBJECT_NAME(so.object_id) AS TableName, so.object_id AS TableID, 0 AS Ordinal FROM sys.objects AS so WHERE so.type = 'U' AND so.is_ms_Shipped = 0 UNION ALL SELECT OBJECT_SCHEMA_NAME(so.object_id) AS SchemaName, OBJECT_NAME(so.object_id) AS TableName, so.object_id AS TableID, tt.Ordinal + 1 AS Ordinal FROM sys.objects AS so INNER JOIN sys.foreign_keys AS f ON f.parent_object_id = so.object_id AND f.parent_object_id != f.referenced_object_id INNER JOIN TablesCTE AS tt ON f.referenced_object_id = tt.TableID WHERE so.type = 'U' AND so.is_ms_Shipped = 0 ) SELECT DISTINCT t.Ordinal, t.SchemaName, t.TableName, t.TableID FROM TablesCTE AS t INNER JOIN ( SELECT itt.SchemaName as SchemaName, itt.TableName as TableName, itt.TableID as TableID, Max(itt.Ordinal) as Ordinal FROM TablesCTE AS itt GROUP BY itt.SchemaName, itt.TableName, itt.TableID ) AS tt ON t.TableID = tt.TableID AND t.Ordinal = tt.Ordinal ORDER BY t.Ordinal, t.TableName
Tom.. 9
感谢您使用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
对于知道什么是可用的,我会用它来安全地清空数据库而不违反任何外键关系.(通过按降序截断)我还可以通过按升序填充表来安全地使用来自另一个数据库的数据填充表.
我的演绎中等调整:这个是SQL-2005 +,适用于没有"rowguidcol"的数据库:
WITH TablesCTE(SchemaName, TableName, TableID, Ordinal) AS ( SELECT OBJECT_SCHEMA_NAME(so.object_id) AS SchemaName, OBJECT_NAME(so.object_id) AS TableName, so.object_id AS TableID, 0 AS Ordinal FROM sys.objects AS so WHERE so.type = 'U' AND so.is_ms_Shipped = 0 UNION ALL SELECT OBJECT_SCHEMA_NAME(so.object_id) AS SchemaName, OBJECT_NAME(so.object_id) AS TableName, so.object_id AS TableID, tt.Ordinal + 1 AS Ordinal FROM sys.objects AS so INNER JOIN sys.foreign_keys AS f ON f.parent_object_id = so.object_id AND f.parent_object_id != f.referenced_object_id INNER JOIN TablesCTE AS tt ON f.referenced_object_id = tt.TableID WHERE so.type = 'U' AND so.is_ms_Shipped = 0 ) SELECT DISTINCT t.Ordinal, t.SchemaName, t.TableName, t.TableID FROM TablesCTE AS t INNER JOIN ( SELECT itt.SchemaName as SchemaName, itt.TableName as TableName, itt.TableID as TableID, Max(itt.Ordinal) as Ordinal FROM TablesCTE AS itt GROUP BY itt.SchemaName, itt.TableName, itt.TableID ) AS tt ON t.TableID = tt.TableID AND t.Ordinal = tt.Ordinal ORDER BY t.Ordinal, t.TableName
感谢您使用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
对于知道什么是可用的,我会用它来安全地清空数据库而不违反任何外键关系.(通过按降序截断)我还可以通过按升序填充表来安全地使用来自另一个数据库的数据填充表.