Flutter中SQLite数据库的使用
同时支持android和ios
支持事务和批量操作
支持插入/查询/更新/删除操作
在iOS和Android上的后台线程中执行数据库操作
1.添加依赖
dependencies:
...
sqflite: any
2.导入依赖
import 'package:sqflite/sqflite.dart';
3.支持SQL查询
// 获取本地SQLite数据库
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, "demo.db");
// 删除数据库
await deleteDatabase(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, value INTEGER, num REAL)");
});
// 开启事务,增加两条记录
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");
});
// 更新一条记录
int count = await database.rawUpdate(
'UPDATE Test SET name = ?, VALUE = ? WHERE name = ?',
["updated name", "9876", "some name"]);
print("updated: $count");
// 获取Test表的数据
List<Map> list = await database.rawQuery('SELECT * FROM Test');
List<Map> 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(const DeepCollectionEquality().equals(list, expectedList));
// 获取记录的数量
count = Sqflite
.firstIntValue(await database.rawQuery("SELECT COUNT(*) FROM Test"));
assert(count == 2);
// 删除一条记录
count = await database
.rawDelete('DELETE FROM Test WHERE name = ?', ['another name']);
assert(count == 1);
// 关闭数据库
await database.close();
4.用法示例
final String tableTodo = "todo";
final String columnId = "_id";
final String columnTitle = "title";
final String columnDone = "done";
class Todo {
int id;
String title;
bool done;
Map<String, dynamic> toMap() {
var map = <String, dynamic>{
columnTitle: title,
columnDone: done == true ? 1 : 0
};
if (id != null) {
map[columnId] = id;
}
return map;
}
Todo();
Todo.fromMap(Map<String, dynamic> map) {
id = map[columnId];
title = map[columnTitle];
done = map[columnDone] == 1;
}
}
class TodoProvider {
Database db;
Future open(String path) async {
db = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute('''
create table $tableTodo (
$columnId integer primary key autoincrement,
$columnTitle text not null,
$columnDone integer not null)
''');
});
}
Future<Todo> insert(Todo todo) async {
todo.id = await db.insert(tableTodo, todo.toMap());
return todo;
}
Future<Todo> getTodo(int id) async {
List<Map> maps = await db.query(tableTodo,
columns: [columnId, columnDone, columnTitle],
where: "$columnId = ?",
whereArgs: [id]);
if (maps.length > 0) {
return new Todo.fromMap(maps.first);
}
return null;
}
Future<int> delete(int id) async {
return await db.delete(tableTodo, where: "$columnId = ?", whereArgs: [id]);
}
Future<int> update(Todo todo) async {
return await db.update(tableTodo, todo.toMap(),
where: "$columnId = ?", whereArgs: [todo.id]);
}
Future close() async => db.close();
}
注意事项
1.Transaction(事务)
当使用transaction对象访问数据时,不能再使用database对象访问数据库
await database.transaction((txn) async {
// 完全Ok
await txn.execute("CREATE TABLE Test1 (id INTEGER PRIMARY KEY)");
// 不能在transaction对象里面使用database对象,这会发生死锁
// await database.execute("CREATE TABLE Test2 (id INTEGER PRIMARY KEY)");
});
2.支持批量操作
batch = db.batch();
batch.insert("Test", {"name": "item"});
batch.update("Test", {"name": "new_item"}, where: "name = ?", whereArgs: ["item"]);
batch.delete("Test", where: "name = ?", whereArgs: ["item"]);
results = await batch.commit();
这些操作返回结果,都会有一些开销;如果你不考虑结果,可以使用:
await batch.commit(noResult: true);
事务期间,直到事务被提交,批量操作才能提交
await database.transaction((txn) async {
var batch = txn.batch();
//...
// 实际提交将在事务启动时发生
await batch.commit();
});
3.表和列的名字
通常避免使用SQLite的关键字作为表名或者列名,例如以下其中之一:
"add","all","alter","and","as","autoincrement","between","case","check","collate","commit","constraint","create","default","deferrable","delete","distinct","drop","else","escape","except","exists","foreign","from","group","having","if","in","index","insert","intersect","into","is","isnull","join","limit","not","notnull","null","on","or","order","primary","references","select","set","table","then","to","transaction","union","unique","update","using","values","when","where"
否则要使用双引号转义,例如:
db.rawQuery('SELECT * FROM "table"');
db.query("table", columns: ["group"], where: '"group" = ?', whereArgs: ["my_group"]);
4.支持的列类型
INTEGER 相当于dart类型中int
REAL 相当于dart类型中num
TEXT 相当于dart类型中String
BLOB 相当于dart类型中Uint8List
Flutter中SQLite数据库的使用的更多相关文章
- Android中SQLite数据库操作(1)——使用SQL语句操作SQLite数据库
下面是最原始的方法,用SQL语句操作数据库.后面的"Android中SQLite数据库操作(2)--SQLiteOpenHelper类"将介绍一种常用的android封装操作SQL ...
- Android中SQLite数据库小计
2016-03-16 Android数据库支持 本文节选并翻译<Enterprise Android - Programing Android Database Applications for ...
- 我的Android六章:Android中SQLite数据库操作
今天学习的内容是Android中的SQLite数据库操作,在讲解这个内容之前小编在前面有一篇博客也是讲解了SQLite数据库的操作,而那篇博客的讲解是讲述了 如何在Window中通过DOM来操作数据库 ...
- Android 中 SQLite 数据库的查看
当 SQLite 数据库创建完成后,如何查看数据库的内容呢?如果直接使用 File Explorer 查看,最多只能看到 database 目录下出现了一个 BookStore.db 文件,Book ...
- iOS 中SQLite数据库操作
在iOS中实现SQLite数据库的操作:1.导入框架(libsqlite3.0.tbd) 2.导入头文件<sqlite3.h> 3.实现数据的增删改查 实现简单 SQLite数据库操作 的 ...
- Android中Sqlite数据库进行增删改查
今天这篇文章写Sqlite数据库,通过一个小案例来完整讲一下数据库常见的CRUD操作. 先对知识点总结: SQLite数据库 轻量级关系型数据库 创建数据库需要使用的api:SQLiteOpenHel ...
- Android 开发中 SQLite 数据库的使用
SQLite 介绍 SQLite 一个非常流行的嵌入式数据库,它支持 SQL 语言,并且只利用很少的内存就有很好的性能.此外它还是开源的,任何人都可以使用它.许多开源项目((Mozilla, PHP, ...
- Android中Sqlite数据库多线程并发问题
最近在做一个Android项目, 为了改善用户体验,把原先必须让用户“等待”的过程改成在新线程中异步执行.但是这样做遇到了多个线程同时需要写Sqlite数据库,导致操作数据库失败. 本人对Java并不 ...
- android中sqlite数据库的基本使用和添加多张表
看了很多关于android使用sqlite数据库的文章,很多都是介绍了数据库的建立和表的建立,而表通常都是只建立一张,而实际情况我们用到的表可能不止一张,那这种情况下我们又该怎么办呢,好了,下面我教大 ...
随机推荐
- python全栈开发 * mysql数据类型 * 180829
* 库的操作 (增删改查)一.系统数据库查看系统库命令 show databases1.information_schema: 虚拟库,不占用磁盘空间,存储的是数据库启动后的一些参数,如用户表信息.列 ...
- CodeForces 1143A The Doors
The Doors 签到题 #include <iostream> using namespace std; int a[200005]; int main() { int n; scan ...
- 终于明白了 C# 中 Task.Yield 的用途
最近在阅读 .NET Threadpool starvation, and how queuing makes it worse 这篇博文时发现文中代码中的一种 Task 用法之前从未见过,在网上看了 ...
- 几何入门合集 gym101968 problem F. Mirror + gym102082 Problem F Fair Chocolate-Cutting + gym101915 problem B. Ali and Wi-Fi
abstract: V const & a 加速 F. Mirror 题意 链接 问题: 有n个人在y=0的平面上(及xoz平面).z=0平面上有一面镜子(边平行于坐标轴).z=a平面上有q个 ...
- 2018-2019-2 网络对抗技术 20165317 Exp3 免杀原理与实践
2018-2019-2 网络对抗技术 20165317 Exp3 免杀原理与实践 实验内容 任务一:正确使用msf编码器,msfvenom生成如jar之类的其他文件,veil-evasion,自己利用 ...
- Nginx(二)-服务模式运行nginx之WINSW
虽然使用命令行控制ngix很简单,但是如果作为一个服务工作的话能更方便地启动.停止或者设置依赖项. 这里使用开源项目Windows Service Wrapper 来实现. github下载地址:ht ...
- liunx安装py.27
liunx安装py.27 按网站(https://blog.csdn.net/u012071918/article/details/78817344) 上的教程安装py.27 1.安装依赖的库 在终端 ...
- Leetcode: Number Complement
Given a positive integer, output its complement number. The complement strategy is to flip the bits ...
- 递归函数 Vue ElementUI
对树形菜单的递归操作,首先应该对树形菜单数据进行整理,优化成自己需要的类型 比如Vue + ElementUI的动态侧边栏数据 export function routerRoleToPretty ( ...
- Elasticsearch.安装(单节点)
Elasticsearch.安装(单节点) 环境Linux 7.x jdk 1.8 elasticsearch 5.x 环境目录结构(根目录多了两个文件夹): /resources /** 存放 ...