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

发布于 2024-12-19 18:32:57 字数 2378 浏览 1 评论 0原文

所以,我已经在这件事上苦苦挣扎了大约一周了。

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

我在这里读过其他问题,说我使用的是主捆绑包的数据库而不是用户数据库,并且模拟器通常会“让你这样做”,而在实时设备上你会收到错误。好吧,这不是我的情况 - 我在模拟器上运行时收到此错误。据我所知,我的代码检查数据库与许多其他人建议的完全一样。

这是我用来验证数据库是否存在的代码,如果不存在,我会复制它:

// 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:“”尝试写入只读数据库。 “

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

编辑:

我刚刚注意到,如果我在 checkDatabase 方法中执行此操作:

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

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

So, I have been beating my head against the wall on this for about a week now.

I'm writing an iPhone app that has an sqlite database in it. I'm able to open the database and read from it (I put some test data in there through via the command line / terminal), select specific data, etc. But, what I cannot do is insert into the database from the phone. When I execute sqlite3_exec(...) it returns error code 8 "attempt to write a readonly database."

I had read other questions on here saying that I was using the Main Bundle's database and not the users database, and that the simulator will often times just "let you do it" while on a live device you'll get an error. Well, that's not what's happening in my case - I'm getting this error while running on the simulator. And from what I can tell my code to check the database is exactly as a lot of others recommend it to be.

Here is the code I use to verify the database exists, and if it doesn't I copy it:

// 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];
}

When I go to insert data using this:

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 returns with the above mentioned error code 8: ""attempt to write a readonly database."

I've also tried the usual restarts, cleaning the project, resetting the simulator data. I even went in to my Simulator directory and deleted all the application data out manually. When I tried to go back in, it recognized the database wasn't there and copied it over, but I still get that error.

EDIT:

I've just noticed that if I do this in the checkDatabase method:

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

it causes the simulator to crash the first go around (after doing a content reset), but each time after that it resumes the above error with no crashes. So maybe I am doing something wrong with my checkDatabase method. ?? :( It never tells me the output of the error message.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青朷 2024-12-26 18:32:57

尝试将 open 函数更改为此

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

或基本上使用简单的 open 函数

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

希望有帮助:)

try to change the open function to this

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

or basically use the trivial open function

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

hope that helps :)

并安 2024-12-26 18:32:57

我尝试了您的代码,但在以下行中失败, 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);

对于 SQL,您应该使用 sqlite3_prepare_v2 并绑定参数而不是 stringWithFormat: 。

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

只要有可能,您应该使用符号常量 (SQLITE_OK) 而不是幻数 (0)。

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

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

I tried your code, and it failed with open = 21 (SQLITE_MISUSE) in the following line:

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

Because you pass -1 to flags parameter. It should be SQLITE_OPEN_READWRITE.

I have some more comments.

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

These release's are not necessary, because you don't alloc/init, retain, or copy them.

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);

You should use sqlite3_prepare_v2 and bind parameters instead of stringWithFormat: for SQL.

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

Whenever possible, you should use symbolic constant (SQLITE_OK) instead of magic number (0).

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

You should initialize error = nil before calling copyItemAtPath: because error is not changed when the copy operation succeeds.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文