Flutter: sqfliteで「ADD COLUMN」を使ってテーブルに複数列を追加しようとしたらエラー

2022/6/21 Flutter エラー・バグ日記 

sqfliteで作成したデータベースをupgradeして、複数の列を追加しようとした。

 

本記事はライトな日記思考で書いているので、詳細説明はしておらず、基本、テキストのみで画像とかは載せておりません。。m(_ _)m

解説記事ではないため、解決していない内容や、その時々の間違った解釈を述べてしまっている可能性が大いにありますので、何卒、ご了承ください。

 

こちらの情報などを拝見し、MySQLでの複数列を追加するSQL文は、

 

ALTER TABLE 'sampleTable1' ADD COLUMN (
    'sampleColumn1' TEXT,
    'sampleColumn2' INTEGER
);

 

のような感じだと分かったので、それを真似て、

 

// クラス・メソッド(関数)・プロパティ(変数)について、筆者が作成したものには、末尾に大文字のオー「O」をつけて表記
// ※パッケージで予め決められているものと区別しやすくするため

// ここでは、dbOはsqfliteのデータベース(Database型)のインスタンス
dbO.execute(
'''ALTER TABLE 'sampleTable1' ADD COLUMN (
    'sampleColumn1' TEXT,
    'sampleColumn2' INTEGER
);'''
)

 

のように実行したら、以下のエラーが出た。

 

E/SQLiteLog(#####): (1) near “(“: syntax error in “ALTER TABLE ‘sampleTable1’ ADD COLUMN (・・・

 

どうやら文法が間違っているらしい。

 

調べてみると、こちらの情報が見つかった。

 

 

どうやら、SQLite(sqfliteが用いているデータベースの仕様)では、単一のステートメントを使用して、テーブルに複数の列を追加することはサポートされていないらしい。

 

複数の列を追加するには、複数の「ALTER TABLE ADD COLUMN」を実行する必要があるとのこと。

 

恥ずかしながら、MySQLとSQLiteでは、こういう点で違いがあることを知る。

 

そこで、以下のように「execute」メソッドの中で、「;」で区切ってみた。

 

dbO.execute(
'''ALTER TABLE 'sampleTable1' ADD COLUMN 'sampleColumn1' TEXT; 
ALTER TABLE 'sampleTable1' ADD COLUMN 'sampleColumn2' INTEGER;'''
)

 

今度はエラーは出なかったが、データを追加する「INSERT INTO」を実行したら、下記のように、「2つめの列(sampleColumn2)が存在しないよ」と言われ、結局エラーになった。

 

E/SQLiteLog(#####): (1) table sampleTable1 has no column named sampleColumn2 in “INSERT INTO sampleTable1 (・・・

 

確かに、「DB Browser for SQLite」でデータベースファイルの中身を確認すると、1つ目の「sampleColumn1」の列しか追加されていなかった(2つ目のSQL文が無視されている)。

 

どうやら、1文ずつ「.execute」メソッドを実行しないといけないらしい。。。

 

こうなると、いくつもSQL文を実行したい場合に面倒だな、、、と思ったが、こちらの情報

 

 

を参考にさせていただき、個々のSQL文をリスト変数に入れ、forループで回すと効率的に実行できると分かった。

 

List<String> queriesO = [
"ALTER TABLE 'sampleTable1' ADD COLUMN 'sampleColumn1' TEXT;",
"ALTER TABLE 'sampleTable1' ADD COLUMN 'sampleColumn2' INTEGER;"
]

for (String queryO in queriesO!) {
        await dbO.execute(queryO);
}

 

これで無事、テーブルに複数列を追加作成し、「INSERT INTO」も問題なく実行できるようになった。

 

ちなみに、上記参考記事によると、更に発展させて、Map型を用いて下記のようにSQL文を用意すれば、データベースのバージョンに応じたマイグレーション処理も簡単に実行できる。

 

※例えば、データベースのバージョン番号を2にしてビルドする場合、Mapのキー「1」とキー「2」のリスト内にあるSQL文を、forループを回して順番に実行すれば良い。

 

// キーとなる整数は、データベースのバージョン番号を表す
Map<int, List<String>> scriptsO = {
1: ["・・・SQL文1・・・;", "・・・SQL文2・・・;", "・・・SQL文3・・・;"],
2: ["・・・SQL文4・・・;", "・・・SQL文5・・・;"],
3: ["・・・SQL文6・・・;", "・・・SQL文7・・・;", "・・・SQL文8・・・;", "・・・SQL文9・・・;"],
}

 

よくよく調べると、この方法は、いくつかの記事で紹介されていた。

 

先人の知恵は凄いなぁと、いつものことながら感心。

 

ありがたく活用させていただきますm(_ _)m

 

\ Flutterの学習で役立ったコンテンツ・書籍 /

 

 

 


Dart入門 – Dartの要点をつかむためのクイックツアー
タイトルとURLをコピーしました