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

※当サイトは、アフィリエイト広告を利用しています

結論:個々の列を追加するSQL文をリスト変数に入れ、forループで回す 

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で開発)

 

個人アプリ開発で役立ったもの

おすすめの学習教材

超初心者向けでオススメな元Udemyの講座/

 

 \キャンペーン時を狙えば安価で網羅的な内容が学べる(日本語訳あり)/

 

\Gitの基礎について無料で学べる/

 

おすすめの学習書籍

実用的image_pickerに関してかなり助けられた/

 

Dartの基礎文法を素早くインプットできる/


Dart入門 - Dartの要点をつかむためのクイックツアー

タイトルとURLをコピーしました