我在查找如何声明以下类型的关联时遇到问题:
说我有一张表“Weekly”:
Weekly {
Id : Int <= PK
Week : Int
Year : Int
}
表“每月”:
Monthly{
Id : Int <= PK
Month: Int
Year : Int
}
我还有一个“WeekMonth”表:
Monthly{
Week : Int <= PK
Month : Int <= PK
Year : Int <= PK
}
正如你所猜测的那样,我希望能够将Weekly与WeekMonth和Monthly与WeekMonth联系起来。
但是,我无法接合能够执行此操作:复合主键的一部分上的外键。尽管如此,在我的WeekMonth表中,年和周以及年和月字段都是显而易见的,因此它应该能够工作。
我已经尝试了多个approch来解决这个问题,但由于每月一周的自定义映射是业务需求,我对它有点困惑
答案 0 :(得分:2)
在我的WeekMonth表中,年和周以及年和月字段都是显而易见的
事实并非如此。 '年和周'可能是唯一的,但它取决于'周'是什么 - 如果它是一个月内的一周(即1-5)那么它不是唯一的。如果它是一年中的一周(1-53)那么它是;但您在该组合上没有唯一或主键。并且“年月”并不是唯一的,因为每个组合都会有多个条目 - 4个或5个。
如果您有复合主键(或唯一键),则外键必须引用该PK中的所有列 - 否则它们不一定是唯一的。
自然钥匙在这里并不适合你。除了不允许您想要的关系外,您还要复制父表和子表中的数据。最好有一个合成密钥,例如从序列中设置:
WeekMonth{
WeekMonth_Id : Int <= PK (synthetic, e.g. from sequence)
Week : Int <= }
Month : Int <= } UK
Year : Int <= }
}
Weekly {
Weekly_Id : Int <= PK
WeekMonth_Id : Int <= FK to WeekMonth
}
Monthly{
Monthly_Id : Int <= PK
WeekMonth_Id : Int <= FK to WeekMonth
}
您不需要在子表中复制年/月/周值,因为您可以从父表中获取它们。而且你不应该复制它们,因为你不能轻易保证匹配相关的父记录,以及一般的规范化原因。
我假设你在每周和每月的表格中都有其他数据,否则它们会有点无意义;任何其他具有FK的表都可以使用FK代替WeekMonth。
如果您确实希望在子表中复制单独的年/月/周值,那么除了当前的PK之外,您还需要为这些组合使用单独的唯一键。所以你修改WeekMonth以获得一年和一月的唯一密钥(这可能取决于'周'代表什么),以及年和月的另一个唯一密钥 - 但由于这不是一个独特的组合,你不能创造那把钥匙。
答案 1 :(得分:2)
假设WeekMonth
表的年度Week
值为1
到53
,那么:
CREATE TABLE WeekMonth(
Week INT,
Month INT,
Year INT,
CONSTRAINT WeekMonth__W_M_Y__PK PRIMARY KEY ( Week, Month, Year ),
CONSTRAINT WeekMonth__W_Y__PK UNIQUE ( Week, Year )
);
CREATE TABLE Monthly(
ID INT PRIMARY KEY,
Month INT,
Year INT,
FirstWeek INT GENERATED ALWAYS
AS ( TO_NUMBER(
TO_CHAR(
NEXT_DAY(
TO_DATE( month||'-'||year, 'MM-YYYY' ) - 1,
'MONDAY'
),
'WW'
)
)
),
CONSTRAINT Monthly__M_Y__PK FOREIGN KEY ( FirstWeek, Month, Year )
REFERENCES WeekMonth( Week, Month, Year )
);
CREATE TABLE Weekly(
ID INT PRIMARY KEY,
Week INT,
Year INT,
CONSTRAINT Weekly__W_Y__PK FOREIGN KEY ( Week, Year )
REFERENCES WeekMonth( Week, Year )
);