【问题标题】:How can I find which tables reference a given table in Oracle SQL Developer?如何在 Oracle SQL Developer 中找到哪些表引用给定表?
【发布时间】:2010-11-11 17:43:41
【问题描述】:

Oracle SQL Developer 中,如果我正在查看一个表的信息,我可以查看约束,这让我可以看到外键(以及该表引用了哪些表),我可以查看依赖项查看哪些包和此类参考表。但我不确定如何找到哪些表引用了该表。

例如,假设我正在查看emp 表。还有另一个表emp_dept,它捕获哪些员工在哪些部门工作,它通过emp_idemp 表的主键)引用emp 表。有没有办法(通过程序中的一些 UI 元素,而不是通过 SQL)找到emp_dept 表引用了emp 表,而我不必知道emp_dept 表存在?

【问题讨论】:

    标签: sql oracle foreign-keys oracle-sqldeveloper


    【解决方案1】:

    没有。 Oracle SQL Developer 没有提供这样的选项。

    您必须手动执行查询或使用其他工具(例如PLSQL Developer 有这样的选项)。以下 SQL 是 PLSQL Developer 使用的 SQL:

    select table_name, constraint_name, status, owner
    from all_constraints
    where r_owner = :r_owner
    and constraint_type = 'R'
    and r_constraint_name in
     (
       select constraint_name from all_constraints
       where constraint_type in ('P', 'U')
       and table_name = :r_table_name
       and owner = :r_owner
     )
    order by table_name, constraint_name
    

    其中r_owner 是架构,r_table_name 是您要查找参考的表。名称区分大小写


    要小心,因为在 Oracle SQL Developer 的报告选项卡上,有选项“所有表/依赖项”来自ALL_DEPENDENCIES,它指的是“过程、包、函数、包主体和触发器之间的依赖关系当前用户可以访问,包括对在没有任何数据库链接的情况下创建的视图的依赖。”。那么,这份报告对您的问题没有任何价值。

    【讨论】:

    • 感谢您的回答。对 Oracle Sql Developer 的糟糕表现感到羞耻。
    • 你提到PLSQL Developer可以做这个功能,你能解释一下吗?
    • @Nicholas,在对象浏览器中,选择一个表,右键单击一个表并选择“外键引用”
    • This answer 提到 SQL Developer 4.1 及更高版本现在有一个选项“模型”选项卡,它将以 ERD 格式显示此信息。
    • r_owner 是您正在使用的架构,r_table_name 是您正在寻找参考的表
    【解决方案2】:

    要将其作为扩展添加到 SQL Developer,请执行以下操作:

    1. 将以下代码保存到 xml 文件中(例如 fk_ref.xml):
    <items>
        <item type="editor" node="TableNode" vertical="true">
        <title><![CDATA[FK References]]></title>
        <query>
            <sql>
                <![CDATA[select a.owner,
                                a.table_name,
                                a.constraint_name,
                                a.status
                         from   all_constraints a
                         where  a.constraint_type = 'R'
                                and exists(
                                   select 1
                                   from   all_constraints
                                   where  constraint_name=a.r_constraint_name
                                          and constraint_type in ('P', 'U')
                                          and table_name = :OBJECT_NAME
                                          and owner = :OBJECT_OWNER)
                                   order by table_name, constraint_name]]>
            </sql>
        </query>
        </item>
    </items>
    
    1. 将扩展添加到 SQL Developer:

      • 工具 > 首选项
      • 数据库 > 用户定义的扩展
      • 点击“添加行”按钮
      • 在类型中选择“EDITOR”,位置是您保存上述 xml 文件的位置
      • 单击“确定”然后重新启动 SQL Developer
    2. 导航到任何表,您现在应该会在 SQL 旁边看到一个附加选项卡,标记为 FK References,其中显示了新的 FK 信息。

    3. 参考

    【讨论】:

    • 你知道 Packages 的节点名称是什么吗?我在网上找到的所有 xsd 链接都不再有效(因为在 Oracle 中删除了它们)。
    • 我在您的建议中添加了一个小改动:and owner = user 在 order by 之前,这样如果您在两个模式中有相同表的两个实例,您只会得到与您的架构相关的参考文献
    • 我在and exists之前添加了这个条件:and owner = :OBJECT_OWNER
    • @M-Denis,在这种情况下,您可能会错过来自其他模式的引用。
    • 应用此功能并运行describe books;select * from books; 后,它不会在Oracle sql developer VM 上显示fk 引用选项卡。
    【解决方案3】:

    在下面的查询中将 [Your TABLE] 替换为 emp

    select owner,constraint_name,constraint_type,table_name,r_owner,r_constraint_name
      from all_constraints 
     where constraint_type='R'
       and r_constraint_name in (select constraint_name 
                                   from all_constraints 
                                  where constraint_type in ('P','U') 
                                    and table_name='[YOUR TABLE]');
    

    【讨论】:

    • 我觉得constraint_type in ('P','U')是多余的,因为如果一个约束TOTO的constraint_type是'R',那么TOTO的r_constraint_name当然就是一个'P' OR 'U'类型的约束的名字引用的表。没有必要指定它。您使用的是 IN,所以它就像很多 OR,我们只关心 OR 的唯一操作数,其计算结果为真。
    【解决方案4】:

    您也许可以从ALL_CONSTRAINTS 视图中查询:

    SELECT table_name
    FROM ALL_CONSTRAINTS
    WHERE constraint_type = 'R' -- "Referential integrity"
      AND r_constraint_name IN
        ( SELECT constraint_name
          FROM ALL_CONSTRAINTS
          WHERE table_name = 'EMP'
            AND constraint_type IN ('U', 'P') -- "Unique" or "Primary key"
        );
    

    【讨论】:

    • 外键可以引用唯一键,而不仅仅是主键,而且表名可以在多个模式中使用,这会导致多个匹配。如果您要使用“All_Constraints”而不是“User_Constraints”,则还需要使用“Owner”列。
    • 感谢您评论“R”“U”和“P”是什么
    • 不要忘记 SQL 请求末尾的分号。
    • 对了,('P','U')中的constraint_type是多余的,因为如果一个约束TOTO的constraint_type是'R',那么TOTO的r_constraint_name当然就是一个约束的名字引用表中的“P”或“U”类型。无需指定。
    【解决方案5】:

    2015 年 5 月发布的 SQL Developer 4.1 添加了一个模型选项卡,该选项卡显示表外键,以实体关系图格式引用您的表。

    【讨论】:

    • 如果您出于某种原因需要在脚本中使用此功能,那么它的用处不大,但如果您只需要了解连接,这似乎是一种现代方式。
    • @SnoringFrog 从技术上讲,这个问题需要一个 UI 元素,所以这是最合适的答案
    【解决方案6】:
    SELECT DISTINCT table_name, 
                    constraint_name, 
                    column_name, 
                    r_table_name, 
                    position, 
                    constraint_type 
    FROM   (SELECT uc.table_name, 
                   uc.constraint_name, 
                   cols.column_name, 
                   (SELECT table_name 
                    FROM   user_constraints 
                    WHERE  constraint_name = uc.r_constraint_name) r_table_name, 
                   (SELECT column_name 
                    FROM   user_cons_columns 
                    WHERE  constraint_name = uc.r_constraint_name 
                           AND position = cols.position)           r_column_name, 
                   cols.position, 
                   uc.constraint_type 
            FROM   user_constraints uc 
                   inner join user_cons_columns cols 
                           ON uc.constraint_name = cols.constraint_name 
            WHERE  constraint_type != 'C') 
    START WITH table_name = '&&tableName' 
               AND column_name = '&&columnName' 
    CONNECT BY NOCYCLE PRIOR table_name = r_table_name 
                             AND PRIOR column_name = r_column_name; 
    

    【讨论】:

    • 这非常有用 - 递归显示某个根表中的所有表,这些表将您在该根表中选择的列的值作为键保存。太棒了,谢谢。
    • 这真的很酷——干得好。我只会添加 lower() 来比较 table_name 和 column_name。
    • 如果我的团队实际上在 DB 层中使用了外键,这对我也非常有用。唉,回头看看hibernate代码。
    【解决方案7】:

    这已经在产品中多年了 - 尽管它在 2011 年还没有出现在产品中。

    但是,只需单击“模型”页面。

    确保您至少使用 4.0 版(2013 年发布)才能访问此功能。

    【讨论】:

      【解决方案8】:

      这样的事情怎么样:

      SELECT c.constraint_name, c.constraint_type, c2.constraint_name, c2.constraint_type, c2.table_name
        FROM dba_constraints c JOIN dba_constraints c2 ON (c.r_constraint_name = c2.constraint_name)
       WHERE c.table_name = <TABLE_OF_INTEREST>
         AND c.constraint_TYPE = 'R';
      

      【讨论】:

      • 当我将表名从 dba_constraints 更改为 all_constraints 时,这对我有用:SELECT c.constraint_name, c.constraint_type, c2.constraint_name, c2.constraint_type, c2.table_name FROM all_constraints c JOIN all_constraints c2 ON (c.r_constraint_name = c2.constraint_name) WHERE c.table_name = '&lt;TABLE_OF_INTEREST&gt;' AND c.constraint_TYPE = 'R';
      【解决方案9】:

      要添加到 sql developer 插件的上述答案,使用下面的 xml 将有助于获取与外键关联的列。

          <items>
              <item type="editor" node="TableNode" vertical="true">
              <title><![CDATA[FK References]]></title>
              <query>
                  <sql>
                      <![CDATA[select a.owner,
                                      a.constraint_name,
                                      a.table_name,
                                      b.column_name,
                                      a.status
                               from   all_constraints a
                               join   all_cons_columns b ON b.constraint_name = a.constraint_name
                               where  a.constraint_type = 'R'
                                      and exists(
                                         select 1
                                         from   all_constraints
                                         where  constraint_name=a.r_constraint_name
                                                and constraint_type in ('P', 'U')
                                                and table_name = :OBJECT_NAME
                                                and owner = :OBJECT_OWNER)
                                         order by table_name, constraint_name]]>
                  </sql>
              </query>
              </item>
          </items>
      

      【讨论】:

        【解决方案10】:

        我喜欢使用直接的 SQL 查询来执行此操作,而不是使用 SQL Developer 应用程序。

        这就是我刚才的做法。最好通读一遍并了解发生了什么,这样您就可以对其进行调整以满足您的需求...

        WITH all_primary_keys AS (
          SELECT constraint_name AS pk_name,
                 table_name
            FROM all_constraints
           WHERE owner = USER
             AND constraint_type = 'P'
        )
          SELECT ac.table_name || ' table has a foreign key called ' || upper(ac.constraint_name)
                 || ' which references the primary key ' || upper(ac.r_constraint_name) || ' on table ' || apk.table_name AS foreign_keys
            FROM all_constraints ac
                 LEFT JOIN all_primary_keys apk
                        ON ac.r_constraint_name = apk.pk_name
           WHERE ac.owner = USER
             AND ac.constraint_type = 'R'
             AND ac.table_name = nvl(upper(:table_name), ac.table_name)
        ORDER BY ac.table_name, ac.constraint_name
        ;
        

        【讨论】:

          【解决方案11】:

          仅将 table_name 替换为您的主表名

          select *
          from all_constraints
          where r_constraint_name in (
          select constraint_name
          from all_constraints
          where table_name='table_name'
          ); 
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-08-10
            • 2010-10-19
            • 1970-01-01
            • 2016-08-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多