postgresql – 为什么可以在可空的列上创建一个带有PRIMARY KEY的表?

前端之家收集整理的这篇文章主要介绍了postgresql – 为什么可以在可空的列上创建一个带有PRIMARY KEY的表?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
以下代码创建一个表,而不会引发任何错误
CREATE TABLE test(
ID INTEGER NULL,CONSTRAINT PK_test PRIMARY KEY(ID)
)

请注意,我无法插入NULL,如预期的:

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列被显式声明为NULLable,并且它是隐式不可为空,作为PRIMARY KEY的一部分.是否有意义?

编辑:如果这个自相矛盾的CREATE TABLE刚刚失败,那会不会更好?

因为PRIMARY KEY自动使列NOT NOT NULL.我引用 the manual here

The primary key constraint specifies that a column or columns of a
table can contain only unique (non-duplicate),nonnull values.
Technically,PRIMARY KEY is merely a combination of UNIQUE and NOT NULL.

大胆强调我的

我运行了一个测试,以确认(反对我以前的信念!)NOT NULL是完全冗余的,与PRIMARY KEY约束(在当前的实现中,最多为9.5版本).在删除PK约束之后,NOT NULL约束保持不变,无论创建时是否显式的NOT NULL子句.

db=# CREATE TEMP TABLE foo (foo_id int PRIMARY KEY);
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
CREATE TABLE

db=# ALTER TABLE foo DROP CONSTRAINT foo_pkey;
ALTER TABLE
db=# \d foo
   table »pg_temp_4.foo«
 column |  type   | attribute
--------+---------+-----------
 foo_id | integer | not null

CREATE语句中包含NULL的相同行为.

但是,如果列应该为NOT NULL,那么在代码存储库中冗余不会保留NOT NULL仍然不会受到伤害.如果您稍后决定移动pk约束,您可能会忘记标记列NOT NULL – 或者它是否应该为NOT NULL.

有一个item in the Postgres TODO wiki从PK约束中解耦NOT NULL.所以这可能会在以后的版本中改变:

Move NOT NULL constraint information to pg_constraint

Currently NOT NULL constraints are stored in pg_attribute without any designation of their origins,e.g. primary keys. One manifest
problem is that dropping a PRIMARY KEY constraint does not remove the
NOT NULL constraint designation. Another issue is that we should
probably force NOT NULL to be propagated from parent tables to
children,just as CHECK constraints are. (But then does dropping
PRIMARY KEY affect children?)

回答补充问题:

Would it not be better if this self-contradictory CREATE TABLE just
Failed right there?

如上所述,这样

foo_id INTEGER NULL PRIMARY KEY

相当于:

foo_id INTEGER PRIMARY KEY

由于NULL被视为噪声字.我们不希望后者失败.所以这不是一个选择.

猜你在找的Postgre SQL相关文章