I'm wanting to create a subset of data for testing purposes, where I start with a Users table, select X of type a, Y of type b, Z of type c (and so on), and create a new table containing those users. I then need to to create all related tables (with the necessary records), and then all related tables to those...
I'm fairly certain the best way to do this is a recursive common table expression, however I don't have much experience with those and was hoping someone could help me out. So far I have the below, but have noticed two things:
- Level 2 seems to contain everything that was in level 1, in addition to the new records I'd expect
This doesn't actually create/insert the records yet (I still need help with that)
WITH cte AS ( SELECT DISTINCT fk.object_id, fk.schema_id, fk.parent_object_id, fc.parent_column_id, t.schema_id AS referenced_schema_id, fk.referenced_object_id, ic.column_id AS referenced_column_id, 1 AS Level FROM sys.foreign_keys fk INNER JOIN sys.tables t ON fk.referenced_object_id = t.object_id INNER JOIN sys.foreign_key_columns fc ON fk.object_id = fc.constraint_object_id INNER JOIN sys.indexes i ON fk.referenced_object_id = i.object_id AND i.is_primary_key = 1 INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id WHERE fk.type = 'F' AND fk.referenced_object_id = OBJECT_ID(N'dbo.Users', N'U') UNION ALL SELECT fk.object_id, fk.schema_id, fk.parent_object_id, fc.parent_column_id, t.schema_id, fk.referenced_object_id, ic.column_id AS referenced_column_id, cte.Level + 1 FROM sys.foreign_keys fk INNER JOIN sys.tables t ON fk.referenced_object_id = t.object_id INNER JOIN sys.foreign_key_columns fc ON fk.object_id = fc.constraint_object_id INNER JOIN sys.indexes i ON fk.referenced_object_id = i.object_id AND i.is_primary_key = 1 INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id INNER JOIN cte ON fk.referenced_object_id = cte.parent_object_id WHERE fk.type = 'F' AND fk.parent_object_id <> cte.referenced_object_id ), cteHierarchy AS ( SELECT DISTINCT OBJECT_NAME(cte.object_id) AS ReferringKey, SCHEMA_NAME(cte.schema_id) AS ReferringSchema, OBJECT_NAME(cte.parent_object_id) as ReferringTable, COL_NAME(cte.parent_object_id,cte.parent_column_id) ReferringColumn, SCHEMA_NAME(cte.referenced_schema_id) AS ReferencedSchema, OBJECT_NAME(cte.referenced_object_id) as ReferencedTable, COL_NAME(cte.referenced_object_id,cte.referenced_column_id) ReferencedColumn, Level FROM cte ) SELECT * FROM cteHierarchy ORDER BY Level, ReferencedSchema, ReferencedTable, ReferringTable;
Thank you for your assistance!