我正在尝试编写一个递归公用表表达式,该表达式通过外键创建所有表的树结构,但是我会遇到具有多对多关系的表。任何人都可以为我解决这个问题吗? / p>
第一个选择是获取所有外键。第二种是递归地将它们与父/子连接相关联。递归在表2停止,即使有表3的链接。有人可以帮忙吗? (在编辑中添加了表格)。
CREATE TABLE [db].[table_one]
(
[table_one_id] int NOT NULL PRIMARY KEY, [one_column_one] int, [one_column_two] varchar(8), [one_column_three] varchar(7)
)
CREATE TABLE [db].[table_two]
(
[table_two_id] int NOT NULL PRIMARY KEY, [table_one_id] int, [table_three_id] int, [two_column_one] int, [two_column_two] varchar(8), [two_column_three] varchar(7)
)
CREATE TABLE [db].[table_three]
(
[table_three_id] int NOT NULL PRIMARY KEY, [table_four_id] int, [column_one] int, [column_two] varchar(8), [column_three] varchar(7)
)
CREATE TABLE [db].[table_four]
(
[table_four_id] int NOT NULL PRIMARY KEY, [column_one] int, [column_two] varchar(8), [column_three] varchar(7)
)
ALTER TABLE [db].[table_two] ADD CONSTRAINT [fk_table_one_table_two] FOREIGN KEY ([table_one_id]) REFERENCES [db].[table_one] ([table_one_id])
ALTER TABLE [db].[table_two] ADD CONSTRAINT [fk_table_three_table_two] FOREIGN KEY ([table_three_id]) REFERENCES [db].[table_three] ([table_three_id])
ALTER TABLE [db].[table_three] ADD CONSTRAINT [fk_table_four_table_three] FOREIGN KEY ([table_four_id]) REFERENCES [db].[table_four] ([table_four_id])
DECLARE @table_name as varchar(25) = 'table_one';
DECLARE @false as Bit = 0, @true as Bit = 1;
with relationship_tables as
(
select s1.name as child_schema,
o1.Name as child_table,
s2.name as parent_schema,
o2.Name as parent_table
from sys.foreign_keys fk
inner join sys.objects o1 on fk.parent_object_id = o1.object_id
inner join sys.schemas s1 on o1.schema_id = s1.schema_id
inner join sys.objects o2 on fk.referenced_object_id = o2.object_id
inner join sys.schemas s2 on o2.schema_id = s2.schema_id
where not (s1.name = s2.name and o1.name = o2.name) /*exclude self-referencing*/
)
,
hierarchy AS
(
SELECT rt.parent_schema,
rt.parent_table,
s.name as child_schema,
t.name as child_table,
CONVERT(VARCHAR(4096), '>' + CONVERT(VARCHAR(50), t.name ) + '>' ) as path,
@false as Loop, 0 AS Level
FROM (select * from sys.tables where name <> 'sysdiagrams') t
INNER JOIN sys.schemas s on t.schema_id = s.schema_id
LEFT OUTER JOIN relationship_tables rt ON s.name = rt.child_schema AND t.name = rt.child_schema
WHERE rt.parent_schema IS NULL
AND t.name LIKE '%' + @table_name + '%'
UNION ALL
SELECT rt.parent_schema,
rt.parent_table,
rt.child_schema,
rt.child_table,
CONVERT(VARCHAR(4096), path + CONVERT(VARCHAR(50), rt.child_table ) + '>' ),
CASE WHEN CHARINDEX( '>' + CONVERT(VARCHAR(50), rt.child_table ) + '>', PATH) = 0 THEN @false ELSE @true END,
hr.Level + 1
FROM relationship_tables rt
INNER JOIN hierarchy hr ON rt.parent_schema = hr.child_schema AND rt.parent_table = hr.child_table
WHERE hr.Loop = 0
)
select parent_table, child_table, path, level from hierarchy
order by level
这是另一项不起作用的尝试:
declare @Objects_In_Objects table
(
ObjectID varchar(25),
ParentObjectId varchar(25)
)
declare @Objects table
(
ObjectId varchar(25),
Name varchar(50)
)
insert into @Objects values
('db.table_one', 'Start table'),
('db.table_two', 'Many to Many'),
('db.table_three', 'Related Table'),
('db.table_four', 'Related Table')
--ObjectID--ParentObjectId
insert into @Objects_In_Objects values
('db.table_one', 'db.table_two'),
('db.table_three', 'db.table_two'),
('db.table_four', 'db.table_three')
DECLARE @ObjectId varchar(25)
SET @ObjectId = 'db.table_one';
;WITH Tree AS
(
SELECT A.ObjectID, A.Name, o.ParentObjectID, 1 AS 'Level'
FROM @Objects A
INNER JOIN @Objects_In_Objects o ON A.ObjectID = o.ParentObjectID OR A.ObjectId = o.ObjectID
WHERE A.ObjectId = @ObjectId -- use the A.ObjectId here
UNION ALL
SELECT A2.ObjectID, A2.Name, B.ParentObjectID, t.Level + 1 AS 'Level'
FROM Tree t
INNER JOIN @Objects_In_Objects B ON B.ParentObjectID = t.ObjectID
INNER JOIN @Objects A2 ON A2.ObjectId = B.ObjectId
)
SELECT *
FROM Tree
INNER JOIN @Objects ar on tree.ObjectId = ar.ObjectId