通过Objective-C创build一个SQLite3数据库文件

我试图在运行时通过Objective-C创build一个SQLite3数据库文件。 我正在尝试创build一个名为“tblStore”的表。 我希望字段名称被称为“strStoreNumber”和“strStoreReg”。 我是iOS和SQLite的新手,所以我很难find执行此操作的语法。 除了创build表格之外,我还希望创build的表格不驻留在应用程序包中,而是存放在手机的某处。 该表需要是可读/可写的。 我已经做了一些阅读“用户沙箱”和“文件目录”。 我不确定我是否了解两者之间的差异。 理想情况下,我的应用程序将使用一个button来从文本字段input。 在将来自文本字段的input放入string之后,将检查是否存在我的“tblStore”SQLite表,如果不存在,将创build表。

回顾一下:1.什么是Obj-C / SQLite创build一个名为“tblStore”的字段为“strStoreNumber”和“strStoreReg”的语法? 2.数据库文件应该放在哪里? 我需要读取和写入tblStore db文件。 3.“用户沙盒”和“文档目录”有什么不同?

这是我目前的:

-(IBAction)setInput:(id)sender { NSString *strStoreNumber; NSString *strRegNumber; NSString *tableName = @"tblStore"; NSString *dbStrStore = @"strStore"; NSString *dbStrReg = @"strReg"; strStoreNumber = StoreNumber.text; strRegNumber = RegNumber.text; NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString* documentsDirectory = [paths lastObject]; NSString* databasePath = [documentsDirectory stringByAppendingPathComponent:@"tblStore.sqlite"]; // NSString* databasePath = [[NSBundle mainBundle] pathForResource:@"tblStore" ofType:@"sqlite"]; if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) { NSLog(@"Opened sqlite database at %@", databasePath); char *err; NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS '%@' ('%@' TEXT PRIMARY KEY, '%@' TEXT);", tableName, dbStrStore, dbStrReg]; if (sqlite3_exec(database, [sql UTF8String], NULL, NULL, &err) != SQLITE_OK) { sqlite3_close(database); NSAssert(0, @"Table failed to create."); } //...stuff } else { NSLog(@"Failed to open database at %@ with error %s", databasePath, sqlite3_errmsg(database)); sqlite3_close (database); } NSString *querystring; // create your statement querystring = [NSString stringWithFormat:@"SELECT strStore, strReg FROM tblStore WHERE strStore = %@ AND strReg = %@;", strStoreNumber, strRegNumber]; const char *sql = [querystring UTF8String]; NSString *szStore = nil; NSString *szReg = nil; sqlite3_stmt *statement = nil; if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL)!=SQLITE_OK) //queryString = Statement { NSLog(@"sql problem occured with: %s", sql); NSLog(@"%s", sqlite3_errmsg(database)); } else { // you could handle multiple rows here while (sqlite3_step(statement) == SQLITE_ROW) { szStore = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 0)]; szReg = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 1)]; } } sqlite3_finalize(statement); lblStoreNumber.text = szStore; lblRegNumber.text = szReg; } 

当我运行我的应用程序时,出现以下错误:

 2012-05-10 14:58:38.169 CCoDBTry[355:f803] Opened sqlite database at /Users/Matt****/Library/Application Support/iPhone Simulator/5.1/Applications/5DB7A218-A0F6- 485F-B366-91FD2F9BC062/Documents/tblStore.sqlite 2012-05-10 14:58:38.307 CCoDBTry[355:f803] sql problem occured with: SELECT strStore, strReg FROM tblStore WHERE strStore = 8053 AND strReg = 4; 2012-05-10 14:58:38.308 CCoDBTry[355:f803] no such column: strStore 

我很欣赏那些抽出时间来解释一些这些东西的人,因为我很新,而且在完成我尝试过的一些事情方面是不成功的。 非常感谢你的帮助!

sqlite是一个痛苦,如果你不知道你在做什么。 我也有一些问题与SQLite C函数,但后来我决定使用SQLite包装。

FMDB和BWDB是好的,易于使用的目标c sqlite包装。 我build议你使用其中的一个。

请注意,BWDB是在lynda.com教程( 这一个 ),如果你没有在网上find它…留下一个评论,我会上传的地方。

编辑:唯一的地方,你可以写在你的应用程序的东西是在你的文件目录…所以..这个简单的术语…如果数据库不在你的文件目录..只读…也你读/写你的分贝..操作系统复制数据库的文件目录..并做所有的读和写在那里,所以你可以在你的应用程序包中有一个数据库,但你不能编辑一个…所以你最终会得到2分贝。我自己也有同样的问题..我通过合并2分贝,当我更新应用程序

编辑2:我上传BWDB最终项目(你有你的包装和项目,看看它是如何工作的)

//创build数据库

 -(NSString *) filePath { NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentDirectory=[paths objectAtIndex:0]; return [documentDirectory stringByAppendingPathComponent:@"LoginDatabase.sql"]; } 

//打开数据库

 -(void)openDB { if(sqlite3_open([[self filePath]UTF8String], &db) !=SQLITE_OK) { sqlite3_close(db); NSAssert(0, @"Database failed to Open"); } } 

//创build表格

 -(void) createTableNamed:(NSString*)tableName withField1:(NSString*) field1 withField2:(NSString*) field2 { char *err; NSString *sql=[NSString stringWithFormat:@" CREATE TABLE IF NOT EXISTS '%@'('%@' TEXT PRIMARY KEY,'%@' TEXT);",tableName,field1,field2]; if(sqlite3_exec(db, [sql UTF8String], NULL, NULL, &err) !=SQLITE_OK) { sqlite3_close(db); NSAssert(0, @"Table failed to create"); } } 

//插入logging

 -(void)insertrecordIntoTable:(NSString*) tableName withField1:(NSString*) field1 field1Value:(NSString*)field1Vaue andField2:(NSString*)field2 field2Value:(NSString*)field2Value { NSString *sqlStr=[NSString stringWithFormat:@"INSERT INTO '%@'('%@','%@')VALUES(?,?)",tableName,field1,field2]; const char *sql=[sqlStr UTF8String]; sqlite3_stmt *statement1; if(sqlite3_prepare_v2(db, sql, -1, &statement1, nil)==SQLITE_OK) { sqlite3_bind_text(statement1, 1, [field1Vaue UTF8String], -1, nil); sqlite3_bind_text(statement1, 2, [field2Value UTF8String], -1, nil); } if(sqlite3_step(statement1) !=SQLITE_DONE) NSAssert(0, @"Error upadating table"); sqlite3_finalize(statement1); } 

//从表中检索数据

 -(void)getAllRowsFromTableNamed:(NSString *)tableName { NSString *field1Str,*field2Str; NSString *qsql=[NSString stringWithFormat:@"SELECT * FROM %@",tableName]; sqlite3_stmt *statement; if(sqlite3_prepare_v2(db, [qsql UTF8String], -1, &statement, nil)==SQLITE_OK) { while(sqlite3_step(statement) ==SQLITE_ROW) { char *field1=(char *) sqlite3_column_text(statement, 0); char *field2=(char *) sqlite3_column_text(statement, 1); field1Str=[[NSString alloc]initWithUTF8String:field1]; field2Str=[[NSString alloc] initWithUTF8String:field2]; NSString *str=[NSString stringWithFormat:@"%@ - %@",field1Str,field2Str]; NSLog(@"%@",str); } } 

}

在viewDidLoad中调用方法

 - (void)viewDidLoad { [self openDB]; [self createTableNamed:@"Login" withField1:@"USERNAME" withField2:@"PASSWORD"]; [self insertrecordIntoTable:@"Login" withField1:@"USERNAME" field1Value:username andField2:@"PASSWORD" field2Value:password]; } 

其中用户名和密码是NSString值;

您可以使用以下代码来获取在“文档”文件夹中创build的数据库。 只需在文档文件夹中传递一个path,如果需要的话,该函数将在指定path的Documents文件夹中复制sqlite数据库。 然后可以使用此path来创build和查询数据库表。

 + (NSString*) createDatabaseIfRequiredAtPath:(NSString*)databasePath { if (databasePath == nil) return nil; NSString *path = [NSString stringWithFormat:@"%@/%@", databasePath, kMainDBName]; NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error = nil; if ([fileManager fileExistsAtPath:path] == NO) { // The writable database does not exist, so copy the default to the appropriate location. NSString *defaultDBPath = [[NSBundle mainBundle] pathForResource:kMainDBName ofType:nil]; BOOL success = [fileManager copyItemAtPath:defaultDBPath toPath:path error:&error]; if (!success) { NSCAssert1(0, @"Failed to create writable database file with message '%@'.", [ error localizedDescription]); return nil; } } return path; 

是否有一个特定的原因,你想直接使用SQLLite,而不是使用CoreData? CoreData使用SQLLite数据库,但它本身是一个更高级别的API,尤其是在表视图等情况下,您将获得许多在Xcode中为其设置的function和模板方法。 定义数据模型是微不足道的,你会得到大量的样板代码,并且都是优化的。

http://www.raywenderlich.com/934/core-data-on-ios-5-tutorial-getting-started

CoreData有时被描述为具有陡峭的学习曲线。 我不同意。 如果您正在考虑在您的应用程序中自己编写SQL,那么CoreData不会有任何问题。

术语“沙箱”是设备文件系统的一部分的抽象术语,应用程序具有读/写权限。 “Documents”目录是应用程序沙箱中的特定目录。 在沙箱中还有其他文件,而不仅仅是文档目录,但是大部分将数据保存到iOS文件系统的应用程序都是在文档目录中进行的。

你可以打开terminal,然后cd到/ Users / Matt * / Library / Application Support / iPhone Simulator / 5.1 / Applications / 5DB7A218-A0F6-485F-B366-91FD2F9BC062 / Documents /

然后sqlite3 tblStore.sqlite

然后使用.schema tblStore应该显示你的表模式,你可以看到它是否正确构build。

您的数据库需要在文档目录中进行写入访问。 如果你的数据库只是被读取,那么永远不会写入到你的应用程序包中。 完成此操作的一种方法是创builddatabase.sqlite文件并将其添加到捆绑软件,并在启动时将其复制到文档目录(如果尚不存在)。

也许你忘记了表格插入。 创build数据库和表,但其空表。 您试图从表中读取空的logging。