概要
コマンドラインツールの「.schema」コマンドで表示されるスキーマ文(DDL)を編集する方法。
デフォルトでは編集できないが、「Pragma writable_schema=ON」を設定することで変更できるようになる。
スキーマ文を編集するだけでテーブルに登録されているデータ構造を変更することは出来ない。 詳しくは下記を参照。
以下のような用途に限定される。
- テーブルにカラム(列)を追加して読みにくくなったスキーマ文を修正する
- 外部キー制約を追加する/削除する
- デフォルト値制約を追加する/削除する
- CHECK制約を設定する
詳細
各テーブルやビューのスキーマ文は「sqlite_schema」というテーブルに保存されている。 このテーブルはSQLite3のシステムが使用するテーブルで、ユーザが操作することはほぼない。 (「.table」コマンドでも表示されない)
「sqlite_schema」テーブルはデフォルトだと操作出来ないが 「pragma writable_schema」を変更すると操作できるようになる。
このテーブルの「sql」カラムを更新することでスキーマ文を編集する。
実行例
実行環境
- Windows 10 64bit
- SQLite3 (3.34.0) Command-Line Shell
- 「.schema」コマンドで表示されるスキーマ文(DDL)は「sqlite_schema」テーブルの 「sql」カラムに登録されている。
- デフォルトのまま「sqlite_schema」テーブルを更新しようとしてもエラーになる。
- 
                  「writable_schema」をONにすると更新できるようになる。
 以下の点に気を付ければいい。- 改行や空白がそのまま反映される。
- セミコロン(;)は無くてもいい。
- 「tbl_name」がテーブル名を指しているのでwhere句でテーブル名を指定する。
 
- 更新した内容が「.schema」コマンドで表示される。
- 終わったら「writable_schema」はOFFにしておく。
                    
sqlite> create table test (id integer, name text);
sqlite> .schema test
CREATE TABLE test (id integer, name text);
sqlite> -- # 1.
sqlite> .mode table
sqlite> select * from sqlite_schema;
+-------+------+----------+----------+-------------------------------------------+
| type  | name | tbl_name | rootpage |                    sql                    |
+-------+------+----------+----------+-------------------------------------------+
| table | test | test     | 2        | CREATE TABLE test (id integer, name text) |
+-------+------+----------+----------+-------------------------------------------+
sqlite> -- # 2.
sqlite> update
   ...>     sqlite_schema
   ...> set
   ...>     sql=
   ...> 'create table test (
   ...>     id   integer,
   ...>     name text
   ...> )'
   ...> where
   ...>     tbl_name = 'test';
Error: table sqlite_master may not be modified
sqlite> -- # 3.
sqlite> pragma writable_schema=on;
sqlite> update
   ...>     sqlite_schema
   ...> set
   ...>     sql=
   ...> 'create table test (
   ...>     id   integer,
   ...>     name text
   ...> )'
   ...> where
   ...>     tbl_name = 'test';
sqlite> -- # 4.
sqlite> .schema test
create table test (
    id   integer,
    name text
);
sqlite> -- # 5.
sqlite> pragma writable_schema=off;
sqlite>
                    
                
         データ構造は変更されない
スキーマ文だけを変更してもテーブルのデータには影響しない。 その結果、スキーマ文とデータに齟齬が出てしまう。
テーブルのデータ構造を変更する場合は alter table などのDDLを使用したほうがいい。
データ構造が変更されない状況の例
- データが入っているテーブルのスキーマ文からカラムを削除する。
- スキーマ文にないカラムにデータを挿入することはできるし、参照もできてしまう。
sqlite> .mode table
sqlite> create table test (id integer, name text);
sqlite> insert into test values (1, 'sample_name');
sqlite> select * from test;
+----+-------------+
| id |    name     |
+----+-------------+
| 1  | sample_name |
+----+-------------+
sqlite> -- # 1.
sqlite> pragma writable_schema=on;
sqlite> update
   ...>     sqlite_schema
   ...> set
   ...>     sql='create table test (id integer)'
   ...> where
   ...>     tbl_name = 'test'
   ...> ;
sqlite> .schema test
create table test (id integer);
sqlite> -- # 2.
sqlite> insert into test values (2, 'sample_name2');
sqlite> select * from test;
+----+--------------+
| id |     name     |
+----+--------------+
| 1  | sample_name  |
| 2  | sample_name2 |
+----+--------------+
                
               上記のようになってしまう理由は
               sqlite 3 ではスキーマ文とテーブルのデータが別々に管理されているため。
               
               詳しい情報は
               
                  公式サイト
               
               を参照のこと
            
参考URL
- 
                  Pragma writable_schema
 公式の writable_schema に関するドキュメント
 https://www.sqlite.org/pragma.html#pragma_writable_schema