sqflite 1.1.7+2

  • Readme
  • Changelog
  • Example
  • Installing
  • 100

sqflite #

pub package Build Status codecov

Flutter的 SQLite插件. 同时支持iOS和Android.

  • 支持交易和批次
  • 打开期间自动版本管理
  • 插入/查询/更新/删除查询的助手
  • 在iOS和Android的后台线程中执行的数据库操作

Getting Started #

在flutter项目中添加依赖项:

dependencies:
  ...
  sqflite: ^1.1.7+1

要获得Flutter入门方面的帮助,请查看在线文档 .

Usage example #

Import sqflite.dart

import 'package:sqflite/sqflite.dart';

Opening a database #

SQLite数据库是文件系统中由路径标识的文件. 如果是相对路径,则该路径相对于getDatabasesPath()获得的路径,该路径是Android上的默认数据库目录和iOS上的documents目录.

var db = await openDatabase('my_db.db');

有一个基本的迁移机制可以处理打开期间的模式更改.

许多应用程序使用一个数据库,并且永远不需要关闭它(当应用程序终止时,它将关闭). 如果要释放资源,可以关闭数据库.

await db.close();

Raw SQL queries #

演示代码执行原始SQL查询

// Get a location using getDatabasesPath
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'demo.db');

// Delete the database
await deleteDatabase(path);

// open the database
Database database = await openDatabase(path, version: 1,
    onCreate: (Database db, int version) async {
  // When creating the db, create the table
  await db.execute(
      'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)');
});

// Insert some records in a transaction
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');
});

// Update some record
int count = await database.rawUpdate(
    'UPDATE Test SET name = ?, VALUE = ? WHERE name = ?',
    ['updated name', '9876', 'some name']);
print('updated: $count');

// Get the records
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 the records
count = Sqflite
    .firstIntValue(await database.rawQuery('SELECT COUNT(*) FROM Test'));
assert(count == 2);

// Delete a record
count = await database
    .rawDelete('DELETE FROM Test WHERE name = ?', ['another name']);
assert(count == 1);

// Close the database
await database.close();

对SQL的基本信息在这里 .

SQL helpers #

使用助手的示例

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 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();
}

Read results #

假设有以下读取结果:

List<Map<String, dynamic>> records = await db.query('my_table');

生成的地图项为只读

// get the first record
Map<String, dynamic> mapRead = records.first;
// Update it in memory...this will throw an exception
mapRead['my_column'] = 1;
// Crash... `mapRead` is read-only

如果要在内存中进行修改,则需要创建一个新地图:

// get the first record
Map<String, dynamic> map = Map<String, dynamic>.from(mapRead);
// Update it in memory now
map['my_column'] = 1;

Transaction #

不使用数据库,而仅在事务中使用Transaction对象访问数据库

await database.transaction((txn) async {
  // Ok
  await txn.execute('CREATE TABLE Test1 (id INTEGER PRIMARY KEY)');
  
  // DON'T  use the database object in a transaction
  // this will deadlock!
  await database.execute('CREATE TABLE Test2 (id INTEGER PRIMARY KEY)');
});

如果回调未引发错误,则提交事务. 如果抛出错误,则交易被取消. 因此,回滚事务的一种方法是引发异常.

Batch support #

为了避免在Dart和本机代码之间进行乒乓球,可以使用Batch

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();

获得每个操作的结果是有成本的(插入的ID以及更新和删除的更改数),尤其是在执行额外SQL请求的Android上. 如果您不关心结果而担心大批量的性能,则可以使用

await batch.commit(noResult: true);

警告,在事务处理期间,直到事务提交后,才会提交批处理

await database.transaction((txn) async {
  var batch = txn.batch();
  
  // ...
  
  // commit but the actual commit will happen when the transaction is committed
  // however the data is available in this transaction
  await batch.commit();
  
  //  ...
});

默认情况下,批处理在遇到错误后立即停止(通常会还原未提交的更改). 您可以忽略错误,以便即使一个操作失败也可以运行并落实每个成功的操作:

await batch.commit(continueOnError: true);

Table and column names #

通常,最好避免对实体名称使用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.query('table')

将等同于在表名周围手动添加双引号(在此处令人困惑地命名为table

db.rawQuery('SELECT * FROM "table"');

但是,在任何其他原始语句(包括orderBywheregroupBy )中,请确保使用双引号正确地对名称进行转义. 例如,请参见下面的"列名称group ,在列参数中未转义,但在where参数中已转义.

db.query('table', columns: ['group'], where: '"group" = ?', whereArgs: ['my_group']);

Supported SQLite types #

尚未对值进行有效性检查,因此请避免使用不受支持的类型https://www.sqlite.org/datatype3.html

DateTime不是受支持的SQLite类型. 我个人将它们存储为int(millisSinceEpoch)或字符串(iso8601)

bool不是受支持的SQLite类型. 使用INTEGER以及0和1值.

有关支持的类型的更多信息,请参见此处 .

INTEGER #

  • 飞镖类型: int
  • 支持的值:从-2 ^ 63到2 ^ 63-1

REAL #

  • 飞镖类型: num

TEXT #

  • 飞镖类型: String

BLOB #

  • 飞镖类型: Uint8List
  • 支持Dart类型List<int> ,但不建议使用(转换速度慢)

Current issues #

  • 由于事务在SQLite(线程)中的工作方式,因此不支持并发读写事务. 当前所有呼叫均已同步,并且交易冻结是互斥的. 我认为支持并发访问的一种基本方法是多次打开数据库,但是它只能在iOS上使用,因为Android重用了同一数据库对象. 我还认为本机线程可能是潜在的未来解决方案,但是在android中,在事务中访问另一个线程中的数据库时会被阻止...
  • 目前,INTEGER限制为-2 ^ 63至2 ^ 63-1(尽管Android支持更大的整数)

More #

1.1.7+2 #

  • 凹凸颤抖/飞镖依赖版本(1.9.1 / 2.5.0)
  • 修复Android上已打开的数据库的热启动和热启动
  • 添加代码文档,代码覆盖率和构建标志

1.1.6+5 #

  • 在Android上的后台线程中打开数据库.
  • 以只读方式打开损坏的数据库时,防止在Android上删除数据库.
  • 修复热重启ROLLBACK警告
  • 修复iOS上的索引参数绑定

1.1.5 #

  • databaseExists添加为顶级功能
  • 处理databaseExistsdeleteDatabase相对路径
  • 通过在本机环境中恢复数据库并执行ROLLBACK来防止SQLITE_BUSY错误,从而支持在iOS和Android上进行事务处理时进行热重启
  • 如果在事务中,请在关闭之前执行ROLLBACK以防止SQLITE_BUSY错误

1.1.4 #

  • 使所有数据库操作在iOS上的单独线程中发生

1.1.3 #

  • 修复使用隔离时iOS上的死锁问题

1.1.2 #

  • Sqflite现在在Android上默认使用具有后台线程优先级的线程处理程序

1.1.1 #

  • 使用mixin并将非抖动代码提取到sqlite_api.dart
  • 弃用仅在内部使用的SqfliteOptions

1.1.0 #

  • 突破性的改变 . 从已弃用的原始Android支持库迁移到AndroidX. 这不应该导致任何功能上的变化,但是如果使用原始插件的Android应用程序也必须迁移 ,因此它们也必须进行迁移 .

    您可能会说,thay版本应提高到2.0.0,但这只是一个工具问题,代码未更改. 这是flutter插件中所做更改的副本

1.0.0 #

  • 将0.13.0版本升级为1.0.0
  • 删除已弃用的API(applyBatch,apply)

0.13.0 #

  • 为批处理添加对continueOrError支持

0.12.0 #

  • 添加iOS目标C前缀以防止冲突
  • 在iOS上,创建数据库目录(如果不存在)

0.11.2 #

  • 添加Database.isOpen ,一旦关闭Database.isOpen ,它将变为false

0.11.1 #

  • 添加Sqlflite.hex以允许对Blob字段进行查询

0.11.0 #

  • add getDatabasesPath to use as the base location to create a database
  • 警告:默认情况下,数据库现在是单个实例(基于path ),要使用旧行为,请在打开数据库时使用singleInstance = false
  • dart2稳定支持

0.10.0 #

  • 准备1.0
  • 删除不推荐使用的方法(重入交易)
  • Add Transaction.batch
  • 向开发人员显示警告以防止死锁

0.9.0 #

  • 支持内存数据库( :memory: path)
  • 支持单实例
  • 新的数据库工厂,用于处理新选项

0.8.9 #

  • 升级到SDK 27

0.8.8 #

  • 允许测试约束异常

0.8.6 #

  • 更好的SQL错误报告
  • 捕获Android本机错误
  • 删除数据库失败时不再打印错误

0.8.4 #

  • 使用openReadOnlyDatabase添加只读支持

0.8.3 #

  • 允许使用Transaction.applyBatch在事务期间运行批处理
  • 恢复Batch.commit以在事务外部使用

0.8.2 #

  • 尽管已经在事务中,但允许在打开期间创建嵌套事务

0.8.1 #

  • 新的Transaction机制未使用区域(目前仍支持旧的机制)
  • 开始使用Batch.apply而不是Batch.commit
  • 弃用Database.inTransactionDatabase.synchronized以便不再使用区域

0.7.1 #

  • add Batch.query, Batch.rawQuery and Batch.execute
  • 将查询结果打包为列/行而不是列表

0.7.0 #

  • 添加对--preview-dart-2

0.6.2+1 #

  • 在pubspec.yaml中添加更长的描述

0.6.2 #

  • 修复travis警告

0.6.1 #

  • 将Flutter SDK约束添加到pubspec.yaml

0.6.0 #

  • 添加对onConfigure支持以允许数据库配置

0.5.0 #

  • Escape table and column name when needed in insert/update/query/delete
  • 在新的sql.dart中导出ConflictAlgorithm,escapeName,unescapeName

0.4.0 #

  • 添加对批处理的支持(插入/更新/删除)

0.3.1 #

  • 删除临时并发实验

0.3.0 #

2018/01/04

  • 突破性的改变 . 升级到Gradle 4.1和Android Studio Gradle插件3.0.1. 较早的Flutter项目也需要升级其Gradle设置才能使用此版本的插件. 说明可以在这里找到.

0.2.4 #

  • 对同步的依赖关系更新为> = 1.1.0

0.2.3 #

  • 让Android在与调用者相同的线程中发送响应,以防止发生错误时的意外行为

0.2.2 #

  • 修复Android上未经检查的警告

0.2.0 #

  • 将NSOperationQueue用于iOS上的所有数据库操作
  • 将ThreadHandler用于Android上的所有数据库操作

0.0.3 #

  • 添加异常处理

0.0.2 #

  • 根据Razvan Lung的建议添加sqlite助手

0.0.1 #

  • 初步实验

example/README.md

sqflite_example #

演示如何使用sqflite插件 .

Quick test #

flutter run

特定的应用程序入口点

flutter run -t lib/main.dart

Getting Started #

要获得Flutter入门方面的帮助,请查看在线文档 .

Use this package as a library

1. Depend on it

将此添加到包的pubspec.yaml文件中:


dependencies:
  sqflite: ^1.1.7+2

2. Install it

您可以从命令行安装软件包:

使用Flutter:


$ flutter pub get

另外,您的编辑器可能支持flutter pub get . 查看您的编辑器文档以了解更多信息.

3. Import it

现在,在Dart代码中,您可以使用:


import 'package:sqflite/sqflite.dart';
  
Popularity:
描述该程序包相对于其他程序包的受欢迎程度. [更多]
100
Health:
从静态分析得出的代码运行状况. [更多]
100
Maintenance:
反映出软件包的整洁和最新状态. [更多]
100
Overall:
以上的加权分数. [更多]
100
了解有关得分的更多信息.

我们于2019年11月20日对此软件包进行了分析,并在下面提供了分数,详细信息和建议. using: 分析已完成,状态使用以下命令 :

  • 飞镖:2.6.0
  • 高达:0.12.21
  • Flutter:1.9.1 + hotfix.6

Platforms

检测到的平台:Flutter

参考Flutter,并且没有冲突的库.

Dependencies

Package Constraint Resolved Available
直接依赖
Dart SDK > = 2.5.0 <3.0.0
flutter 0.0.0
path > = 1.5.1 <3.0.0 1.6.4
synchronized > = 2.0.2 <4.0.0 2.1.0+1
传递依存关系
collection 1.14.11 1.14.12
meta 1.1.7 1.1.8
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
开发依赖
flutter_test
http >=0.12.0+2
pedantic > = 1.4.0 <3.0.0
process_run >=0.10.0
test_api any

by  ICOPY.SITE