Flutter: sqfliteで「ADD COLUMN」を使ってテーブルに複数列を追加しようとしたらエラー
結論:個々の列を追加するSQL文をリスト変数に入れ、forループで回す
2022/6/21 Flutter エラー・バグ日記
sqfliteで作成したデータベースをupgradeして、複数の列を追加しようとした。
こちらの情報などを拝見し、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で開発)
個人アプリ開発で役立ったもの
おすすめの学習教材
\超初心者向けでオススメな元Udemyの講座/
\キャンペーン時を狙えば安価で網羅的な内容が学べる(日本語訳あり)/
\Gitの基礎について無料で学べる/
おすすめの学習書籍
\実用的。image_pickerに関してかなり助けられた/
\Dartの基礎文法を素早くインプットできる/