首页 > 解决方案 > 原因:SQL(查询)错误或缺少数据库。- 在颤振/飞镖中

问题描述

我试图构建一个应用程序,它接受标题、日期、链接、优先级,然后使用 Flutter 和 SQLite 显示它们。我最初在没有“链接”的情况下构建它并且它运行良好,但是当我添加归档的“链接”时,它给了我这个错误:

 E/flutter ( 8491): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: DatabaseException(table task_table has no column named link (code 1): , while compiling: INSERT INTO task_table (title, date, link, priority, status) VALUES (?, ?, ?, ?, ?)
E/flutter ( 8491): #################################################################
E/flutter ( 8491): Error Code : 1 (SQLITE_ERROR)
E/flutter ( 8491): Caused By : SQL(query) error or missing database.
E/flutter ( 8491):  (table task_table has no column named link (code 1): , while compiling: INSERT INTO task_table (title, date, link, priority, status) VALUES (?, ?, ?, ?, ?))
E/flutter ( 8491): #################################################################) sql 'INSERT INTO task_table (title, date, link, priority, status) VALUES (?, ?, ?, ?, ?)' args [math, 2021-04-28T00:00:00.000, google, Medium, 0]}

与此相关的代码分布在两个文件中:一个数据库帮助文件,它基本上存储了数据库管理的所有功能

import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:todo/models/task_model.dart';

class DatabaseHelper {
  static final DatabaseHelper instance = DatabaseHelper._instance();
  static Database _db;

  DatabaseHelper._instance();

  String taskTable = 'task_table';
  String colId = 'id';
  String colTitle = 'title';
  String colDate = 'date';
  String colLink = 'link';
  String colPriority = 'priority';
  String colStatus = 'status';

  // task tables
  // Id | Title | Date | Link | Priority | Status
  //  0     ''     ''     ''        ''
  //  2     ''     ''     ''        ''
  //  3     ''     ''     ''        ''

  Future<Database> get db async {
    if (_db == null) {
      _db = await _initDb();
    }
    return _db;
  }

  Future<Database> _initDb() async {
    Directory dir = await getApplicationDocumentsDirectory();
    String path = dir.path + 'todo_list.db';
    final todoListDb =
        await openDatabase(path, version: 1, onCreate: _createDb);
    return todoListDb;
  }

  void _createDb(Database db, int version) async {
    await db.execute(
        'CREATE TABLE $taskTable($colId INTEGER PRIMARY KEY AUTOINCREMENT, $colTitle TEXT, $colDate TEXT, $colLink TEXT, $colPriority TEXT, $colStatus INTEGER)');
  }

  Future<List<Map<String, dynamic>>> getTaskMapList() async {
    Database db = await this.db;
    final List<Map<String, dynamic>> result = await db.query(taskTable);
    return result;
  }

  Future<List<Task>> getTaskList() async {
    final List<Map<String, dynamic>> taskMapList = await getTaskMapList();
    final List<Task> taskList = [];
    taskMapList.forEach((taskMap) {
      taskList.add(Task.fromMap(taskMap));
    });
    taskList.sort((taskA, taskB) => taskA.date.compareTo(taskB.date));
    return taskList;
  }

  Future<int> insertTask(Task task) async {
    Database db = await this.db;
    final int result = await db.insert(taskTable, task.toMap());
    return result;
  }

  Future<int> updateTask(Task task) async {
    Database db = await this.db;
    final int result = await db.update(taskTable, task.toMap(),
        where: '$colId = ?', whereArgs: [task.id]);
    return result;
  }

  Future<int> deleteTask(int id) async {
    Database db = await this.db;
    final int result =
        await db.delete(taskTable, where: '$colId = ?', whereArgs: [id]);
    return result;
  }
}

第二个文件是数据库模型文件,其中包含数据库创建等:

class Task {
  int id;
  String title;
  DateTime date;
  String link;
  String priority;
  int status; // 0 - complete, 1- complete

  Task({
    this.title,
    this.date,
    this.link,
    this.priority,
    this.status,
  });
  Task.withId({
    this.id,
    this.title,
    this.date,
    this.link,
    this.priority,
    this.status,
  });

  Map<String, dynamic> toMap() {
    final map = Map<String, dynamic>();
    if (id != null) {
      map['id'] = id;
    }
    map['title'] = title;
    map['date'] = date.toIso8601String();
    map['link'] = link;
    map['priority'] = priority;
    map['status'] = status;
    return map;
  }

  factory Task.fromMap(Map<String, dynamic> map) {
    return Task.withId(
        id: map['id'],
        title: map['title'],
        date: DateTime.parse(map['date']),
        link: map['link'],
        priority: map['priority'],
        status: map['status']);
  }
}

这是我第一次在 Flutter 中使用数据库,因此非常感谢任何反馈。谢谢

标签: databasesqliteflutterdart

解决方案


该错误表明您在表中没有可用的列。问题是每次启动应用程序时都不会创建数据库。您的问题有两种解决方案:

  1. 出于调试目的,只需删除应用程序并重新运行代码,这将使用正确的列重新生成数据库。警告:这仅用于调试,不适用于生产。

  2. 对于生产,当您在数据库上添加更改时,您必须增加数据库版本,在您的情况下从 1 到假设为 2。接下来,该openDatabase方法有一个参数onUpgrade,将在升级数据库版本时调用,在您的情况下从1 到 2,在这里你必须运行额外的 sql 命令来更新你的表。像这样的东西:

await openDatabase(path, version: 1, onCreate: _createDb, onUpgrade: (db, old, newVersion) async {
      if(old < 2) {
          await db.execute("ALTER TABLE task_table ADD link TEXT");
      }
});

另外不要忘记更新您的 create table 语句以在此处添加新列。

一种情况是您不想将 保存link在数据库中,在这种情况下,您必须将其从 json serialization (your toMapmethod) 中删除。


推荐阅读