やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

SQLite3構文 列制約(not null)

 NULL禁止。

成果物

not null

0_0.sql

create table T(A int not null);



 テーブル作成できた。

違反

0_1.sql

create table T(A int not null);
insert into T values(NULL);
Error: near line 2: NOT NULL constraint failed: T.A

integer primary key not nullNULLをセットしてもエラーにならずrowid+1になる

1_0.sql

create table T(A integer primary key not null, B text);
insert into T(B) values('A');
insert into T(A,B) values(NULL,'B');
select * from T;
1|A
2|B

 え、マジで?

integer primary keyNULL代入するとrowid+1になる

 そもそもnot null制約がなくても、nullを代入したらrowid+1になるらしい。

1_1.sql

create table T(A integer primary key, B text);
insert into T(A,B) values(NULL,'A');
.echo on
select * from T;
select * from T where A is NULL;
.echo off
select * from T;
1|A
select * from T where A is NULL;
.echo off

 あれ、こうなるの? NULLが入っちゃうような気がしていたが。勘違いだったか、バージョン更新で変わったか。

 nullが入っちゃうのはinteger以外でのprimary keyのときだけ?

not null on conflict ...

 使えるようだが省略する。そもそもNULL値など使うべきでない。

 だからNULLが代入されたときの対処はデフォルトのエラーだけで十分。

ベストプラクティス

  • integer primary keyNULLを代入してもrowid+1になってくれるのでnot null不要(設定しても同様だが短縮できるため不要)
  • integer primary key以外はnot nullにする(NULL撲滅)
    • on conflict ...も使えるがNULL撲滅のためNULLが与えられた時点でエラーにすべきなので不要
    • defaultにて適当な初期値を与える

 たとえば以下。

create table users(
  id    integer  primary key,
  age   integer  not null default 0,
  name  text     not null default '',
  image blob     not null default x''
);

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux

前回まで