繁体   English   中英

iPhone上的SQLite3 - 插入返回错误代码8尝试编写只读数据库

[英]SQLite3 on iPhone - insert returns error code 8 attempt to write a readonly database

因此,大约一个星期以来,我一直在头上撞墙。

我正在编写一个包含sqlite数据库的iPhone应用程序。 我能够打开数据库并从中读取(我通过命令行/终端输入一些测试数据),选择特定数据等。但是,我不能做的是从手机插入数据库。 当我执行sqlite3_exec(...)时,它返回错误代码8“尝试编写只读数据库”。

我在这里读过其他问题,说我使用的是Main Bundle的数据库,而不是用户数据库,并且模拟器在运行的设备上经常会出现“让你做”的错误。 嗯,这不是我的情况下发生的事情 - 我在模拟器上运行时遇到此错误。 从我可以告诉我的代码来检查数据库正如许多其他人推荐的那样。

这是我用来验证数据库存在的代码,如果不存在,则将其复制:

// initialize db (if not already)
+(void) checkDatabase {
    // setup some variables
    Boolean success;
    dbName = @"daarma.sqlite";
    NSArray *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDirectory, YES);
    // I have tried this with both NSUserDirectory and NSUserDomainMask, desn't seem to make a difference
    NSString *documentsDir = [documentPath objectAtIndex:0];
    dbPath = [documentsDir stringByAppendingPathComponent:dbName];
    //    dbPath = [[NSBundle mainBundle] pathForResource:@"daarma" ofType:@"sqlite"];

    // check to see if the database already exists
    NSFileManager *fm = [NSFileManager defaultManager];
    success = [fm fileExistsAtPath:dbPath];
    if(success) {
        NSLog(@"Database exists, returning.");
        return;
    }

    // if not, we create it
    NSLog(@"Creating database in user profile...");
    NSString *dbPathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbName];
    [fm copyItemAtPath:dbPathFromApp toPath:dbPath error:nil];    

    [fm release];
    [documentPath release];
    [documentsDir release];
}

当我使用这个插入数据时:

sqlite3 *db;
int open = sqlite3_open_v2([dbPath UTF8String], &db, -1, NULL);
if(open == 0) {
    NSLog(@"open, inserting");
    NSString *sql = [NSString stringWithFormat:@"insert into affiliates values('1','2','3','4','5','6','7','8','9','10','11','12')"];
    int exec = sqlite3_exec(db, [sql UTF8String], NULL, NULL, NULL);
    NSLog(@"exec = %d",exec);
}
sqlite3_close(db);

exec返回上面提到的错误代码8:“”尝试编写只读数据库。“

我还尝试了通常的重启,清理项目,重置模拟器数据。 我什至进入了Simulator目录,并手动删除了所有应用程序数据。 当我尝试返回时,它识别出数据库不在那里并复制了它,但是我仍然遇到该错误。

编辑:

我刚才注意到,如果我在checkDatabase方法中这样做:

NSError *error;
[fm copyItemAtPath:dbPathFromApp toPath:dbPath error:&error]; 
NSLog(@"error = %@",error);

它导致模拟器在第一次运行时崩溃(在执行内容重置之后),但每次之后它恢复上述错误而没有崩溃。 所以也许我的checkDatabase方法做错了。 ?? :(它从不告诉我错误消息的输出。

尝试将打开功能更改为此

sqlite3_open_v2([dbPath UTF8String], &db, SQLITE_OPEN_READWRITE , NULL);

或者基本上使用琐碎的开放功能

Sqlite3_open([dbPath UTF8String],&db);// this should do the job

希望有帮助:)

我尝试了您的代码,但以下行中的open = 21(SQLITE_MISUSE)导致失败:

int open = sqlite3_open_v2([dbPath UTF8String], &db, -1, NULL);

因为您将-1传递给flags参数。 它应该是SQLITE_OPEN_READWRITE。

我还有一些意见。

[fm release];
[documentPath release];
[documentsDir release];

这些版本不是必需的,因为您无需分配/初始化,保留或复制它们。

NSString *sql = [NSString stringWithFormat:@"insert into affiliates values('1','2','3','4','5','6','7','8','9','10','11','12')"];
int exec = sqlite3_exec(db, [sql UTF8String], NULL, NULL, NULL);

你应该使用sqlite3_prepare_v2并绑定参数而不是stringWithFormat:for SQL。

if(open == 0) { ... }

尽可能使用符号常量(SQLITE_OK)代替幻数(0)。

NSError *error;
[fm copyItemAtPath:dbPathFromApp toPath:dbPath error:&error]; 
NSLog(@"error = %@",error);

您应该在调用copyItemAtPath之前初始化error = nil:因为复制操作成功时不会更改错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM