使用sqflite多表关联查询时出现“no such table”错误求助
解决sqflite多表关联查询的"no such table"问题
你的错误核心是每个表对应了独立的数据库文件(比如items.db、users.db、userItems.db),而sqflite的多表关联查询只能在同一个数据库文件内的表之间执行,跨数据库文件无法直接关联。下面是正确的实现方式:
1. 统一所有表到同一个数据库文件
所有业务表(users、items、userItems)都要创建在同一个数据库文件中,比如命名为app_database.db。
2. 重构DatabaseService类
让它维护单一的数据库实例,初始化时一次性创建所有表:
import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; class DatabaseService { static final DatabaseService _instance = DatabaseService._internal(); factory DatabaseService() => _instance; DatabaseService._internal(); Database? _database; Future<Database> get database async { if (_database != null) return _database!; _database = await _initDatabase(); return _database!; } Future<Database> _initDatabase() async { final dbPath = await getDatabasesPath(); final path = join(dbPath, 'app_database.db'); // 统一数据库文件名 return await openDatabase( path, version: 1, onCreate: (db, version) async { // 批量创建所有表 await _createItemsTable(db); await _createUsersTable(db); await _createUserItemsTable(db); }, ); } // 创建items表 Future<void> _createItemsTable(Database db) async { const tableName = "items"; await db.execute("""CREATE TABLE IF NOT EXISTS $tableName ( "itemId" INTEGER NOT NULL, "itemName" TEXT NOT NULL, "itemType" TEXT NOT NULL, "itemSubType" TEXT NOT NULL, PRIMARY KEY ("itemId" AUTOINCREMENT) );"""); } // 创建users表(修复原SQL语法错误:PRIMARY KEY前缺逗号) Future<void> _createUsersTable(Database db) async { const tableName = "users"; await db.execute("""CREATE TABLE IF NOT EXISTS $tableName ( "username" TEXT NOT NULL, "mail" TEXT NOT NULL, "password" TEXT NOT NULL, "birthdate" INTEGER NOT NULL, PRIMARY KEY ("username") );"""); } // 创建userItems表(修复原SQL语法错误,明确外键关联列) Future<void> _createUserItemsTable(Database db) async { const tableName = "userItems"; await db.execute("""CREATE TABLE IF NOT EXISTS $tableName ( "username" TEXT NOT NULL, "itemId" INTEGER NOT NULL, "quantity" INTEGER NOT NULL, PRIMARY KEY ("username", "itemId"), FOREIGN KEY (username) REFERENCES users(username), FOREIGN KEY (itemId) REFERENCES items(itemId) );"""); } }
3. 修改多表查询代码
使用统一的DatabaseService实例,即可正常执行关联查询:
Future<List<UserItems>> fetchUserItems(String username) async { final database = await DatabaseService().database; final userItems = await database.rawQuery( ''' SELECT items.itemName, userItems.quantity FROM items INNER JOIN userItems ON userItems.itemId = items.itemId WHERE userItems.username = ? ORDER BY items.itemName ASC ''', [username] ); return userItems.map((row) => UserItems.fromSqfliteDatabase(row)).toList(); }
建议给列名加上表前缀,避免多表查询时的列名冲突。
4. 清理旧数据库文件
卸载并重装应用,或者手动清理应用数据,删除之前创建的独立数据库文件(如items.db等),避免残留数据干扰。
内容的提问来源于stack exchange,提问作者Miriana
相关产品推荐
相关产品推荐

