hakeの日記

Windows環境でプログラミングの勉強をしています。

SQLite - ROWIDとカラム制約事項

ROWID

特に指定しなくても、レコードをユニークに決定するROWIDというinteger型のカラムが内部的に付加される。

sqlite> create table AAA(ii integer, tt text);
sqlite> insert into AAA values(10, 'aaa'),(20, 'bbb');
sqlite> select rowid,* from AAA;
rowid       ii          tt
----------  ----------  ----------
1           10          aaa
2           20          bbb

 

PRIMARY KEY

主キーを指定する。

create table テーブル名( カラム1名 カラム1型名 primary key, ……);
create table テーブル名( カラム1名 カラム1型名, ……,  primary key(カラム名, …… ));

ひとつのカラムを主キーにする場合はどちらの書き方でも良いが、二つ以上のカラムを主キーにする場合は後者の書き方とする。
主キーの値(複数カラムの場合は値の組み合わせ)が同じレコードを追加することはできない。
注意点として、主キーをNULLにしたレコードは複数追加することが可能。ただし後でNULLを変更した場合に、既に存在する主キーを一致する場合はエラーになる。

sqlite> create table AAA(ii integer, tt text, primary key(ii, tt) );
sqlite> insert into AAA values(10, 'aaa');
sqlite> insert into AAA values(null, 'aaa');
sqlite> insert into AAA values(null, 'aaa');
sqlite> insert into AAA values(40, 'bbb');
sqlite> select rowid,* from AAA;
rowid       ii          tt
----------  ----------  ----------
1           10          aaa
2                       aaa
3                       aaa
4           40          bbb
sqlite> update AAA set ii=10 where rowid=2;
Error: UNIQUE constraint failed: AAA.ii, AAA.tt

sqlite> insert into AAA values(20, 'aaa');

sqlite> insert into AAA values(10, 'aaa');
Error: UNIQUE constraint failed: AAA.ii, AAA.tt

 

INTEGER PRIMARY KEY

INTEGER PRIMARY KEYの場合は自動で増加する値が付加される。
注意点として、INTEGERをINTなどとした場合は付加されない。
最大値のレコードを削除した後に、レコードを追加すると最大値が再利用される。

sqlite> create table AAA(ii integer primary key, tt text);
sqlite> insert into AAA values(null, 'aaa');
sqlite> insert into AAA values(null, 'bbb');
sqlite> select * from AAA;
ii          tt
----------  ----------
1           aaa
2           bbb
sqlite> delete from AAA where tt='bbb';  --最大値のレコードを削除
sqlite> select * from AAA;
ii          tt
----------  ----------
1           aaa
sqlite> insert into AAA values(null, 'ccc');
sqlite> select * from AAA;
ii          tt
----------  ----------
1           aaa
2           ccc   -- 最大値の数値が再利用される

 

INTEGER PRIMARY KEY AUTOINCREMENT

最大値の再利用を指せない様にするには、AUTOINCREMENTを付加する。
AUTOINCREMENTを使用した場合は、最大値を管理するsqlite_sequenceというテーブルが作成される。
なお、INTEGER PRIMARY KEY AUTOINCREMENTを付加したカラムはROWIDと同一になる。

sqlite> create table AAA(ii integer primary key autoincrement, tt text);
sqlite> insert into AAA values(null, 'aaa');
sqlite> insert into AAA values(null, 'bbb');
sqlite> select * from AAA;
ii          tt
----------  ----------
1           aaa
2           bbb
sqlite> delete from AAA where tt='bbb';
sqlite> select * from AAA;
ii          tt
----------  ----------
1           aaa
sqlite> insert into AAA values(null, 'ccc');
sqlite> select * from AAA;
ii          tt
----------  ----------
1           aaa
3           ccc

sqlite> .schema
CREATE TABLE AAA(ii integer primary key autoincrement, tt text);
CREATE TABLE sqlite_sequence(name,seq);

sqlite> select rowid,* from AAA;
ii          ii          tt
----------  ----------  ----------
1           1           aaa
3           3           ccc

 

NOT NULL

NULL(データの無い状態)を許可しない

sqlite> create table AAA(ii integer not null, tt text);

sqlite> insert into AAA values(null, 'aaa');
Error: NOT NULL constraint failed: AAA.ii

sqlite> insert into AAA(tt) values('bbb');
Error: NOT NULL constraint failed: AAA.ii

 

UNIQUE

重複したデータ値を許可しない。
SQLiteの場合は、PRIMARY KEYと同じ意味か?

create table テーブル名( カラム1名 カラム1型名 unique, ……);
create table テーブル名( カラム1名 カラム1型名, ……, unique(カラム名,……));
sqlite> create table AAA(ii integer, tt text, unique(ii, tt));
sqlite> insert into AAA values(1, 'aaa');
sqlite> insert into AAA values(1, 'bbb');
sqlite> insert into AAA values(2, 'aaa');
sqlite> insert into AAA values(1, 'aaa');
Error: UNIQUE constraint failed: AAA.ii, AAA.tt

 

DEFAULT

データを省略した場合のデフォルト値を設定する。

sqlite> create table AAA(ii integer default 100, tt text);
sqlite> insert into AAA values(1, 'aaa');
sqlite> insert into AAA values(null, 'bbb');
sqlite> insert into AAA(tt) values('ccc');
sqlite> select * from AAA;
ii          tt
----------  ----------
1           aaa
            bbb
100         ccc

 

CEHECK

データを格納する前にチェックを行う

create table テーブル名( カラム1名 カラム1型名 check(条件), ……);
create table テーブル名( カラム1名 カラム1型名, ……,  check(条件));
sqlite> create table AAA(ii integer, tt text, check(ii>=0 and ii<=9) );
sqlite> insert into AAA values(1, 'aaa');
sqlite> insert into AAA values(-1, 'bbb');
Error: CHECK constraint failed: AAA
sqlite> insert into AAA values(10, 'ccc');
Error: CHECK constraint failed: AAA

 

外部参照制約(FOREIGN KEY)

参照先の外部テーブルのカラムに存在する値のみ書き込むことができる。
SQLiteでは、この機能はデフォルトでOFFなので、データベースファイルに接続する毎にONする必要があるので注意のこと。

sqlite> PRAGMA foreign_keys; --状態確認
foreign_keys
------------
0
sqlite> PRAGMA foreign_keys  = ON; --外部参照を有効にする
sqlite> PRAGMA foreign_keys;
foreign_keys
------------
1

 

テーブルBBBのカラムidをテーブルAAAのuser_idを参照するようにする。
sqlite> PRAGMA foreign_keys  = ON; --外部参照を有効にする

sqlite> create table AAA(user_id integer primary key autoincrement, name text);
sqlite> insert into AAA values(null,'aaa'),(null,'bbb');
sqlite> select * from AAA;
user_id     name
----------  ----------
1           aaa
2           bbb

sqlite> create table BBB(id integer, rr real, foreign key(id) references AAA(user_id));
sqlite> insert into BBB values(1,1.0);
sqlite> insert into BBB values(2,2.0);
sqlite> insert into BBB values(3,3.0);
Error: FOREIGN KEY constraint failed

sqlite> PRAGMA foreign_keys  = OFF; --外部参照を無効にする
sqlite> PRAGMA foreign_keys;
foreign_keys
------------
0
sqlite> insert into BBB values(3,3.0);--エラーにならない