以下代码创建了一个表,但没有引发任何错误:

CREATE TABLE test(
ID INTEGER NULL,
CONSTRAINT PK_test PRIMARY KEY(ID)
)

请注意,我不能像预期的那样插入空值:

INSERT INTO test
VALUES(1),(NULL)
ERROR:  null value in column "id" violates not-null constraint
DETAIL:  Failing row contains (null).
********** Error **********

ERROR: null value in column "id" violates not-null constraint
SQL state: 23502
Detail: Failing row contains (null).

为什么我可以创建一个定义自相矛盾的表?ID列作为主键的一部分显式声明为可空,而隐式声明为不可空.这有意义吗?

编辑:如果这个自相矛盾的创建表失败了,不是更好吗?

推荐答案

因为PRIMARY KEY makes包含了NOT NULL automatically列.我引用the manual here:

主键约束指定

我的.

我运行了一个测试来确认NOT NULLPRIMARY KEY约束(在当前的实现中,在版本13中重新测试)结合起来是完全冗余的.100 constraint stays即使在放弃PK约束之后,也不会在创建时忽略显式NOT NULL子句.

CREATE TABLE foo (foo_id int PRIMARY KEY);
ALTER TABLE foo DROP CONSTRAINT foo_pkey;
db=# \d foo
   table »public.foo«
 column |  type   | attribute
--------+---------+-----------
 foo_id | integer | not null    -- stays

db<>fiddle 100

如果CREATE TABLE语句中包含NULL,则行为相同.

如果列应该是NOT NULL,那么在代码存储库中保留NOT NULL个冗余也不会有什么坏处.如果您后来决定更改PK约束,可能会忘记标记列NOT NULL,或者是否应该标记为NOT NULL.

有一个item in the Postgres TODO wiki来将NOT NULL与PK约束解耦.因此,在future 的版本中,这可能会发生变化:

将非空约束信息移动到pg_约束

目前,非空约束存储在pg_属性中,不指定其来源,例如主键.一份 list

补充问题的答案

如果这个自相矛盾的创建表

如上所述,这

foo_id INTEGER NULL PRIMARY KEY

(目前)100%相当于:

foo_id INTEGER PRIMARY KEY

Since NULL is treated as noise word in this context.
And we wouldn't want the latter to fail. So this is not an option.

Postgresql相关问答推荐

PostgreSQL按描述请求

为什么在PostgreSQL中CPU_INDEX_TUPLE_COST与CPU_TUPLE_COST不同

如何在PostgreSQL中对深度嵌套的jsonb属性创建索引

将具有自定义类型的表从一种模式复制到另一种模式

无法将 json 范围读取为 pgtype.Int4range

使用来自 docker 图像的 postgres 设置 Keycloak 21

是否可以在 postgres jsonb 列中的列表上创建索引

PostgreSQL:如何从另一列的 json 值替换为一列?

对 Postgres 进行身份验证时如何使用自定义密码哈希算法?

Postgres 转储按顺序插入

如何获得区间的绝对值

Django + Postgres + 大时间序列

包含受先前 DELETE 影响的行数的变量?

如何使用 SpringBoot + JPA 存储 PostgreSQL jsonb?

在函数中返回字段作为插入结果

如何从另一个脚本运行 postgres sql 脚本?

如何在Postgres中分组并返回总和行

如何为 postgres 编写 DELETE CASCADE?

由于不支持身份验证类型 10,无法连接到 Postgres DB

如何在 PostgreSQL 中获取数组的最后一个元素?