我的情况是这样的。 出于安全原因,我决定将应用数据放入捆绑包,将用户数据放入文档目录。 问题是如何从不同的数据库加入表? 如果不可能,我是否必须在文档目录中创建一个数据库表?
答案 0 :(得分:6)
Sqlite3允许它将外部数据库附加到当前连接。 想象一下,您有两个数据库,每个数据库通过FMDatabase保存自己的连接(出于多线程目的,您应该使用FMDatabaseQueue)。 现在,将另一个数据库附加到第一个数据库的连接。然后,您可以从数据库1加入数据库2中的表。重要说明:所有这些都是通过sqlite per sql语句进行的,与FMDB无关。
我将在github上提供示例代码: https://github.com/itinance/MultiDatabaseJoin
为简单起见,我将数据库文件放在/ tmp-directory下。 使用iOS-Simulator这很好用,我还没有在真正的设备中测试过这段代码,你可以将数据库放在文件夹或类似的东西中(但这还不是重点)。
这里重要的是sqlite3中的以下查询:
[db1 executeStatements:@"ATTACH DATABASE '/tmp/tmp2.db' AS second_db"];
在数据库连接db 1 ,我们从第二个数据库附加数据库文件。
在此附加之后,您可以在类似这样的查询中将Database-Connection 1加入数据库连接2中的表:
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];