sqlite は、クライアント/サーバ形態でない組み込み用のデータベースソフトとして、最近注目を浴びています。この sqlite ですが、現在のバージョンである sqlite3 と、昔のバージョンである sqlite2 の二系統があります。もちろん、今から使うには sqlite3 の方がよいのですが、PHP などでは、まだまだ sqlite2 が使用されています。
ところで、sqlite2 では、一度作った表に新しい列を追加しようとしても、それを一発で操作できる SQL はありませんでした。そこで、それを行うために、一度一時的な表を作成し、そこに現在の表をコピー、新しく列が追加された表を作成、一時的な表から新しい表へコピーすると言う方法で、列を追加すると言う方法をとります。
以下に例を示します。このコードでは、a, b, c, という integer 型の表 test を作成し、そこに、(1,2,3) というレコードを挿入しています。そのような表に対し、新しい列 integer 型の d を追加しています。“BEGIN TRANSACTION”から“COMMIT”までの間のコードがそれです。
SQLITE_MASTER というのは、このデータベースで使用可能な表の情報を保持しているシステムの表です。
実行コマンド
CREATE TABLE test (a integer,b integer,c integer); SELECT * FROM SQLITE_MASTER; INSERT INTO test (a,b,c) VALUES(1,2,3); SELECT * FROM test; BEGIN TRANSACTION; CREATE TEMPORARY TABLE test_temp(a integer,b integer,c integer); INSERT INTO test_temp SELECT * FROM test; DROP TABLE test; CREATE TABLE test (a integer,b integer,c integer,d integer); INSERT INTO test SELECT *,null FROM test_temp; DROP TABLE test_temp; COMMIT; SELECT * FROM SQLITE_MASTER; SELECT * FROM test;
実行結果
SQLite version 2.8.17 Enter ".help" for instructions sqlite> CREATE TABLE test (a integer,b integer,c integer); sqlite> SELECT * FROM SQLITE_MASTER; table|test|test|3|CREATE TABLE test (a integer,b integer,c integer) sqlite> INSERT INTO test (a,b,c) VALUES(1,2,3); sqlite> SELECT * FROM test; 1|2|3 sqlite> sqlite> BEGIN TRANSACTION; sqlite> CREATE TEMPORARY TABLE test_temp(a integer,b integer,c integer); sqlite> INSERT INTO test_temp SELECT * FROM test; sqlite> DROP TABLE test; sqlite> CREATE TABLE test (a integer,b integer,c integer,d integer); sqlite> INSERT INTO test SELECT *,null FROM test_temp; sqlite> DROP TABLE test_temp; sqlite> COMMIT; sqlite> sqlite> SELECT * FROM SQLITE_MASTER; table|test|test|3|CREATE TABLE test (a integer,b integer,c integer,d integer) sqlite> SELECT * FROM test; 1|2|3| sqlite>
sqlite3 では、この操作は、“ALTER TABLE ... ADD COLUMN ...”という SQL で一発で操作できるようになりました。ただし、この SQL を実行したデータベースファイルは、VACUUM を実行するまで、3.1.3 以前のバージョンからそのデータベースファイルを読み込むことができないという問題があるので、ただちに VACUUM を実行しておいたほうがよいでしょう。
実行コマンド
CREATE TABLE test (a integer,b integer,c integer); SELECT * FROM SQLITE_MASTER; INSERT INTO test (a,b,c) VALUES(1,2,3); SELECT * FROM test; ALTER TABLE test ADD COLUMN d integer; VACUUM; SELECT * FROM SQLITE_MASTER; SELECT * FROM test;
実行結果
SQLite version 3.3.13 Enter ".help" for instructions sqlite> CREATE TABLE test (a integer,b integer,c integer); sqlite> SELECT * FROM SQLITE_MASTER; table|test|test|2|CREATE TABLE test (a integer,b integer,c integer) sqlite> INSERT INTO test (a,b,c) VALUES(1,2,3); sqlite> SELECT * FROM test; 1|2|3 sqlite> sqlite> ALTER TABLE test ADD COLUMN d integer; sqlite> VACUUM; sqlite> sqlite> SELECT * FROM SQLITE_MASTER; table|test|test|2|CREATE TABLE test (a integer,b integer,c integer, d integer) sqlite> SELECT * FROM test; 1|2|3| sqlite>