我的要求是加入表A和表D.我知道其间有表B和C,它们有PK和FK关系。我想要一个查询来了解表B和C以及关系中涉及的键。我需要知道整个数据库。数据库图将给我关系,但我没有权限查看图表。而且,我需要查找每组表。这就是我试图编写一个为我完成工作的查询的原因。
简而言之,如果我在查询中提供表A和表D,那么查询应该为我提供必要的列(在我们的例子中为B.id2,C.id3)来加入A和D.
SELECT A.*, D.* FROM A Join B on A.id1 = B.id2 Join C on B.id2 = C.id3 Join D on C.id3 = D.id4
提前致谢。
答案 0 :(得分:2)
我拉起了我在工作中写的那个;看起来我实际上并没有打扰CTE(因为他们是屁股恕我直言的皇家痛苦)。它有点冗长,因为它只是我从proc中删除的代码。我的版本最初没有包含列,但我添加了它们。我只是将它们连接起来就像它们是ON
子句一样,但你可以调整你喜欢的方式。
use AdventureWorks2014
go
declare
@BaseTable nvarchar(128) = 'SalesPerson',
@BaseTableSchema nvarchar(128) = 'Sales'
declare
@Depth int = 0,
@RowCount int,
@Ident int
declare @KeyHierarchy table
(
Depth int,
ReferencingTableSchema nvarchar(128),
ReferencingTableName nvarchar(128),
ReferencingObjectId int,
ReferencingTableNameFull as quotename(ReferencingTableSchema) + '.' + quotename(ReferencingTableName),
ReferencedTableSchema nvarchar(128),
ReferencedTableName nvarchar(128),
ReferencedObjectId int,
ReferencedTableNameFull as quotename(ReferencedTableSchema) + '.' + quotename(ReferencedTableName),
MatchingColumns nvarchar(max)
primary key clustered (ReferencingTableSchema, ReferencingTableName)
)
insert into @KeyHierarchy
(
Depth,
ReferencingTableSchema,
ReferencingTableName,
ReferencingObjectId
)
select
Depth = @Depth,
ReferencingTableSchema = @BaseTableSchema,
ReferencingTableName = @BaseTable,
ReferencingObjectId = object_id(@BaseTableSchema + '.' + @BaseTable)
select @RowCount = 1
while @RowCount > 0
begin
insert into @KeyHierarchy
(
Depth,
ReferencedTableSchema,
ReferencedTableName,
ReferencedObjectId,
ReferencingTableSchema,
ReferencingTableName,
ReferencingObjectId,
MatchingColumns
)
select distinct
Depth = @Depth + 1,
ReferencedTableSchema = object_schema_name(f.referenced_object_id),
ReferencedTableName = object_name(f.referenced_object_id),
ReferencedObjectId = f.referenced_object_id,
ReferencingTableSchema = object_schema_name(f.parent_object_id),
ReferencingTableName = object_name(f.parent_object_id),
ReferencingObjectId = f.parent_object_id,
MatchingColumns = stuff
(
(
select
concat
(
' and parent.',
quotename(col_name(c.parent_object_id, c.parent_column_id)),
' = ',
'referenced.',
quotename(col_name(c.referenced_object_id, c.referenced_column_id))
)
from sys.foreign_key_columns c
where f.object_id = c.constraint_object_id
order by c.constraint_column_id
for xml path(''), type
).value('.', 'nvarchar(max)'), 1, 4, ''
)
from @KeyHierarchy k
inner join sys.foreign_keys f
on f.referenced_object_id = k.ReferencingObjectId
and f.parent_object_id not in (select ReferencingObjectId from @KeyHierarchy where Depth < @Depth + 1)
where k.Depth = @Depth
select
@RowCount = @@RowCount,
@Depth += 1
end
select
BaseTable = @BaseTable,
ReferencingTableNameFull,
ReferencedTableNameFull,
MatchingColumns,
Depth
from @KeyHierarchy
order by Depth, ReferencingTableNameFull
答案 1 :(得分:0)
这有一些问题,但它是一个开始
select t.name [t_name], c.name [c_name], f.*
from sys.foreign_keys f
join sys.tables t
on f.parent_object_id = t.object_id
and f.type = 'F'
left join sys.columns c
on c.object_id = f.referenced_object_id
and c.system_type_id = 56
答案 2 :(得分:0)
你可以从这个出发点摆弄:
with
ForeignKeys as (
-- All foreign keys with their associated tables and columns.
select fk.name as ConstraintName, fk.object_id as ContraintObjectId,
pt.name as ParentTable, pt.object_id as ParentTableObjectId, pc.name as ParentColumn, pc.column_id as ParentColumnId,
ft.name as ForeignTable, ft.object_id as ForeignTableObjectId, fc.name as ForeignColumn, fc.column_id as ForeignColumnId
from sys.foreign_keys as fk inner join
sys.foreign_key_columns as fkc on fkc.constraint_object_id = fk.object_id inner join
sys.tables as pt on pt.object_id = fkc.parent_object_id inner join
sys.columns as pc on pc.object_id = pt.object_id and pc.column_id = fkc.parent_column_id inner join
sys.tables as ft on ft.object_id = fkc.referenced_object_id inner join
sys.columns as fc on fc.object_id = ft.object_id and fc.column_id = fkc.referenced_column_id ),
RelatedTables as (
-- All ordered pairs of directly related tables.
select distinct ParentTable, ParentTableObjectId, ForeignTable, ForeignTableObjectId
from ForeignKeys ),
RelatedTablesHierarchy as (
-- Hierarchy of related tables.
-- Start from each distinct table that has a foreign key relation ...
select ParentTable, ParentTableObjectId, ForeignTable, ForeignTableObjectId,
Cast( ParentTable + '»' + ForeignTable as NVarChar(4000) ) as Path
from RelatedTables
union all
-- ... and add any other table to which the foreign table is related.
select RTH.ParentTable, RTH.ParentTableObjectId, RT.ForeignTable, RT.ForeignTableObjectId,
Cast( Path + '»' + RT.ForeignTable as NVarChar(4000) )
from RelatedTablesHierarchy as RTH inner join
RelatedTables as RT on RT.ParentTableObjectId = RTH.ForeignTableObjectId
-- NB: Avoid getting caught in reference loops.
where '»' + Path + '»' not like '%»' + RT.ForeignTable + '»%'
)
-- Output the results with Path made a little easier to read.
select Replace( Path, '»', ' » ' ) as Path, ParentTable, ParentTableObjectId, ForeignTable, ForeignTableObjectId
from RelatedTablesHierarchy
order by Path;
初始查询肯定带有一些额外的包袱,但您需要它来确定连接所需的表名和列名。 (提示:在将对象名称组合到语句中时使用QuoteName()
。)
注意:公共表表达式对参考循环有抵抗力,例如:具有外键引用自身的表以及涉及多个表的较长循环。