次のコードは、エラーを発生させずにテーブルを作成します。
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列は、PRIMARY KEYの一部として、NULL可能として明示的に宣言されており、暗黙的にNULL可能ではありません。それは意味がありますか?
編集:この自己矛盾するCREATE TABLEがちょうどそこで失敗した場合、それは良くないでしょうか?
PRIMARY KEY
は列を作成するため列NOT NULL
は自動的に。引用します マニュアルはこちら :
主キー制約は、テーブルの1つまたは複数の列に、一意の(重複していない)非null値のみを含めることができることを指定します。技術的には、
PRIMARY KEY
はUNIQUE
とNOT NULL
の組み合わせにすぎません。
大胆な強調鉱山。
(私の以前の信念に対して)NOT NULL
がPRIMARY KEY
制約と組み合わせて完全に冗長であることを確認するためにテストを実行しました(現在の実装では、バージョン9.5まで)。 NOT NULL制約は、作成時に明示的なNOT NULL
句に関係なく、PK制約を削除した後も残ります。
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
NULL
がCREATE
ステートメントに含まれている場合の動作は同じです。
ただし、列がNOT NULL
であると想定されている場合でも、コードリポジトリにNOT NULL
を重複して保持しても問題はありません。後でpk制約を移動することを決定した場合、列にNOT NULL
をマークするのを忘れるか、またはNOT NULL
であると想定されていたかどうかを忘れることがあります。
PK制約からNOT NULL
を分離するための Postgres TODO wikiの項目 があります。したがって、これは将来のバージョンで変更される可能性があります。
NOT NULL制約情報をpg_constraintに移動
現在、NOT NULL制約は、その起源を指定せずにpg_attributeに保存されています。主キー。 1つの明白な問題は、PRIMARY KEY制約を削除してもNOT NULL制約の指定が削除されないことです。もう1つの問題は、CHECK制約と同じように、NOT NULLを親テーブルから子に強制的に伝搬する必要があることです。 (しかし、PRIMARY KEYを削除すると子供に影響がありますか?)
この自己矛盾するCREATE TABLEがすぐに失敗した方がいいのではないでしょうか。
上記で説明したように、これは
foo_id INTEGER NULL PRIMARY KEY
以下と同等です。
foo_id INTEGER PRIMARY KEY
NULL
はノイズワードとして扱われるため。
そして、後者が失敗することを望まないでしょう。したがって、これはオプションではありません。
メモリが役立つ場合、ドキュメントは次のように述べています:
null
は基本的に無視されるノイズワードですprimary key
は、nullではなく、一意の制約を強制します見る:
# create table test (id int null primary key);
CREATE TABLE
# \d test
Table "public.test"
Column | Type | Modifiers
--------+---------+-----------
id | integer | not null
Indexes:
"test_pkey" PRIMARY KEY, btree (id)
@ErwinBrandstetterが言ったように、PRIMARY KEYはUNIQUEとNOT NULLの単なる組み合わせの場合、NOT NULL
の代わりにPRIMARY KEY
なしでUNIQUE
制約を使用できます。例:
CREATE TABLE test(
id integer,
CONSTRAINT test_id_key UNIQUE(id)
);
このようにして、次のようなことができます。
INSERT INTO test (id) VALUES (NULL);
INSERT INTO test (id) VALUES (NULL);
INSERT INTO test (id) VALUES (NULL);