PostgreSQL:实现最小基数数据库

问题描述

我有一个像这样的实体关系图

enter image description here

因此在Postgresql中,我创建了三个这样的表:

create table Artist(
    id id primary key
)

create table Musical_Event(
    id id primary key
)

create table Play_In(
    artist id,musical_event id,primary key (artist,musical_event),foreign key (artist) references Artist(id),foreign key (musical_event) references Musical_Event(id)
)

从图中可以看出,一个音乐盛会必须至少有一位表演艺术家。我不确定如何在Postgresql中实现此约束。如果删除了表Play_In中的一行,我可以简单地创建一个触发器,以检查该行涉及的音乐事件是否还有至少一位其他艺术家,如果没有,请引发异常。但是,我无法创建这样的触发器,该触发器在插入新的音乐事件时会激活,实际上,在创建涉及的音乐事件之前,我无法在Play_in中插入一行,因为这会违反外键约束。所以我想到的唯一方法就是

  1. 创建一个触发器,该触发器在插入Musical_Event中的新行之后激活,并调用一个函数,该函数提示用户在Play_In中添加一行(引用相同的musical_event)。但是我不知道这是否可能。
  2. 创建一个在Musical_Event和Play_in中插入一行的功能(musical_event列等于新音乐事件的ID),并且用户只能使用此功能在Musical_Event中插入新行。
  3. 创建一个视图作为Musical_Event和Play_in的联接,并带有一个触发器,该触发器每次在视图中插入新行时都会激活,并调用一个函数,该函数将新值插入Musical_Event和Play_In中。用户只能在此视图中插入值,才能在Musical_event中插入新行。

还有其他选择吗?哪种方法是处理这种情况的最佳方法,以及如何实现?

解决方法

这是一个很难实现的关系。因为:

  • 您具有从plays_inevents的外键关系,因此Event_Id必须有效,才能在Play_In中插入一行。
  • 不过,您指定您必须具有plays_in记录才能创建Event

循环逻辑。有一些方法可以“解决”问题-例如,通过关闭或推迟约束。因此,一种方法是使用deferred constraints在单个事务中插入艺术家和事件。这适用于Postgres,可能是Postgres的首选解决方案。但是,它并不是所有数据库的通用解决方案。

另一种解决方案是请一位特殊艺术家。该特殊艺术家将具有从eventsartists的直接外键关系,并且是NOT NULL。问题是一位艺术家是“特殊”艺术家,因此将被单独查询。

我认为,如果您真的想“强制”执行此操作,我的首选方法是在artist_count表中添加events。可以使用触发器来维护此计数。

然后使用视图显示有效事件:

create view v_events as
    select e.*
    from events e
    where artist_count > 0;

使用视图的代码只会包含具有有效艺术家的事件,并且填充数据不会有问题。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...