我有一个"消息表" ,我只希望用他的上一条消息检索"用户ID"
我试图添加" 2 sql语句"在彼此内部,但它不停地循环,
sqlite3_stmt *statement;
NSMutableArray * messages = [[NSMutableArray alloc]init];
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_chatDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:
@"SELECT DISTINCT FROMID , USERNAME from CHATCOMPLETE"];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(_chatDB,
query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
int userID = [[[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)] integerValue];
NSString *querySQL2 = [NSString stringWithFormat:
@"SELECT MESSAGE , USERNAME from CHATCOMPLETE where FROMID=\"%d\"",userID];
const char *query_stmt2 = [querySQL2 UTF8String];
if (sqlite3_prepare_v2(_chatDB,
query_stmt2, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(@"LAST MESSAGE %@",[[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)]);
sqlite3_reset(statement);
}
}
}
sqlite3_reset(statement);
}
}
return messages;
更新 这是插入消息
-(void)saveData:(NSString *)message toID:(int)toID fromID:(int)fromID isRead:(BOOL)read date:(NSDate *)date messageID:(int)messageID userName:(NSString*)userName
{
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_chatDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat: @"INSERT INTO CHATCOMPLETE (MESSAGE, TOID, FROMID, READ, date, MESSAGEID, USERNAME) VALUES (\"%@\", \"%d\", \"%d\", \"%c\", \"%@\", \"%d\", \"%@\")", message, toID, fromID, read, date,messageID,userName];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(_chatDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(@"DONE");
/* status.text = @"Contact added";
name.text = @"";
address.text = @"";
phone.text = @"";*/
} else {
// status.text = @"Failed to add contact";
}
sqlite3_finalize(statement);
sqlite3_close(_chatDB);
}
}
答案 0 :(得分:1)
这是获取给定fromID
的最后一条消息的查询:
SELECT * FROM chatting WHERE fromID=9999 ORDER BY id DESC LIMIT 1
答案 1 :(得分:1)
在SQLite 3.7.11或更高版本中,以下查询将返回每个发件人的日期最长的邮件:
SELECT *, MAX(date)
FROM ChatComplete
GROUP BY FromID
答案 2 :(得分:0)
有一些问题:
您的两个嵌套查询只有一个sqlite3_stmt
变量。您需要为每个单独的sqlite3_stmt
。
您正在呼叫sqlite3_reset
。仅在将新值绑定到预准备语句中的?
占位符时使用,这在此处不适用。更糟糕的是,你在循环中调用它。
与手头的问题无关,但是对于每个准备好的语句,在完成循环结果时不要忘记调用sqlite3_finalize
,以释放准备语句时使用的内存。
因此,您可能需要以下内容:
sqlite3_stmt *userStatement;
sqlite3_stmt *messageStatement;
int rc; // the return code
NSMutableArray * messages = [[NSMutableArray alloc]init];
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_chatDB) == SQLITE_OK)
{
const char *query_stmt = "SELECT DISTINCT FROMID , USERNAME from CHATCOMPLETE";
if (sqlite3_prepare_v2(_chatDB, query_stmt, -1, &userStatement, NULL) != SQLITE_OK)
{
NSLog(@"%s: prepare userStatement failed: %s", __PRETTY_FUNCTION__, sqlite3_errmsg(_chatDB));
}
else
{
while ((rc = sqlite3_step(userStatement)) == SQLITE_ROW)
{
int userID = [[[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)] integerValue];
const char *query_stmt2 = "SELECT MESSAGE , USERNAME from CHATCOMPLETE where FROMID=? ORDER BY timestamp DESC LIMIT 1"; // change the `ORDER BY` to use whatever field you want to sort by
if (sqlite3_prepare_v2(_chatDB, query_stmt2, -1, &messageStatement, NULL) != SQLITE_OK)
{
NSLog(@"%s: prepare messageStatement failed: %s", __PRETTY_FUNCTION__, sqlite3_errmsg(_chatDB));
}
else
{
if (sqlite3_bind_int(messageStatement, 1, userID) != SQLITE_OK)
{
NSLog(@"%s: bind userID %d failed: %s", __PRETTY_FUNCTION__, userID, sqlite3_errmsg(_chatDB));
}
while ((rc = sqlite3_step(messageStatement)) == SQLITE_ROW)
{
NSLog(@"LAST MESSAGE %@",[[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)]);
}
if (rc != SQLITE_DONE)
{
NSLog(@"%s: step messageStatement failed: %s", __PRETTY_FUNCTION__, sqlite3_errmsg(_chatDB));
}
sqlite3_finalize(messageStatement);
}
}
if (rc != SQLITE_DONE)
{
NSLog(@"%s: step userStatement failed: %s", __PRETTY_FUNCTION__, sqlite3_errmsg(_chatDB));
}
sqlite3_finalize(userStatement);
}
}
else
{
NSLog(@"%s: open %@ failed", __PRETTY_FUNCTION__, _databasePath);
}
return messages;
请注意,除了上述三点之外,此代码示例还包括:
如果sqlite3_errmsg
失败,请使用sqlite3_prepare_v2
记录错误。
添加了对sqlite3_step
返回代码的检查,如果失败则再次记录sqlite3_errmsg
。
如果sqlite3_open
失败,则添加日志。
使用sqlite3_bind_int()
而不是使用stringWithFormat
构建SQL。在这种情况下,因为userID
是数字,这不是关键,但如果在WHERE
子句中使用字符串值,使用sqlite3_bind_text()
函数变得至关重要,所以我只是想表现出这种模式。
例如,查看保存例程并尝试保存恰好带有双引号的消息(例如I spoke with Bob and he says "hello" to you.
)。您的stringWithFormat
构造将失败。如果您使用sqlite3_bind_text
,它将解决该问题。
BTW,正如您所看到的,当您添加所有正确的结果验证,绑定值等时,代码变得有点笨拙。您可以考虑使用FMDB,这极大地简化了您的SQLite Objective-C代码。