app*_*l3r 8 postgresql database-design merge
我正在查看 PostgreSQL 的INSERT INTO .. ON CONFLICT (..) DO UPDATE ..
语法并意识到,您不能使用它进行多个唯一约束检查。我的意思是,您要么通过列名引用复合唯一索引ON CONFLICT (Name, Symbol)
(如果为这两列定义了唯一索引),要么使用主键。如果为列定义两个单独的唯一索引,则只能检查一个。
CREATE TABLE student
(Id int primary key, Name varchar(50), Symbol varchar(50),
CONSTRAINT col1_unique UNIQUE (Name),
CONSTRAINT col2_unique UNIQUE (Symbol)
);
INSERT INTO student
(Id, Name, Symbol)
VALUES
(1, 'John', 'J'),
(2, 'David', 'D'),
(3, 'Will', 'W');
INSERT INTO student
(Id, Name, Symbol)
VALUES
(4, 'Jeremy', 'J')
on conflict(Name) DO UPDATE
set Name = 'Jeremy';
Run Code Online (Sandbox Code Playgroud)
可能会抛出错误,说J
是重复的。然而,这个例子只是一个糟糕的设计,因为符号应该在另一个表中,并通过一对多关系连接到学生表。这就是为什么我想知道,也许 PostgreSQLon conflict
是这样设计的,因为您总是可以以某种方式重构表,其中只有一个唯一索引。是真的还是另有原因?
总有第六种,或域键,范式。这里每个非键列都成为它自己的表。所以 3NF 表 T(Key, Col1, Col2, ..) 变成 T1(Key, Col1), T2(Key, Col2) 等等。那些需要唯一性的新表可以声明它。
然而,我认为在一个表上有多个唯一约束是完全可以的。以国家/地区表为例。例如,这将包含 ID、名称、ISO 代码、首都和其他一些内容。前四个中的每一个都是独一无二的。此外,如果我们希望我们的系统依赖于每个都是独一无二的,我相信我们应该为每个定义独特的约束。这强制执行所有消费者都可以依赖的数据的真实性。