- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在编写一个直接访问 SQLite
的 iOS 应用程序。我在 Android 上做过很多次这种事情,所以我很难找出我的错误所在 - 但是我的插入返回了 SQLITE_MISUSE
错误(代码 21) ,消息“内存不足”。以下是我为完成此插页所采取的步骤。
首先,表创建:
NSString *sql = @"CREATE TABLE IF NOT EXISTS UsersTable (lastName TEXT,id TEXT PRIMARY KEY NOT NULL,picture BLOB,firstName TEXT,age TEXT,email TEXT,sex TEXT,height TEXT,weight TEXT)";
//create the database if it does not yet exist
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: path ] == NO)
{
const char *dbpath = [path UTF8String];
//This was if (sqlite3_open(dbpath, &store) == SQLITE_OK) , but it has not made a difference.
if (sqlite3_open_v2(dbpath, &store, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) == SQLITE_OK)
{
char *errMsg = NULL;
const char *sql_stmt = [sql UTF8String];
if (sqlite3_exec(store, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
NSLog(@"Failed to create table: %s", errMsg);
}
if (errMsg)
sqlite3_free(errMsg);
}
else
{
NSLog(@"Failed to open/create database");
}
}
接下来,插入(当前使用电子邮件地址作为用户 ID):
INSERT INTO UsersTable (id,lastName,firstName,email) VALUES ("jsmith@foobar.com","Smith","John","jsmith@foobar.com")
我为所有数据库交互使用一个选择器,所以上面的文本在这里传递:
-(int)execSQL:(NSString *)statement
{
NSLog(@"%@",statement);
const char *insert_stmt = [statement UTF8String];
sqlite3_stmt *stmnt;
sqlite3_prepare_v2(store, insert_stmt, -1, &stmnt, NULL);
int result = sqlite3_step(stmnt);
sqlite3_finalize(stmnt);
if (result != SQLITE_OK)
{
NSLog(@"Error: %s", sqlite3_errmsg(store));//This prints "Error: out of memory"
}
return result;
}
我做错了什么?
最佳答案
如果数据库不存在,您的 open 例程只会创建/打开数据库。您的数据库可能已经存在,因此您的例程甚至没有打开它。
最重要的是,如果您尝试在不打开数据库的情况下调用 SQLite 函数,您将得到 SQLITE_MISUSE
返回代码(表明 SQLite 函数未按正确顺序调用)和 sqlite3_errmsg
将返回神秘的“内存不足”错误。
其他一些不相关的观察结果:
你真的应该检查 sqlite3_prepare
的返回码:
- (int)execSQL:(NSString *)statement
{
int result;
NSLog(@"%@",statement);
const char *insert_stmt = [statement UTF8String];
sqlite3_stmt *stmnt;
if ((result = sqlite3_prepare_v2(store, insert_stmt, -1, &stmnt, NULL)) != SQLITE_OK)
{
NSLog(@"%s: prepare failure '%s' (%d)", __FUNCTION__, sqlite3_errmsg(store), result);
return result;
}
if ((result = sqlite3_step(stmnt)) != SQLITE_DONE)
{
NSLog(@"%s: step failure: '%s' (%d)", __FUNCTION__, sqlite3_errmsg(store), result);
}
sqlite3_finalize(stmnt);
return result;
}
根据我的经验,许多常见的开发问题都与 SQL 本身有关,可以通过检查 sqlite3_prepare_v2
语句的返回码来识别。
您真的不应该在 NSString
中构建 SQL 语句。你向 SQL 注入(inject)攻击敞开大门,或者考虑到更良性的情况,如果某人的名字中有引号,则只是一个 SQL 错误,例如“毁灭者”
。您应该使用 ?
占位符,然后使用 sqlite3_bind_xxx
绑定(bind)值的函数。像这样的东西:
- (int)insertIdentifier:(NSString *)identifier
lastName:(NSString *)lastName
firstName:(NSString *)firstName
email:(NSString *)email
{
int result;
const char *insert_stmt = "INSERT INTO UsersTable (id, lastName, firstName, email) VALUES (?, ?, ?, ?);";
sqlite3_stmt *stmnt;
if ((result = sqlite3_prepare_v2(store, insert_stmt, -1, &stmnt, NULL)) != SQLITE_OK)
{
NSLog(@"%s: prepare failure '%s' (%d)", __FUNCTION__, sqlite3_errmsg(store), result);
return result;
}
if ((result = sqlite3_bind_text(stmnt, 1, [identifier UTF8String], -1, NULL)) != SQLITE_OK)
{
NSLog(@"%s: bind #1 failure '%s' (%d)", __FUNCTION__, sqlite3_errmsg(store), result);
sqlite3_finalize(stmnt);
return result;
}
if ((result = sqlite3_bind_text(stmnt, 2, [lastName UTF8String], -1, NULL)) != SQLITE_OK)
{
NSLog(@"%s: bind #2 failure '%s' (%d)", __FUNCTION__, sqlite3_errmsg(store), result);
sqlite3_finalize(stmnt);
return result;
}
if ((result = sqlite3_bind_text(stmnt, 3, [firstName UTF8String], -1, NULL)) != SQLITE_OK)
{
NSLog(@"%s: bind #3 failure '%s' (%d)", __FUNCTION__, sqlite3_errmsg(store), result);
sqlite3_finalize(stmnt);
return result;
}
if ((result = sqlite3_bind_text(stmnt, 4, [email UTF8String], -1, NULL)) != SQLITE_OK)
{
NSLog(@"%s: bind #4 failure '%s' (%d)", __FUNCTION__, sqlite3_errmsg(store), result);
sqlite3_finalize(stmnt);
return result;
}
if ((result = sqlite3_step(stmnt)) != SQLITE_DONE)
{
NSLog(@"%s: step failure: '%s'", __FUNCTION__, sqlite3_errmsg(store));
}
sqlite3_finalize(stmnt);
return result;
}
然后你可以这样调用它:
[self insertIdentifier:@"jsmith@foobar.com"
lastName:@"Smith"
firstName:@"John"
email:@"jsmith@foobar.com"];
如您所见,当您开始编写代码并适当检查每个返回值、绑定(bind)每个变量等时,您的 SQLite 代码会很快变得毛茸茸。我建议您考虑查看 FMDB .它是 SQLite 函数的一个漂亮、精简的包装器,极大地简化了在 Objective-C 中编写 SQLite 代码的练习。
关于ios - 为什么我得到 SQLITE_MISUSE : Out of Memory error?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15283117/
我在以下代码中收到 SQLITE_MISUSE 错误,我想知道这是否可能是由于将表名作为绑定(bind)参数引起的? SQLITE_MISUE 有哪些不同的原因? const char sqlNeur
我是第一次使用SQLite3,想不通出现如下错误。以下是相关行: //open db; I checked, and sqlite3_open() returns 0 here (SQLITE_OK)
我尝试将一组对象插入到我的数据库中,除了最后一个之外,所有对象都成功插入,它给了我这个错误 这是我用来插入数据库的代码 - (int)insertWithQuery:(NSString *)que
我在 Java 应用程序中使用 SQlite。如果我运行我的程序,它会在某个时候出错。 有时这是一个简单的异常,有时则是 JVM 发生 fatal error 。 java.sql.SQLExcept
我正在编写一个直接访问 SQLite 的 iOS 应用程序。我在 Android 上做过很多次这种事情,所以我很难找出我的错误所在 - 但是我的插入返回了 SQLITE_MISUSE 错误(代码 21
当我用这个查询启动代码时,有时我可以看到列出的所有表,有时只看到一个,而且我总是得到这个错误: 查询错误:错误:SQLITE_MISUSE:未知错误 我读到当 SQLITE API 使用不当时会发生
随着 iOS 5 的发布,我们在设置 sqlite 数据库的序列化选项时遇到越来越多的错误(因此其保存用于多线程)。我们在 sqlite3_config 上收到 SQLITE_MISUSE 错误代码。
我是一名优秀的程序员,十分优秀!