考虑 PosgtreSQL 中的这两个表:
# report
+----+-------------+--------------------+
| id | report_name | report_description |
+----+-------------+--------------------+
| 1 | RPT | ABCDEFGH |
| 2 | TST | LMNOPQRS |
+----+-------------+--------------------+
# report_years
+----+--------------+-------------+------+
| id | report_id_fk | report_name | year |
+----+--------------+-------------+------+
| 11 | 1 | RPT | 2019 |
| 12 | 1 | RPT | 2020 |
| 13 | 2 | TST | 2019 |
+----+--------------+-------------+------+
- 鉴于这
report_id_fk
是report_years
表中的外键,没有办法CASCADE
更新report_name
基于report_id_fk
? - 它们必须是单独的外键吗?
report_name
甚至不应该放在report_years
表中,因为它是多余的,应该用JOIN
to来查询report
?- 是否有可能有一个多字段外键约束,
report_name
并且year
对于 a 来说是必需的CASCADE
?
例如:
# report
+----+-------------+------+
| id | report_name | year |
+----+-------------+------+
| 1 | RPT | 2018 |
| 2 | RPT | 2019 |
| 3 | RPT | 2020 |
+----+-------------+------+
# report_details
+----+-----------+----------------+---------+---------+
| id | report_id | report_name_fk | year_fk | details |
+----+-----------+----------------+---------+---------+
| 11 | 1 | RPT | 2018 | ABC |
| 12 | 2 | RPT | 2019 | DEF |
| 13 | 3 | RPT | 2020 | GHI |
+----+-----------+----------------+---------+---------+
- 如果我想更改
report_name
foryear = 2020
inreport
,它CASCADE
会report_details
更新report_name_fk
基于report_name_fk
andyear_fk
? - 或者(回到问题 1),我可以设置一个
CASCADE
可以更新report_name_fk
的year_fk
inreport_details
吗?
我可以通过手册了解如何做到这一点UPDATE
,但看看是否可以使用CASCADE
. 或者,就像我认为的那样,这是多余的,应该避免,如果您需要知道report_name
并year
获得报告report_details
,您应该只写一个查询JOIN
。
您可以使用两列外键和级联更新来解决此问题,但这需要对 进行冗余的两列唯一约束
report
,这将损害 DML 性能并使用额外的存储空间。正确的解决方案是从
report_years
. 这种从数据模型中去除冗余以提高一致性的概念非常重要,以至于它有了一个名字:规范化。