やってみる

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

SQLite3謎 主キーの型をintにするとinsertで値を省略したらNULLになってしまう

 原因不明。仕様? バグ?

成果物

期待値

 insertするときidを省略したい。自動的にrowidを入れて欲しい。

問題

 型intとするとid値にNULLが自動挿入される。

create table t1(id int primary key, name text);
insert into t1(name) values('A');
select * from t1;
|A
select * from t1 where id is NULL;
|A

重複エラーにもならない!

 主キーとして機能せず……。

insert into t1(name) values('B');
insert into t1(name) values('C');
insert into t1(name) values('D');
select * from t1;
|A
|B
|C
|D
select * from t1 where id is NULL;
|A
|B
|C
|D

 これはひどいintegerintにしてinsert時に省略しただけで、こんな悲劇が起ころうとは一体だれが想像しただろうか。これを仕様というならもう何も信じられないレベル。もはやイントでなくインポ。不能としか言いようがない。

解決

 型をintでなくintegerにする。

create table t2(id integer primary key, name text);
insert into t2(name) values('A');
select * from t2;
1|A
select * from t2 where id is NULL;



現状まとめ

省略時の値
int NULL
integer rowid

なぜ?

 不明。先述のような違いが生まれる理由は見つけられなかった。

intでもintegerと同じではないのか?

宣言されたタイプにintが含まれている場合、INTEGERアフィニティーが割り当てられます。

 ならintでもintegerと同じ動作になるのでは?

主キーにNULLが含まれることがある

プライマリキーの列値はNULLにできます。これはバグですが、問題が発見された時点で、バグに依存している多くのデータベースがバグに依存していたため、前進するバグの動作をサポートする決定が下されました。

 そもそもこのバグ仕様が悪い。これが一因のはず。

こうするとどうなる?

 エラーになるパターン集。

not null制約

create table t1(id int not null primary key, name text);
insert into t1(name) values('A');
Error: near line 2: NOT NULL constraint failed: t1.id

 insertするときにidを省略できなくなる。

default(rowid)

create table t1(id int not null primary key default(rowid), name text);
Error: near line 1: default value of column [id] is not constant

 default値は定数でないとダメらしい。

所感

 これもバグ? わからんがintでなくintegerにしたほうが良い。intはタイポでインポなかんぽ。詐欺乙。

対象環境

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

前回まで