概要
準備
パッケージの追加
dependencies: sqflite: ^2.3.0
インポート文
import 'package:sqflite/sqflite.dart';
基本操作
データベースの作成&削除
- 以下の手順ではここで生成したテーブルを使用します。
- ファイル名を指定してテーブルを構築します。
- getDatabasesPathはデフォルトのデータベース保存用フォルダのパスを取得できるとのこと。
- 生成されるテーブル(テーブル名:Test)
id(主キー) | name | age |
---|
// getDatabasesPathを取得 var databasesPath = await getDatabasesPath(); String path = '$databasesPath/demo.db'; // データベースを開く(pathに存在しなければ新規作成) Database database = await openDatabase( path, version: 1, onCreate: (Database db, int version) async { await db.execute( 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)' ); });
ちなみに作成したテーブルは以下の操作で削除できます。
await deleteDatabase(path);
データの追加(rawInsert, insert)
- (1) rawInsert(SQL文を使った方法)と(2) insert(Mapとかを引数に持つ関数を指定)の2つの方法がある。
- どちらの場合でもidを未指定の場合は連番で自動的に決定される。
(1)rawInsert(SQL文を使った方法)
- SQL文を文字列として認識する方法と、数値などの引数のみ外に出す方法の2つがあります。
// SQLを文字列として認識 await database.rawInsert( 'INSERT INTO Test(name, age) VALUES("アリス", 22)' ); // 引数のみ外で指定 await database.rawInsert( 'INSERT INTO Test(name, age) VALUES(?, ?)', ['マイク', 1234] );
実行後のテーブル
id(主キー) | name | age |
---|---|---|
1 | アリス | 22 |
2 | マイク | 1234 |
(2)insert(Mapとかを引数に持つ関数を指定)
- テーブル名、追加したいデータ(Map型)を指定します(ほかの引数は公式ドキュメントを参考にしてください)。
await database.insert( 'Test', {'name': 'ケビン', 'age': 48}, ); // idを明示して追加((1), (2)どちらでも可能) await database.insert( 'Test', {'id': 13, 'name': 'ブラック', 'age': 4}, );
実行後のテーブル(赤字が追加データ)
id(主キー) | name | age |
---|---|---|
1 | アリス | 22 |
2 | マイク | 1234 |
3 | ケビン | 48 |
13 | ブラック | 4 |
データ更新(rawUpdate, update)
- テーブルは先ほどの続きです。
- 追加と同様に(1) rawUpdate(SQL文を使った方法)と(2) update(関数利用)の2つの方法がある。
(1)rawUpdate(SQL文を使った方法)
- 追加と同様にSQL文を文字列として認識する方法と、数値などの引数のみ外に出す方法の2つがありますが、後者のみ載せています。
// アリスを更新 await database.rawUpdate( 'UPDATE Test SET name = ?, age = ? WHERE name = ?', ['エミリー', 98, 'アリス'] );
実行後のテーブル(変更したデータのみ赤字)
id(主キー) | name | age |
---|---|---|
1 | エミリー | 98 |
2 | マイク | 1234 |
3 | ケビン | 48 |
13 | ブラック | 4 |
(2)update(関数利用)
- 引数はテーブル名、変更後のデータ(Map型)、検索に使用するカラム名、削除したいid, nameなどの数値です。(ほかの引数は公式ドキュメントを参考にしてください)。
// 「id=3」を更新 await database.update( 'Test', {'id': 4, 'name': 'ジム'}, where: 'id = ?', whereArgs: [3] );
実行後のテーブル(変更したデータのみ赤字)
id(主キー) | name | age |
---|---|---|
1 | エミリー | 98 |
2 | マイク | 1234 |
4 | ジム | 48 |
13 | ブラック | 4 |
データの削除(rawDelete, delete)
- テーブルは先ほどの続きです。
- 追加と同様に(1) rawDelete(SQL文を使った方法)と(2) delete(関数利用)の2つの方法がある。
(1)rawDelete(SQL文を使った方法)
- 追加と同様にSQL文を文字列として認識する方法と、数値などの引数のみ外に出す方法の2つがあります。
// 「name = ケビン」を削除 await database.rawDelete( 'DELETE FROM Test WHERE name = ?', ['ケビン'] ); // 「age = 4」(ブラック)を削除 await database.rawDelete( 'DELETE FROM Test WHERE age = 4' );
実行後のテーブル
id(主キー) | name | age |
---|---|---|
1 | アリス | 22 |
2 | マイク | 1234 |
(2)delete(関数利用)
- 引数はテーブル名、削除に使うカラム、削除したいid, nameなどの数値です。(ほかの引数は公式ドキュメントを参考にしてください)。
// 「id = 2」(マイク)を削除 await database.delete( 'Test', where: 'id = ?', whereArgs: [2]
実行後のテーブル
id(主キー) | name | age |
---|---|---|
1 | アリス | 22 |
テーブルの表示
List<Map> list = await database.rawQuery('SELECT * FROM Test'); print(list);
デモアプリ
- データの追加・削除・更新ができる簡単なアプリを製作しました。
- idが同じデータを追加するときにエラーが出るなどはありますがご容赦ください。
ソースコード
入力フォーム
import 'package:flutter/material.dart'; class DataInputForm extends StatelessWidget { final Function(int id) updateId; final Function(String name) updateName; final Function(int age) updateAge; const DataInputForm({super.key, required this.updateId, required this.updateName, required this.updateAge}); @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ TextFormField( keyboardType: TextInputType.number, onChanged: (value) => updateId(int.parse(value)), decoration: const InputDecoration( labelText: 'id', border: OutlineInputBorder(), ) ), const SizedBox(height: 10), TextFormField( keyboardType: TextInputType.name, onChanged: (value) => updateName(value), decoration: const InputDecoration( labelText: 'name', border: OutlineInputBorder(), ) ), const SizedBox(height: 10), TextFormField( keyboardType: TextInputType.number, onChanged: (value) => updateAge(int.parse(value)), decoration: const InputDecoration( labelText: 'age', border: OutlineInputBorder(), ) ), ], ); } }
メイン画面
import 'package:flutter/material.dart'; import 'data_input_form.dart'; import 'package:sqflite/sqflite.dart'; // データベースのパスとオブジェクト late String path; late Database database; List<Map> listMap = []; void main() async { // これがないと「 Unhandled Exception: Binding has not yet been initialized.」というエラーが出る WidgetsFlutterBinding.ensureInitialized(); // パスを取得 var databasesPath = await getDatabasesPath(); path = '$databasesPath/demo.db'; // データベースを開く database = await openDatabase( path, version: 1, onCreate: (Database db, int version) async { await db.execute( 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)' ); }); final app = MaterialApp( title: 'Flutter Demo', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const MyHomePage(), ); runApp(app); } class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int? id; String? name; int? age; void updateId(int id){ setState(() { this.id = id; }); } void updateName(String name){ setState(() { this.name = name; }); } void updateAge(int age){ setState(() { this.age = age; }); } void updateList() async { listMap = await database.rawQuery('SELECT * FROM Test'); setState(() {}); } @override void initState() { super.initState(); // リストを初期化 updateList(); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ // データベースを削除 ElevatedButton( onPressed: () async { // データベースを削除 await deleteDatabase(path); // データベースを再度開く database = await openDatabase( path, version: 1, onCreate: (Database db, int version) async { await db.execute( 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)' ); }); // 表示を更新 listMap = []; setState(() {}); }, child: const Text('データベースを初期化'), ), // Id, name, numを入力 DataInputForm( updateId: updateId, updateName: updateName, updateAge: updateAge ), // id, name, numのいずれも埋まっていたらinsert, updateが可能 if(id!=null)...{ // 削除 ElevatedButton( onPressed: () async{ await database.delete( 'Test', where: 'id = ?', whereArgs: [id] ); // 表示を更新 updateList(); }, child: const Text('id指定でdelete'), ), if(name!=null && age!=null)...{ // 更新 ElevatedButton( onPressed: () async{ await database.update( 'Test', {'name': name, 'age': age}, where: 'id = ?', whereArgs: [id] ); // 表示を更新 updateList(); }, child: const Text('id指定でupdate'), ), // 追加 ElevatedButton( onPressed: () async{ await database.insert( 'Test', {'id': id, 'name': name, 'age': age}, ); // 表示を更新 listMap = await database.rawQuery('SELECT * FROM Test'); setState(() {}); }, child: const Text('insert'), ) }, }, // データを表示 const Text( 'データ表示', style: TextStyle( fontSize: 20 ), ), for (var map in listMap) ...{ Text('id = ${map["id"]}, name = ${map["name"]}, age = ${map["age"]}'), } ], ), ), ); } }
実行画面