Flutter SQFlite多对多关系配置求助:如何关联两张表?
处理SQFlite中的多对多关系
你说得对,在SQLite(包括Flutter的SQFlite插件)里处理多对多关系,必须创建第三张中间关联表——这是关系型数据库处理这类关联的标准方案,因为两张表无法直接存储双向的多对多映射。
为什么需要中间表?
A表的一条记录对应多条B记录,同时B表的一条记录也对应多条A记录,这种双向关联没法通过在A或B表中添加外键字段实现(那样只能存单个关联,无法满足多个)。中间表的作用就是存储每一对A和B的关联关系,每条记录代表一个“A-B”的绑定。
修改你的数据库创建代码
我帮你调整了onCreate方法,添加了中间表(命名为A_B,你也可以改成更贴合业务的名字,比如a_b_relationship):
static Future<Database> database() async { final dbPath = await sql.getDatabasesPath(); return sql.openDatabase( path.join(dbPath, 'my_db.db'), onCreate: (db, version) { return db.execute(''' CREATE TABLE A( id INTEGER PRIMARY KEY, title TEXT, description TEXT ); CREATE TABLE B( id INTEGER PRIMARY KEY, title TEXT, description TEXT ); CREATE TABLE A_B( a_id INTEGER, b_id INTEGER, -- 联合主键确保同一个A-B关联不会重复存储 PRIMARY KEY(a_id, b_id), -- 外键约束保证关联的A/B记录存在 FOREIGN KEY(a_id) REFERENCES A(id) ON DELETE CASCADE, FOREIGN KEY(b_id) REFERENCES B(id) ON DELETE CASCADE ); '''); }, version: 1, ); }
代码说明:
INTEGER PRIMARY KEY:SQLite推荐用INTEGER而非INT,如果不手动指定id,SQLite会自动为每条记录生成唯一的自增id(如果需要手动管理id也可以保留原来的写法,但自增更省心)。- 中间表
A_B的PRIMARY KEY(a_id, b_id):确保同一个A和B的组合不会被重复插入。 ON DELETE CASCADE:可选配置,意思是如果A表或B表中的某条记录被删除,中间表中对应的关联记录会自动删除,避免无效的关联数据。如果不需要这个行为,可以去掉这部分。
如何操作多对多关联?
1. 关联A和B记录
当你需要把A表中id为aId的记录和B表中id为bId的记录关联起来时,只需往中间表插入一条记录:
await db.insert( 'A_B', {'a_id': aId, 'b_id': bId}, conflictAlgorithm: ConflictAlgorithm.ignore, // 避免重复插入时报错 );
2. 查询A记录对应的所有B记录
通过JOIN查询获取关联数据:
// 查询id为1的A记录关联的所有B记录 final List<Map<String, dynamic>> bRecords = await db.rawQuery(''' SELECT B.* FROM B JOIN A_B ON B.id = A_B.b_id WHERE A_B.a_id = ? ''', [1]); // 转换为你自定义的B模型(如果有的话) final List<BModel> bList = bRecords.map((map) => BModel.fromMap(map)).toList();
3. 查询B记录对应的所有A记录
逻辑和上面类似,调整JOIN的方向即可:
// 查询id为2的B记录关联的所有A记录 final List<Map<String, dynamic>> aRecords = await db.rawQuery(''' SELECT A.* FROM A JOIN A_B ON A.id = A_B.a_id WHERE A_B.b_id = ? ''', [2]);
这样就能完整实现A和B表之间的多对多关系管理了,如果有其他具体的业务场景需要优化,随时可以再细化!
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

