我有一个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约束应该只引用当前行,所以我想知道是否可以对此做任何事情。
答案 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)引用你的第一个表。