use*_*637 20 postgresql null database-design unique primary-key
这是我在Postgres中遇到的一个奇怪的,不需要的行为:当我使用复合主键创建Postgres表时,它会对复合组合的每一列强制执行NOT NULL约束.
例如,
CREATE TABLE distributors (m_id integer, x_id integer, PRIMARY KEY(m_id, x_id));
Run Code Online (Sandbox Code Playgroud)
强制NOT NULL列上的约束m_id和x_id,我不想!MySQL没有这样做.我认为Oracle也不会这样做.
据我所知,PRIMARY KEY强制执行UNIQUE并NOT NULL自动执行但对单列主键有意义.在多列主键表中,唯一性由组合确定.
有没有简单的方法来避免Postgres的这种行为?
如果我执行这个:
CREATE TABLE distributors (m_id integer, x_id integer);
Run Code Online (Sandbox Code Playgroud)
我NOT NULL当然没有任何限制.
Erw*_*ter 39
如果您需要允许NULL值,请使用UNIQUE约束而不是a PRIMARY KEY(并添加代理PK列,我建议使用serial).这允许列为NULL:
CREATE TABLE distributor (
distributor_id serial PRIMARY KEY
, m_id integer
, x_id integer
, UNIQUE(m_id, x_id)
);Run Code Online (Sandbox Code Playgroud)
但请注意(根据文档):
出于唯一约束的目的,空值不被视为相等.
在你的情况,你可以输入(1, NULL)为(m_id, x_id)不违反约束任意次数.Postgres从不认为两个NULL值相等 - 根据SQL标准中的定义.
如果您需要将NULL值视为等于禁止此类"重复",我会看到两个选项:
除了UNIQUE上面的约束:
CREATE UNIQUE INDEX dist_m_uni_idx ON distributor (m_id) WHERE x_id IS NULL;
CREATE UNIQUE INDEX dist_x_uni_idx ON distributor (x_id) WHERE m_id IS NULL;
Run Code Online (Sandbox Code Playgroud)
但是,如果两列以上的列可以为NULL,则会快速失控.
有关:
而不是UNIQUE约束.我们需要一个在相关列中永远不会出现的自由默认值,例如-1.添加CHECK约束以禁止它:
CREATE TABLE distributor (
distributor serial PRIMARY KEY
, m_id integer
, x_id integer
, CHECK (m_id <> -1)
, CHECK (x_id <> -1)
);Run Code Online (Sandbox Code Playgroud)
CREATE UNIQUE INDEX distributor_uni_idx ON distributor (COALESCE(m_id, -1)
, COALESCE(x_id, -1))
Run Code Online (Sandbox Code Playgroud)
某些RDBMS如何处理事情并不总是正确行为的有用指标.在Postgres的本手册的提示:
这意味着即使存在唯一约束,也可以在至少一个约束列中存储包含空值的重复行.此行为符合SQL标准,但我们听说其他SQL数据库可能不遵循此规则.因此在开发可移植的应用程序时要小心.
大胆强调我的.
| 归档时间: |
|
| 查看次数: |
11984 次 |
| 最近记录: |