如何查找特定行的外键依赖项?

时间:2011-09-30 21:12:41

标签: sql-server

如果我有桌子,TableA:

Id
1
2
3
...

还有另外两张表:

表B:

Id, TableAId
1   1
2   1

表C:

Id, TableAId
1,  1
2,  2

TableAId与TableA.Id。

的FK关系

如何确定TableA,Id 1有三行指向它?那个TableA,Id 2有一行指向它吗?更具体地说,我如何识别这些行是什么? (他们的表名和Id)

3 个答案:

答案 0 :(得分:15)

您可以使用INFORMATION_SCHEMA视图生成select语句以显示相关行。我只针对问题中提供的表进行了测试,但它可以扩展为在密钥为多列的情况下工作。

declare @table_schema nvarchar(50) = 'dbo',
        @table_name nvarchar(50) = 'TableA',
        @id int = 1

select fk_col.TABLE_SCHEMA, fk_col.TABLE_NAME, fk_col.COLUMN_NAME, 
    'select * from ' + fk_col.TABLE_SCHEMA + '.' + fk_col.TABLE_NAME + ' t1 '
        + ' inner join ' + @table_schema + '.' + @table_name + ' t2 '
        + ' on t1.' + fk_col.COLUMN_NAME + ' = t2.' + pk_col.COLUMN_NAME
        + ' where t2.' + pk_col.COLUMN_NAME + ' = ' + cast(@id as nvarchar)

from INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk

    join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE pk_col
        on pk.CONSTRAINT_SCHEMA = pk_col.CONSTRAINT_SCHEMA
        and pk.CONSTRAINT_NAME = pk_col.CONSTRAINT_NAME

    join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS fk 
        on pk.CONSTRAINT_SCHEMA = fk.UNIQUE_CONSTRAINT_SCHEMA 
        and pk.CONSTRAINT_NAME = fk.UNIQUE_CONSTRAINT_NAME

    join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE fk_col
        on fk_col.CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA
        and fk_col.CONSTRAINT_NAME = fk.CONSTRAINT_NAME

where pk.TABLE_SCHEMA = @table_schema 
    and pk.TABLE_NAME = @table_name
    and pk.CONSTRAINT_TYPE = 'PRIMARY KEY'

生成的select语句:

select * from dbo.TableB t1  inner join dbo.TableA t2  on t1.TableAId = t2.Id where t2.Id = 1
select * from dbo.TableC t1  inner join dbo.TableA t2  on t1.TableAId = t2.Id where t2.Id = 1

和查询结果:

Id          TableAId    Id
----------- ----------- -----------
1           1           1
2           1           1

Id          TableAId    Id
----------- ----------- -----------
1           1           1

答案 1 :(得分:4)

我在这台电脑上没有SQL,所以我不能给你确切的代码,但这是你应该去的方式。请注意,我将使用SQL Server术语。

如果没有动态sql,我认为没有办法做到这一点,至少在SQL Server中是这样。

  1. 使用列FK_TBL_NMFK_CLMN_VAL创建临时表#t。
  2. 获得TableA的pk的所有fk关系应该不难:

    SELECT *  FROM sys.foreign_keys 
    WHERE referenced_object_id = OBJECT_ID('TableA') 
    
  3. 使用游标迭代此查询的结果,并为每个生成并执行将加入TableA的动态sql和从游标检索的表并返回FK_TBL_NM(TableB,TableC, ...)和fk列的值。

  4. 将结果插入到#t(将动态sql结果放入表中但是对stackoverflow进行研究是很棘手的)

  5. 现在,您的表格在TableBTableC,... {/ p>中的每一行都包含一行

    我知道这是可行的,因为我在几天前为我当前的项目编写了类似逻辑的代码。

    请注意,您应该使用pk / fk使用更多的一列来使用您的代码。列也有不同的数据类型。它使事情变得复杂但是有可能。

    上面列出的每一步都不难实现。但是,如果您遇到任何困难,请搜索stackoverflow:)

答案 2 :(得分:2)

为了找出存在哪些FK关系,您需要检查SQL Server中的sys目录视图 - 类似于:

SELECT * 
FROM sys.foreign_keys
WHERE referenced_object_id = OBJECT_ID('TableA')

这将列出TableA存在的所有外键关系。

获得该信息之后,TableA与所涉及的任何其他表之间的联接非常简单。

更新:一旦您知道,例如TableBTableC引用您的TableA,您可以通过简单的JOIN找到depdendent行:

SELECT c.*
FROM dbo.TableC c
INNER JOIN dbo.TableA a ON a.ID = c.TableAID  -- or whatever column joins the tables.....
WHERE.......  -- possibly with a WHERE clause...