【问题标题】:How do i determine whether a given entry has foreign keys pointing to it?如何确定给定条目是否有指向它的外键?
【发布时间】:2020-09-22 16:40:10
【问题描述】:

我目前正在为父表开发一个触发器函数,它应该对子表上的相关行执行检查,该子表具有已更新的父表行的外键。

我做了小 dbfiddle 设置我的情况:

https://www.db-fiddle.com/f/sV8f9F7Lg6R6HE89nXNhhV/4

我的数据模型包含给定实体注册的实例,其中包含给定条目的不同版本。所以我的情况是,我拥有国家、纳尼亚和机场纳尼亚机场。纳尼亚机场有一个国家的外键,表明它是纳尼亚的一部分。

每个机场都有一个检查功能,确保子表与其父表的生命周期一致,这意味着只要纳尼亚不存在,纳尼亚机场就不能存在......

第一个查询显示的是哪个,但我如何以另一种方式进行有效的检查?目前我可以将国家/地区更改为国外 og 其孩子的寿命使孩子成为孤儿?

我有一个想法为每个父子关系创建一个触发器,但它似乎有点繁重,我只对受影响的孩子做这个检查感兴趣,而不是每个孩子?

我怎么知道某事依赖于这一行,并执行我想要的检查,反之亦然,什么都不依赖于这个给定的行?

【问题讨论】:

  • 我不认为你的小提琴正在做你期望它做的事情。尝试从 airport_registration 中选择 * - entity_id 为 NULL 是否正确?事实上,我看不出您的数据如何将任何机场与任何国家联系起来; airport_registration 是唯一一个具有 FK 到机场的表,并且 FK 列 (airport_registration.entity_id) 始终为 NULL。
  • 您说的是国家和机场。为什么你有4张桌子?这些…registration 是怎么回事?你想写什么触发器?
  • @Bergi 我添加了一些详细说明
  • @AdamKG 我添加了更多 mvp 示例
  • @Lamda 谢谢,现在这更有意义了。我不确定是否有一个好的解决方案

标签: sql postgresql temporal-database


【解决方案1】:

正如您所概述的,您需要在两个方向上进行约束检查:更新机场时,确保国家/地区有效;并且当国家/地区更新时,您需要确保所有机场注册在更新后的国家/地区范围内仍然具有有效范围。

您可以通过带有函数的 CONSTRAINT 子句来实现这一点,但是当您使用 TRIGGER 时,您将可以更好地控制逻辑。例如a 在触发器函数中,您将始终可以使用新旧行或值,因此如果时间范围没有更改,您可以轻松跳过检查。

要检查“另一面”,您必须在触发器函数中执行 SQL 查询。如果您在机场有很多行,也许可以在外键列(例如在 airport.country)上添加一个 INDEX 以加快查询速度。

“国家”上的触发器将有权访问修改后的国家/地区 ID,因此您可以执行如下 SQL: IF EXISTS(SELECT 1 FROM airport a WHERE country=NEW.entity_id AND ... /* insert range checking condition here*/ ) THEN RAISE ERROR ''; END IF;,您不必担心性能问题。

https://www.postgresql.org/docs/12/plpgsql-trigger.html 有一个关于触发函数的综合示例和文档。

【讨论】:

    【解决方案2】:

    如果我没有正确回答您的问题,也许会对您有所帮助。

    SELECT
        tc.table_schema, 
        tc.constraint_name, 
        tc.table_name, 
        kcu.column_name, 
        ccu.table_schema AS foreign_table_schema,
        ccu.table_name AS foreign_table_name,
        ccu.column_name AS foreign_column_name 
    FROM 
        information_schema.table_constraints AS tc 
        JOIN information_schema.key_column_usage AS kcu
          ON tc.constraint_name = kcu.constraint_name
          AND tc.table_schema = kcu.table_schema
        JOIN information_schema.constraint_column_usage AS ccu
          ON ccu.constraint_name = tc.constraint_name
          AND ccu.table_schema = tc.table_schema
    WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name='mytable';
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-04
      • 1970-01-01
      • 2018-06-25
      • 2021-07-21
      • 2016-08-11
      • 2012-11-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多