主キー(PRIMARY KEY) 制約をつけた列には、NULL は登録できない と SQL標準で規定されていますが、SQLiteでは NULL も登録できます。
理由は、初期バージョンの不具合で 主キー列に NULL を登録出来てしまったそうで、後方互換性を維持するために現在でも NULL が登録できるようです。
目次
検証1. 主キー列にNULLを登録する
次のテーブル(test)の主キー(ID)に NULL を登録します。
test テーブル
1 2 3 4 |
create table test ( ID INT PRIMARY KEY, NAME TEXT ); |
insert文
1 |
insert into test ( ID, NAME ) values ( null , 'Aさん' ); |
insert & select結果
1 2 3 |
sqlite> insert into test ( ID, NAME ) values ( null , 'Aさん' ); sqlite> select * from test where ID is NULL; |Aさん |
ID が NULL のデータをSelect したところ Insert したデータを取得することが出来ました。
確かに、主キー列に NULL を登録することが出来ました。
検証2. 主キー列がNULLのデータを複数登録できるか
検証1で主キー列に NULL が登録出来てしまうことが分かりました。
次に、主キー列が NULL のデータを複数登録できるか検証します。
検証1の状態のDBに次のレコードを登録します。
insert文
1 |
insert into test ( NAME ) values ( 'Bさん' ); |
実行結果
1 2 3 4 5 |
sqlite> insert into test ( NAME ) values ( 'Bさん' ); sqlite> select * from test where ID is null; |Aさん |Bさん sqlite> |
登録することができ、Select の結果にも表示されました。
でもこの状態ですと、主キー列に NULL が登録されたデータが複数存在することになります。
主キーなのに、一意に指定することができません。
もし、このようなデータが存在する場合は、ROWID を使いましょう。
ROWID は SQLite が自動的に付与する列で、一意になります。
先ほどのデータも ROWID を含めて Select すると
1 2 3 |
sqlite> select ROWID, * from test where ID is null; 1||Aさん 2||Bさん |
このように、ROWID には、1・2 と値が設定されていることが分かります。
まとめ
SQLiteの主キー列には、NULL が登録できることを検証しました。
通常、アプリケーションを作成する場合は、主キー列に NULL を許可すると、アプリの不具合で 主キー列 に NULL を登録されてしまう可能性があります。
そのため、SQLite で主キー制約をつける場合、NOT NULL 制約も付与することをオススメします。
ID列に主キー、NOT NULL 制約を付与する例
1 2 3 4 |
create table test ( ID INT NOT NULL PRIMARY KEY, NAME TEXT ); |
NOT NULL 制約を付与すると、ID列にNULLを登録することが出来なくなります。
1 2 |
sqlite> insert into test ( ID, NAME ) values ( null , 'Aさん' ); Error: NOT NULL constraint failed: test.ID |