我正在寻找一种方法来建立两个表之间的一对多关系。下面解释了表结构,但我试图将一切都与问题无关。
表objects
有一列名为uuid
。
表contents
有3列名为content
,object_uuid
和timestamp
。
基本思路是在objects
中插入一行,并从数据库中获取新的uuid
。然后,将uuid
存储为contents
中的每一行,以将内容与对象相关联。
现在我正在尝试使用数据库强制执行:
contents
中的每一行都引用objects
中的一行(外键应该这样做)objects
1}}中至少row
<{1}}中没有contents
行
应在提交交易时强制执行这些约束。
普通触发器可能无法帮助,因为当写入objects
表中的一行时,contents
中就不会有一行。 Postgres确实有所谓的constraint triggers
,可以推迟到交易结束。可以使用它们,但它们似乎是某种不适合日常使用的内部构造。
创意或解决方案应该是标准SQL(首选)或与Postgres一起使用(版本无关紧要)。感谢您的任何意见。
答案 0 :(得分:2)
你的主要问题是外键限制以外的问题;没有约束可以引用另一个表。
您最好的选择是对此进行非规范化,并在object
上添加一列,其中包含引用它的contents
计数。您可以创建一个触发器来使其保持最新状态。
contents_count INTEGER NOT NULL DEFAULT 0
除非您为可以更新此列的人员提供一些用户安全性,否则这不会是不可破解的。但是如果你用触发器保持最新状态,而你想要避免的只是意外腐败,那就足够了。
编辑:根据评论,CHECK
约束不可延迟。如果所有内容都被删除,即使打算在同一事务中添加更多内容,此解决方案也会引发错误。
答案 1 :(得分:0)
也许你想要做的是将标准化更多一点。您需要第三个表,它引用其他表的元素。表objects
应该有自己的uuid和表contents
sholud也有自己的uuid,没有对表objects
的引用。第三个表应该只有对其他两个表的引用,但主键是两个引用的组合。
所以例如你有一个表objects
的uuid,并且你想要那个uuid的所有内容,假设第三个表的列为object_uuid和content_uuid,并且表内容有自己的串行列,名为uuid,你的查询应该是这样的:
SELECT * FROM thirdtable,contents
WHERE thirdtable.content_uuid = contents.uuid AND thirdtable.object_uuid=34;
然后你可以在每个表上使用on insert触发器
CREATE TRIGGER my_insert_trigger AFTER INSERT OR UPDATE ON contents
FOR EACH ROW EXECUTE PROCEDURE my_check_function();
然后在函数my_check_function()中删除objects
中第三个表中不存在的每一行。在我回答的时候,其他人首先回答,如果你们喜欢我的解决方案,我可以帮助你制作my_check_function()函数。