使用SQL定义一对多关系

时间:2011-12-09 23:08:40

标签: sql postgresql constraints one-to-many

我正在寻找一种方法来建立两个表之间的一对多关系。下面解释了表结构,但我试图将一切都与问题无关。

objects有一列名为uuid

contents有3列名为contentobject_uuidtimestamp

基本思路是在objects中插入一行,并从数据库中获取新的uuid。然后,将uuid存储为contents中的每一行,以将内容与对象相关联。

现在我正在尝试使用数据库强制执行:

  • contents中的每一行都引用objects中的一行(外键应该这样做)
  • objects row <{1}}中没有contents

应在提交交易时强制执行这些约束。

普通触发器可能无法帮助,因为当写入objects表中的一行时,contents中就不会有一行。 Postgres确实有所谓的constraint triggers,可以推迟到交易结束。可以使用它们,但它们似乎是某种不适合日常使用的内部构造。

创意或解决方案应该是标准SQL(首选)或与Postgres一起使用(版本无关紧要)。感谢您的任何意见。

2 个答案:

答案 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()函数。