如何在
sqflite
中快速插入多条记录?标准的快速方法是:
await database.insert(table, object.toMap())
但我不认为用循环一对一插入记录是一个好主意。 或者我可以通过交易插入所有列表?
正如我在评论中提到的,您可以使用
Batch
。这是示例。
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();
如果您正在寻找快速性能,请忽略结果并使用
await batch.commit(noResult: true);
在这种情况下你可以使用批处理。
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);
如果您有要插入的对象列表,您可以这样做(这不是一个非常干净的代码,但它可以工作):
insertClients(List<Client> clients) async {
final db = await database;
var buffer = new StringBuffer();
clients.forEach((c) {
if (buffer.isNotEmpty) {
buffer.write(",\n");
}
buffer.write("('");
buffer.write(c.firstName);
buffer.write("', '");
buffer.write(c.lastName);
buffer.write("', '");
buffer.write(c.address);
buffer.write("')");
});
var raw =
await db.rawInsert("INSERT Into Clients (firstName,lastName,address)"
" VALUES ${buffer.toString()}");
return raw;
}
我正在使用 SQLite 中的这条语句:
INSERT INTO 'tablename' ('column1', 'column2') VALUES
('data1', 'data2'),
('data1', 'data2'),
('data1', 'data2');
我看到了使用数据库事务的可能性,与Android非常相似。 我发现使用它们更好,这里我展示了一个代码示例,如果它对某人有用的话。 在我的示例中,显示了 try-catch,但可以使用 Future 函数回调来获得更清晰的代码:
Future<List<dynamic>> insertAll(String table, List<dynamic> objects) async {
List<dynamic> listRes = new List();
var res;
try {
await DbHelper().database.transaction((db) async {
objects.forEach((obj) async {
try {
var iRes = await db.insert(table, obj.toMap());
listRes.add(iRes);
} catch (ex) {
DbHelper().databaseLog(CON_INSERT_MULTIPLE, "Error!", ex);
}
});
});
DbHelper().databaseLog(CON_INSERT_MULTIPLE, table, listRes);
res = listRes;
} catch (er) {
res = OutComeCallClient.ERROR;
DbHelper().databaseLog(CON_INSERT_MULTIPLE, "Error!", er);
}
return res;
}
这是我的代码,也许可以提供帮助;) 感谢米哈伊V。
insertOrUpdateAll(List<Map<String, dynamic>> ticks) async {
if (ticks.length == 0) return null;
final columns = ticks.first.keys.join(",");
var valuesBuffer = new StringBuffer();
ticks.forEach((task) {
if (valuesBuffer.isNotEmpty) valuesBuffer.write(",\n");
valuesBuffer.write("(");
int ix = 0;
task.forEach((key, value) {
if (ix++ != 0) valuesBuffer.write(',');
final isString =
columnsInfo.where((c) => c.name == key).first.type == RowType.text;
if (isString) valuesBuffer.write("'$value'");
valuesBuffer.write(value);
});
valuesBuffer.write(")");
});
return await db.rawInsert("INSERT Into Clients ($columns)"
" VALUES ${valuesBuffer.toString()}");
}
Model
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
final String tableName = "todom";
final String Column_id = "id";
final String Column_name = "name";
class TaskModel{
final String name;
int id;
TaskModel({this.name, this.id});
Map<String, dynamic> toMap(){
return {
Column_name : this.name
};
}
}
class TodoHelper{
Database db;
TodoHelper(){
initDatabase();
}
Future<void> initDatabase() async{
db = await openDatabase(
join(await getDatabasesPath(), "databse.db"),
onCreate: (db, version){
return db.execute("CREATE TABLE $tableName($Column_id INTEGER PRIMARY KEY AUTOINCREMENT, $Column_name TEXT)");
},
version: 1
);
}
Future<void> insertTask(TaskModel task) async{
try{
db.insert(tableName, task.toMap(), conflictAlgorithm: ConflictAlgorithm.replace);
}catch(_){
print(_);
}
}
Future<List<TaskModel>> getAllTask () async{
final List<Map<String, dynamic>> tasks = await db.query(tableName);
return List.generate(tasks.length, (i){
return TaskModel(name: tasks[i][Column_name], id: tasks[i][Column_id]);
});
}
}
main.dart
import 'package:flutter/material.dart';
import 'TaskModel.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final textController = TextEditingController();
List<TaskModel> tasks = [];
TaskModel currentTask;
@override
Widget build(BuildContext context) {
final TodoHelper _todoHelper = TodoHelper();
return Scaffold(
body: Container(
padding:EdgeInsets.all(32),
child: Column(
children: <Widget>[
TextField(
controller: textController,
),
FlatButton(
child: Text("Insert"),
onPressed: (){
currentTask = TaskModel(name: textController.text);
_todoHelper.insertTask(currentTask);
},
color: Colors.blue,
textColor: Colors.white,
),
FlatButton(
child: Text("Show All Task"),
onPressed: () async{
List<TaskModel> list = await _todoHelper.getAllTask();
setState(() {
tasks = list;
});
},
color: Colors.red,
textColor: Colors.white,
),
Expanded(
child: ListView.separated(
itemBuilder: (context, index){
return ListTile(
leading: Text("${tasks[index].id}"),
title: Text("${tasks[index].name}"),
);
},
separatorBuilder: (context, index) => Divider(),
itemCount: tasks.length,
),
)
],
),
),
);
}
}
你可以尝试使用 rawInsert
Database db = await instance.database;
String sql = '''
INSERT INTO p_tasklistproviderobjective (
idticket,
objective
) VALUES (?, ?)
''';
//you can get this data from json object /API
List<Map> data = [
{"idticket": 5, "objective": "dono"},
{"idticket": 6, "objective": "dono2"},
{"idticket": 7, "objective": "dono3"},
{"idticket": 8, "objective": "dono4"},
];
//and then loop your data here
data.forEach((element) async {
await db.rawInsert(sql, [element['idticket'], element['objective']]);
});
SQFLite 不提供批量插入的方法。即使他们有批量概念,你也没有得到有效的回应。
例如,我要在表中逐一插入 10 行,这需要 5 秒。这里我使用 for 循环逐一迭代插入查询。
在批处理概念的同一示例中,我们将在批处理事务查询中传递一个包含 10 行的列表,它将像我们在传统方法中那样运行循环所以基本上正常插入需要 5 秒,然后批处理概念同样需要 4 秒会工作
所以我更喜欢使用Isolate概念来在短时间内插入大量数据。
注意:如果您在错误的地方使用隔离,可能会导致内存问题。在接触隔离概念之前,请先阅读文档。隔离并不适合所有此类情况。
尝试使用隔离请参阅以下博客
https://medium.com/flutter-community/isolates-in-flutter-a0dd7a18b7f6