如何强制执行约束,允许重复三列,但只有当两列匹配时?

时间:2013-11-30 19:11:27

标签: sql postgresql

我有一个SQL表,其中包含必须满足两个约束的条目。首先,不应该使用相同的MID和Source重复。其次,对于相同的源和ID,Source,ID,DBID的组合必须相同。问题是,如何强制执行第二个约束?下面的示例表:

MID Source  ID          DBID    Match   Accuracy
================================================
1   FILE    Alice (HD)  1       DIRECT  100%
1   TMDB    M-1201      2       NAME    95%
2   FILE    Alice (SD)  3       DIRECT  100%
2   TMDB    M-1201      2       ID      100%
2   IMDB    tt0048348   5       ID      100%
3   FILE    Unknown     4       DIRECT  100%
3   TMDB    null        null    null    null
4   TMDB    S-1201      1       NAME    92%
5   TMDB    null        null    null    null

约束类似于:

UNIQUE(MID, Source)
CHECK THAT (Source, ID, DBID) are same for all (Source, ID)

因此,以下记录应该导致:

MID Source  ID          DBID    Match   Accuracy
================================================
6   TMDB    M-1201      2       DIRECT  100%
--> Accepted (TMDB, M-1201, 2) matches existing (TMDB, M-1201, 2)
7   TMDB    M-1201      500     DIRECT  100%
--> Violates CHECK, as there already exists (TMDB, M-1201, 2) and 2 != 500
1   FILE    Something   501     NAME    95%
--> Violates UNIQUE, as there already exists (1, FILE)

我已经尝试将Source,ID,DBID规范化为单独的表,但是我无法在没有重复信息的情况下检查UNIQUE约束(导致进一步的约束以确保它不会失去同步)。

我正在使用PostgreSQL,但更喜欢一个相当便携的解决方案 - 我怀疑EXCLUDE约束可能适用于PostgreSQL,但我不确定它是如何应用的。根据PostgreSQL文档,CHECK约束应该只引用当前行,所以我想知道是否可以对此做任何事情。

1 个答案:

答案 0 :(得分:0)

  

我已经尝试将Source,ID,DBID规范化为单独的表,但是我无法在没有重复信息的情况下检查UNIQUE约束(导致进一步的约束以确保它不会失去同步)。

实际上,的方式。 DBID取决于Source和ID,因此它应该位于不同的表中。这就是数据库的工作方式以及规范化的工作原理。

Source  ID          DBID
========================
FILE    Alice (HD)  1   
TMDB    M-1201      2   
FILE    Alice (SD)  3   
IMDB    tt0048348   5   
FILE    Unknown     4   
TMDB    S-1201      1   

使用主键(来源,ID)

MID Source  ID          Match   Accuracy
========================================
1   FILE    Alice (HD)  DIRECT  100%
1   TMDB    M-1201      NAME    95%
2   FILE    Alice (SD)  DIRECT  100%
2   TMDB    M-1201      ID      100%
2   IMDB    tt0048348   ID      100%
3   FILE    Unknown     DIRECT  100%
3   TMDB    null        null    null
4   TMDB    S-1201      NAME    92%
5   TMDB    null        null    null

如果(MID,Source)应该是唯一的,您可以将其作为主键。另一种选择是将(MID,Source,ID)作为主键并在(MID,Source)上添加唯一约束。无论你决定做什么,都应该有一个外键约束(Source,ID)引用你的第一个表。