如何在 iOS 应用程序中连接来自 FMDB 中两个不同数据库的两个表

How to join two tables from two different databases in FMDB in a iOS app

我的场景是这样的。 出于安全原因,我决定将应用程序数据放入捆绑包,将用户数据放入文档目录。 问题是如何加入来自不同数据库的tables? 如果不可能,我是否必须在文档目录中为数据库创建一个 table?

Sqlite3 允许将外部数据库附加到当前连接。 想象一下,您有两个数据库,每个数据库都通过 FMDatabase 拥有自己的连接(出于多线程目的,您应该改用 FMDatabaseQueue)。 现在,将另一个数据库附加到第一个数据库的连接上。然后你可以从数据库 1 连接到数据库 2 中的 table。重要提示:所有这些都是通过每个 sql 语句的 sqlite 发生的,与 FMDB 无关。

我将在 github 提供示例代码: https://github.com/itinance/MultiDatabaseJoin

为简单起见,我将数据库文件放在 /tmp 目录下。 使用 iOS-Simulator 效果很好,我还没有在真正的设备中测试过这段代码,您可以将数据库放在文档文件夹或类似的东西中(但这不是重点).

这里重要的是 sqlite3 中的以下查询:

[db1 executeStatements:@"ATTACH DATABASE '/tmp/tmp2.db' AS second_db"];

在数据库连接 db1 我们从第二个数据库附加数据库文件。

在此附加之后,您可以在如下查询中将数据库连接 1 加入到数据库连接 2 中的 table:

SELECT a.id, a.name AS aname, b.name AS bname FROM a INNER JOIN second_db.b ON b.a_id = a.id

这是我试过的全部代码:

FMDatabase *db1 = [FMDatabase databaseWithPath:@"/tmp/tmp1.db"];
FMDatabase *db2 = [FMDatabase databaseWithPath:@"/tmp/tmp2.db"];

[db1 open];
[db2 open];

[db1 executeStatements:@"CREATE TABLE a (id INTEGER, name TEXT)"];
[db1 executeStatements:@"INSERT INTO a (id, name) VALUES (1, 'foo'), (2, 'bar')"];

[db2 executeStatements:@"CREATE TABLE b (id INTEGER, a_id INTEGER, name TEXT)"];
[db2 executeStatements:@"INSERT INTO b (id, a_id, name) VALUES (1, 1, 'b_foo'), (2, 2, 'b_bar')"];

bool success = [db1 executeStatements:@"ATTACH DATABASE '/tmp/tmp2.db' AS second_db"];
if(!success) {
    NSLog(@"%@", db1.lastErrorMessage);
    return YES;
}

FMResultSet* rs = [db1 executeQuery:@"SELECT a.id, a.name AS aname, b.name AS bname FROM a INNER JOIN second_db.b ON b.a_id = a.id"];
while( [rs next]) {
    NSLog(@"%@, %@", [rs stringForColumn:@"aname"], [rs stringForColumn:@"bname"]);
}
[rs close];