哥哥手把手教你Flutter中SQFLite數據庫的使用---粘去就用那種

Flutter中SQFLite數據庫:

支持事務的批量操作

支持增刪改查

在iOS和Android雙端后臺線程中執行數據庫操作

使用方式:

1,添加依賴

dependencies:... sqflite: any

2,導入文件:

import 'package:sqflite/sqflite.dart';

3, //創建數據庫

Future<String> _createNewDb(String dbName) async {

//獲取數據庫文件路徑

var dbPath = await getDatabasesPath();

print('dbPath:' + dbPath);

String path = join(dbPath, dbName);

if (await new Directory(dirname(path)).exists()) {

await deleteDatabase(path);

} else {

try { await new Directory(dirname(path)).create(recursive: true);

} catch (e) { print(e);

}

}

return path;

}

_create() async {

dbPath = await _createNewDb(dbName);

Database db = await openDatabase(dbPath);

await db.execute(sql_createTable);

await db.close();

setState(() {

_result = '創建user.db成功,創建user_table成功'; });

}

//打開數據庫,獲取數據庫對象

_open() async {

if(null == dbPath){ var path = await getDatabasesPath();

dbPath = join(path, dbName); print('dbPath:' + dbPath);

}

return await openDatabase(dbPath);

}

4,刪除數據庫

await deleteDatabase(path);?

5,打開數據庫并創建一張表? ? ? ? ??

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, value INTEGER, num REAL)");

});? ?

// 插入數據庫的兩種方式

1,Future<int> rawInsert(String sql, [List<dynamic> arguments]);

2,Future<int> insert(String table, Map<String, dynamic> values,?{String nullColumnHack, ConflictAlgorithm conflictAlgorithm});

rawInsert方法第一個參數為一條插入sql語句,可以使用?作為占位符,通過第二個參數填充數據。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? insert方法第一個參數為操作的表名,第二個參數map中是想要添加的字段名和對應字段值。?

示例:

?await database.transaction((txn) async {

?int id1 = await txn.rawInsert( 'INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)');

?print("inserted1: $id1");?

//? 查詢操作的兩種方法

Future<List<Map<String, dynamic>>> query(String table,

?{bool distinct,

?List<String> columns,

?String where,

?List<dynamic> whereArgs,

?String groupBy,

?String having,

?String orderBy,

?intlimit,

?intoffset});

Future<List<Map<String, dynamic>>> rawQuery(String sql,?[List<dynamic> arguments]);?

query方法第一個參數為操作的表名,后邊的可選參數依次表示是否去重、查詢字段、WHERE子句(可使用?作為占位符)、WHERE子句占位符參數值、GROUP BY子句、HAVING子句、ORDER BY子句、查詢的條數、查詢的偏移位等。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rawQuery方法第一個參數為一條查詢sql語句,可以使用?作為占位符,通過第二個參數填充數據。?

示例如下:

await database.transaction ((txn)? async {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int id1 = await txn.rawInsert( 'INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)');? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?print("inserted1: $id1");? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int id2 = await txn.rawInsert( 'INSERT INTO Test(name, value, num) VALUES(?, ?, ?)', ["another name", 12345678, 3.1416]);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?print("inserted2: $id2");});?

//? 更新的兩種方式

Future<int> rawUpdate(String sql, [List<dynamic> arguments]);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Future<int> update(String table, Map<String, dynamic> values,?{String where,?List<dynamic> whereArgs,?ConflictAlgorithm conflictAlgorithm});

rawUpdate方法第一個參數為一條更新sql語句,可以使用?作為占位符,通過第二個參數填充數據。

update方法第一個參數為操作的表名,第二個參數為修改的字段和對應值,后邊的可選參數依次表示WHERE子句(可使用?作為占位符)、WHERE子句占位符參數值、發生沖突時的操作算法(包括回滾、終止、忽略等等)。

示例如下:

int count =awaitdatabase.rawUpdate(

UPDATE Test SET name = ?, VALUE = ? WHERE name = ?',["updated name","9876","some name"]);

print("updated: $count");

// 刪除的兩種方式

Future rawDelete(String sql, [List arguments]);?

Future delete(String table, {String where, List whereArgs});?

rawDelete方法第一個參數為一條刪除sql語句,可以使用?作為占位符,通過第二個參數填充數據。?

delete方法第一個參數為操作的表名,后邊的可選參數依次表示WHERE子句(可使用?作為占位符)、WHERE子句占位符參數值。?

示例如下:

count =awaitdatabase.rawDelete('DELETE FROM Test WHERE name = ?',['an

other name']);

assert(count==1);

// 獲取Test表的數據

List list = awaitdatabase.rawQuery('SELECT * FROM Test');List expectedList=[{"name":"updated name","id":1,"value":9876,"num":456.789},{"name":"another name","id":2,"value":12345678,"num":3.1416}];

print(list);

print(expectedList);

assert(constDeepCollectionEquality().equals(list, expectedList));

// 獲取記錄的數量

count = Sqflite.firstIntValue(awaitdatabase.rawQuery("SELECT COUNT(*) FROM Test"));

assert(count==2);

// 關閉數據庫

await? ?database.close();

Future close() async => db.close();

使用示例如下所示:

其中有一些注意事項:

1,Transcaction?

2,支持批量操作

但是這里注意,這些操作返回結果,都會有一些開銷,如果不考慮結果,可以使用。

事務期間,直到事務被提交,批量操作才能提交。

3,表和列的名字

通常避免使用SQLite關鍵字作為表名或者列名,例如以下其中之一。

如果必須使用如上,需要使用雙引號轉義,例如:

4,支持的列類型

首先,我們創建一個書籍類,包括書籍ID、書名、作者、價格、出版社等信息。

示例二:
finalString tableBook = 'book';

finalString columnId = '_id';

finalString columnName = 'name';

finalString columnAuthor = 'author';

finalString columnPrice = 'price';

finalString columnPublishingHouse = 'publishingHouse';

classBook {

?intid;

?String name;

?String author;

?doubleprice;

?String publishingHouse;

?Map<String, dynamic> toMap() {

?var map = <String, dynamic>{

?columnName: name,

?columnAuthor: author,

?columnPrice: price,

?columnPublishingHouse: publishingHouse

?};

?if(id != null) {

?map[columnId] = id;

?}

?returnmap;

?}

?Book();

?Book.fromMap(Map<String, dynamic> map) {

?id = map[columnId];

?name = map[columnName];

?author = map[columnAuthor];

?price = map[columnPrice];

?publishingHouse = map[columnPublishingHouse];

?}

}

2,創建對應的數據庫文件和表

// 獲取數據庫文件的存儲路徑

?var databasesPath = await getDatabasesPath();

?String path = join(databasesPath, 'demo.db');

//根據數據庫文件路徑和數據庫版本號創建數據庫表

?db = await openDatabase(path, version: 1,

?onCreate: (Database db, intversion) async {

?await db.execute('''

??CREATE TABLE $tableBook (

??$columnId INTEGER PRIMARY KEY,

??$columnName TEXT,

??$columnAuthor TEXT,

??$columnPrice REAL,

??$columnPublishingHouse TEXT)

??''');

?});

3,CRUD實現
// 插入一條書籍數據

Future<Book> insert(Book book) async {

book.id = await db.insert(tableBook, book.toMap());

returnbook;

}

// 查找所有書籍信息

Future<List<Book>> queryAll() async {

List<Map> maps = await db.query(tableBook, columns: [

columnId,

columnName,

columnAuthor,

columnPrice,

columnPublishingHouse

]);

if(maps == null|| maps.length == 0) {

returnnull;

}

List<Book> books = [];

for(inti = 0; i < maps.length; i++) {

books.add(Book.fromMap(maps[i]));

}

returnbooks;

}

// 根據ID查找書籍信息

Future<Book> getBook(intid) async {

List<Map> maps = await db.query(tableBook,

columns: [

?columnId,

?columnName,

?columnAuthor,

?columnPrice,

?columnPublishingHouse

],

where: '$columnId = ?',

whereArgs: [id]);

if(maps.length > 0) {

returnBook.fromMap(maps.first);

}

returnnull;

}

// 根據ID刪除書籍信息

Future<int> delete(intid) async {

returnawait db.delete(tableBook, where: '$columnId = ?', whereArgs: [id]);

}

// 更新書籍信息

Future<int> update(Book book) async {

returnawait db.update(tableBook, book.toMap(),

where: '$columnId = ?', whereArgs: [book.id]);

}

4,關閉數據庫,上文中已提示

5,CRUDUtils

_add() async {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Database db = await _open(); String sql = "INSERT INTO user_table(username,pwd) VALUES('$username','$pwd')";? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//開啟事務? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? await db.transaction((txn) async {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int id = await txn.rawInsert(sql); });? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? await db.close();? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? setState(() {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? _result = "插入username=$username,pwd=$pwd數據成功";? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }) ;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? _delete() async {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Database db = await _open();? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//刪除最近一條? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String sql = "DELETE FROM user_table where id in (select id from user_table order by id desc limit 1)";? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int count = await db.rawDelete(sql);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? await db.close();????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? setState(() {???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (count == 1) {???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?_result = "刪除成功,請查看";???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? } else {???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ? ? ? ? _result = "刪除0條數據或刪除失敗,請看log";???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ? ? } }); }???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?? _update() async {???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? Database db = await _open();???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? String sql = "UPDATE user_table SET pwd = ? WHERE id = ?";???? ??? ??? ??? ??? ??? ??? ??? int count = await db.rawUpdate(sql, ["654321", '1']); print(count);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? await db.close();???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? setState(() {???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?? _result = "更新數據成功,請查看";???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ? ? ? ? ? ? ? ? ? ? }); }???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? //批量增、改、刪數據???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? _batch() async {???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Database db = await _open();???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? var batch = db.batch();???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? batch.insert("user_table", {"username": "batchName1"});???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? batch.update("user_table", {"username": "batchName2"}, where: "username = ?",whereArgs: ["batchName1"]);???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? batch.delete("user_table", where: "username = ?", whereArgs: ["Leon"]);? ? ? ? ? ? ? ? ? ?//返回每個數據庫操作的結果組成的數組 [6, 3, 0]:新增返回id=6,修改了3條數據,刪除了0條數據???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? var results = await batch.commit(); await db.close();???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? setState(() {???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?? _result = "批量增、改數據成功 "+results.toString();???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? }); }???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?? _queryNum() async {???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Database db = await _open(); int count = Sqflite.firstIntValue(???? ??? ??? ??? ??? ??? ??? ??? ??? await db.rawQuery(sql_query_count)); await db.close(); setState(() {???? ??? ??? ??? ??? ??? _result = "數據條數:$count"; });???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? }???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? _query() async {???? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? Database db = await _open(); List<Map> list = await db.rawQuery(sql_query);???? ??? await db.close(); setState(() { _result = "數據詳情:$list"; });? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }?

數據庫的創建、打開,都需要先獲取數據庫文件的路徑,獲取到path之后Database db = await openDatabase(dbPath);獲取數據庫對象,注意數據庫的操作全都是異步的,要用關鍵字await。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。