【问题标题】:How to find foreign key dependencies of a specific row?如何查找特定行的外键依赖项?
【发布时间】:2011-11-28 18:59:28
【问题描述】:

如果我有一张桌子,TableA:

Id
1
2
3
...

还有另外两个表:

表B:

Id, TableAId
1   1
2   1

表C:

Id, TableAId
1,  1
2,  2

其中 TableAId 是与 TableA.Id 的 FK 关系。

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

【问题讨论】:

  • 你的目标并不完全清楚。您是想查找元数据以识别表之间的外键关系,还是希望 TSql 查询在您已经知道外键关系的情况下找到数据?
  • 我对元数据不感兴趣。在我的示例中,我展示了我对确定依赖于另一个特定行的表和特定行的兴趣。我想在不编写(可能)巨大的选择语句的情况下获取该信息,将每个可能的表与目标表连接在一起。

标签: sql-server


【解决方案1】:

您可以使用INFORMATION_SCHEMA 视图生成选择语句来显示有问题的行。我仅针对问题中提供的表格对此进行了测试,但可以将其扩展为在键为多列的情况下工作。

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 * 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

【讨论】:

  • 您好,能否给我等效的Mysql代码。
【解决方案2】:

我在这台计算机上没有 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. 使用游标遍历此查询的结果,并为每个生成和执行动态 sql,该 sql 将连接 TableA 和从游标检索的表并返回 FK_TBL_NM(TableB,TableC,...)和 fk 列的值。

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

现在您的表格包含TableBTableC、...中每一行的一行

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

请注意,您可能应该让您的代码与多于一列的 pk/fk 一起使用。列也有不同的数据类型。它使事情有点复杂,但这是可能的。

我上面列出的每个步骤都不难实现。但是,如果您有任何困难,请在 stackoverflow 上搜索 :)

【讨论】:

    【解决方案3】:

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

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

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

    一旦您获得了这些信息,就可以在TableA 和涉及的任何其他表之间进行非常简单的 JOIN。

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

    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...
    

    【讨论】:

    • @KirkWoll:是的,我知道 - 但数据级别的那些依赖关系仅基于模式存在!如果您不知道 what 其他表引用 TableA,则您无法从其他表中找出哪些 rows 引用行在你的TableA
    • 确实知道架构级别的依赖关系。但这并没有告诉我如何找到数据依赖关系。如何找到依赖的?在实践中,我有大约 20-30 个表都指向这个表。创建大规模连接是唯一的方法吗?
    • @KirkWoll:如果您不知道这些行可能在哪些其他表中引用您在TableA 中的行,您想如何查找数据依赖关系?您首先需要 schema 依赖项 - THEN(并且只有 THEN)才能查找数据依赖项....
    • 好的,感谢您的帮助。我希望不需要编写包含大量连接的大量选择语句。例如,尝试删除具有此类依赖关系的行是找出将被违反的 FK 的一种快速简便的方法。我只是希望有类似的东西,而不必实际尝试删除。
    • @KirkWoll:我不知道有任何这种“神奇”的方式来删除所有内容 - 当然,除非你在 FK 关系中使用 ON DELETE CASCADE
    猜你喜欢
    • 2010-10-29
    • 2011-06-20
    • 2018-02-23
    • 1970-01-01
    • 1970-01-01
    • 2016-05-24
    • 2015-09-06
    • 2015-06-27
    • 2013-04-13
    相关资源
    最近更新 更多