【问题标题】:Oracle: FK referring PK in multiple parent tablesOracle:FK 在多个父表中引用 PK
【发布时间】:2011-03-29 14:43:00
【问题描述】:

在 Oracle 10g 中,是否可以为外键定义引用完整性约束以引用多个父表中的主键。

例如:

DEPT_AMER

部门编号
10
11
12

DEPT_APAC

部门编号
13
14
15

DEPT_EMEA

部门编号
16
17
18

电磁脉冲

EMP_ID DEPT_ID
500 11
501 15

我希望 EMP.DEPT_ID 能够引用 DEPT_AMER、DEPT_APAC 和 DEPT_AMER 中的部门 ID 之一。有没有办法定义参照完整性来满足这种需求。 3个表中的DEPT_ID都是从一个公共序列中生成的,并且保证是唯一的。

如果引用完整性约束是不可能的,有没有更好的方法来维护这种数据完整性?

【问题讨论】:

    标签: sql oracle foreign-key-relationship referential-integrity


    【解决方案1】:

    您在三个不同的表中有一个实体。最好的方法是将 DEPT_AMER + DEPT_EMEA + DEPT_APAC 加入一个名为 DEPT 的表中,并带有新字段 DEPT_TYPE(AMER 或 EMEA 或 APAC)。它对功能支持和性能更好。

    如果在南极开设新部门,你会怎么做?添加另一个表?不!您只需添加另一个 dept_type。

    【讨论】:

    • 是什么阻止了部门 ID 在多个父表中使用?
    • 实际上,南极洲的一个部门正是我要派人去的地方,他提出了一个具有多个父表的数据模型。
    【解决方案2】:

    如果所有表中的字段都相同,那么我建议将此模型重构为单个表并为遗留应用程序创建视图。 有时这种设计用于分区,但 Oracle 会自动维护分区,应用级分区是多余的。

    【讨论】:

      【解决方案3】:

      你可以定义约束,但它不会做你想做的事。您永远无法向 emp 表添加任何内容,因为键 DEPT_ID 必须驻留在每个 DEPT_ 表中。

      假设您必须保留现有结构,最简单的方法是定义一个物化视图,将这些表中的每一个合并到一个视图中。 IMO,这是一个有缺陷的实现。我会为 DEPT_ 信息创建一个表,其中包含一个拆分各种类型的列。

      【讨论】:

        【解决方案4】:

        您不能定义这样的 FK 约束。 但是您可以使用触发器验证数据完整性。 例如:

         CREATE OR REPLACE TRIGGER emp_check_dept_id_trg
            BEFORE INSERT OR UPDATE 
            on emp
            FOR EACH ROW
            DECLARE
              l_res NUMBER;
            BEGIN
              SELECT count(*) 
              INTO l_res
              FROM (
                      SELECT dept_id FROM DEPT_AMER WHERE dept_id = :NEW.DEPT_ID
                    UNION ALL
                        SELECT dept_id FROM DEPT_APAC WHERE dept_id = :NEW.DEPT_ID
                    UNION ALL
                        SELECT dept_id FROM DEPT_EMEA WHERE dept_id = :NEW.DEPT_ID
                  )
              ;
              IF l_res = 0 THEN
                raise_application_error(-20000, 'referential integrity violated');
              END IF;
            END;
            /
        

        【讨论】:

        • 您可以尝试,但基于触发器的 RI 几乎永远不会 100% 可靠。您需要锁定 DEPT_* 行以防止它们被另一个会话删除,依此类推。
        • 没错。但是当架构更改不可能时,例如由于外部应用程序。那么还有哪些替代方案。
        猜你喜欢
        • 2011-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多