这个函数向我显示错误“准备 - 错误#0:没有这样的表:项目 “。有人可以帮我解决这个错误。
- (void)viewDidLoad
{
[super viewDidLoad];
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &contactDB)== SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:@"Select name FROM items"];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{ NSLog(@"Data not fetched");
if (sqlite3_step(statement) == SQLITE_ROW)
{NSLog(@"Prepare-error #%i: %s", (sqlite3_prepare_v2(contactDB, [querySQL UTF8String], -1, &statement, NULL) == SQLITE_OK), sqlite3_errmsg(contactDB));
NSString *namefeild = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
[list objectAtIndex:namefeild];
}
else{
NSLog(@"Data not fetched");
}
sqlite3_finalize(statement);
}else {NSLog(@"Prepare-error #%i: %s", (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK), sqlite3_errmsg(contactDB));}
sqlite3_close(contactDB);
}
这两个函数是n个不同的视图控制器。
在视图didload中创建数据库。
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *docsDir;
NSArray *dirPath;
dirPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPath objectAtIndex:0];
databasePath = [[NSString alloc]initWithString:[docsDir stringByAppendingPathComponent:@"contactDB"]];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: databasePath] == NO) {
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK) {
char *errMsg;
const char *sql_stmt = "create table if not exists items(name varchar, price integer, description varchar)";
if (sqlite3_exec(contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
NSLog(@"Fail to create table");
}
sqlite3_close(contactDB);
}else{
NSLog(@"Failed to open database");
}
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
并在保存操作中将数据添加到数据库中。
- (IBAction)save:(id)sender {
sqlite3_stmt *statement;
const char *dbpath = [ databasePath UTF8String];
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK) {
NSString *insertSQL = [NSString stringWithFormat:@"insert into items(name, price, description) values (\"%@\",\"%@\",\"%@\")", nametxt.text, pricetxt.text, description.text];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(@"contact added");
nametxt.text= @"";
pricetxt.text = @"";
description.text = @"";
}else{
NSLog(@"Failed to add contact");
}
sqlite3_finalize(statement);
sqlite3_close(contactDB);
}
}
答案 0 :(得分:1)
通常,这意味着您打开的数据库中不存在该表。您应该在模拟器的Documents文件夹(~/Library/Application Support/iPhone Simulator
)中找到该数据库,并在您选择的MacOS SQLite工具中打开它,亲自查看该表是否存在。我怀疑它不会在那里。
此问题的常见原因是databasePath
处的文件不存在(例如,您可能在数据包中包含数据库副本,但不包含Documents文件夹),在这种情况下sqlite3_open
将在databasePath
静静地创建一个新的空白数据库。
假设您不希望它在找不到它时创建空白数据库,您应该:
从模拟器/设备中删除您的应用程序(以便删除所有空白数据库);
检查您的原始开放例程并使用NSFileManager
检查数据库是否存在(如果数据库尚未存在)(可能在继续之前将数据库从包中复制到文档中);
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:databasePath]) {
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"itemsdb" ofType:@"sqlite"];
[fileManager copyItemAtPath:bundlePath toPath:databasePath error:nil];
}
或者如果数据库不存在,您的代码可能会动态创建表,但想法是一样的。在打开文件之前检查文件是否存在。
也许在将来,请考虑将sqlite3_open_v2
与SQLITE_OPEN_READWRITE
选项一起使用(但不 SQLITE_OPEN_CREATE
选项),这不会创建数据库,如果找不到数据库,将报告错误。
说过上面的内容(当有人遇到像你这样的错误时,你应该知道“你应该知道的那些表”应该在那里时,这是一般的建议吗),你的代码示例中有一些特定的问题你处理错误报告:
如果步骤成功,则表示您报告错误。当然,如果步骤失败,你只会这样做。
由于步骤而产生的错误显示“准备错误”。当然应该是“步骤错误”。
您的错误记录正在调用再次失败的函数以获取返回码。您应该在第一次调用该函数时保存返回代码,从而使您不必再次调用它来获取错误消息。 (这很重要,因为有时函数返回的值会改变并重置错误信息。不要再次调用失败的函数!)保存原始返回码也更有效。
因此:
if (sqlite3_open(dbpath, &contactDB)== SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:@"Select name FROM items"];
const char *query_stmt = [querySQL UTF8String];
int rc; // variable to hold the return code
if ((rc = sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL)) == SQLITE_OK)
{
if ((rc = sqlite3_step(statement)) == SQLITE_ROW)
{
NSString *namefeild = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
[list objectAtIndex:namefeild];
}
else {
if (rc == SQLITE_DONE)
NSLog(@"step found no data");
else
NSLog(@"step-error #%i: %s", rc, sqlite3_errmsg(contactDB));
}
sqlite3_finalize(statement);
} else {
NSLog(@"Prepare-error #%i: %s", rc, sqlite3_errmsg(contactDB));
}
sqlite3_close(contactDB);
}
答案 1 :(得分:1)
- (void)viewDidLoad
{
[super viewDidLoad];
const char *dbpath = [databasePath UTF8String];
NSLog("%@", databasePath);
...
...
}
将数据库路径复制到剪贴板并将其粘贴到控制台中。
在.dump命令之后,您是否看到了表的创建语句?如果没有,那么您需要仔细检查实际创建数据库的位置。如果您使用.dump命令的内容更新答案,那将非常有用。