xcode打开sqlite3数据库的遇到的问题以及数据库操作方法
2012-03-19 01:20
465 查看
当调用 sqlite3_prepare_v2() 函数的时候,是一个将SQL语句编译为sqlite内部一个结构体(sqlite3_stmt).该结构体中包含了将要执行的的SQL语句的信息.
通常情况下,应该是返回0。还有一些时候是返回其他数值。我以1为例,简单介绍一下错误解决的思路和方法:
我们尝试用以下代码来进行测试:
// Get the path to the documents directory and append the databaseName
NSString*documentPaths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath= [documentsDirstringByAppendingPathComponent:databaseName];
NSFileManager*fileManager = [NSFileManagerdefaultManager];
BOOL success = [fileManagerfileExistsAtPath:databasePath];
上面的这个path,我们可以看到,我们需要连接的数据库的那个路径。有时候,如果你的工程创建好了以后,在运行时会把database复制到这个路径下面。如果中途数据库发生了变化,随之有可能没有拷贝过去,那么这个路径下的数据库文件会和你工程里面的不一致。也许这个path下面的是一个大小为0字节的空数据库。所以通常即便是发现了数据库的存在,但是也不能保证你数据库的结构体是正确的。因此必须确保该数据库是所需要添加的数据库。操作方法如下:
NSString*defaultDBPath =[[[NSBundlemainBundle]resourcePath]stringByAppendingPathComponent:@"databaseName"];
success = [fileManagercopyItemAtPath:defaultDBPathtoPath:databasePath error:&error];
if(!success)
NSAssert1(0,@"数据库附加失败!'%@'.",
[errorlocalizedDescrip
4000
tion]);
else
NSLog(@"数据库附加成功");
简要说明一下SQLite数据库执行SQL语句的过程
** 调用sqlite3_prepare()将SQL语句编译为sqlite内部一个结构体(sqlite3_stmt).该结构体中包含了将要执行的的SQL语句的信息.
** 如果需要传入参数,在SQL语句中用'?'作为占位符,再调用sqlite3_bind_XXX()函数将对应的参数传入.
** 调用sqlite3_step(),这时候SQL语句才真正执行.注意该函数的返回值,SQLITE_DONE和SQLITE_ROW都是表示执行成功, 不同的是SQLITE_DONE表示没有查询结果,象UPDATE,INSERT这些SQL语句都是返回SQLITE_DONE,SELECT查询语句在 查询结果不为空的时候返回SQLITE_ROW,在查询结果为空的时候返回SQLITE_DONE.
** 每次调用sqlite3_step()的时候,只返回一行数据,使用sqlite3_column_XXX()函数来取出这些数据.要取出全部的数据需要 反复调用sqlite3_step(). (注意, 在bind参数的时候,参数列表的index从1开始,而取出数据的时候,列的index是从0开始).
** 在SQL语句使用完了之后要调用sqlite3_finalize()来释放stmt占用的内存.该内存是在sqlite3_prepare()时分配的.
** 如果SQL语句要重复使用,可以调用sqlite3_reset()来清楚已经绑定的参数.
下面是我的打算的函数调用方式。引用的SqliteHelper之后,里面的方法可以直接调用。
[SqliteHelperopen];
catArray= [[NSMutableArrayalloc]init];
[SqliteHelperGetAllCat:catArray];
self.DataArray=catArray;
[catArrayrelease];
.h文件中的定义部分。
#import "SqliteHelper.h"
static sqlite3 *database_ = nil;
@implementationSqliteHelper
@synthesize databaseName;
@synthesize databasePath;
+可以理解为Static函数的写法把。
open函数不用太多介绍。上一篇里面有详细的讲解。
+(BOOL) open{
databaseName=@"mydatabase.sqlite";
// Get the path to the documents directory and append the databaseName
NSArray*documentPaths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath= [documentsDirstringByAppendingPathComponent:databaseName];
NSFileManager * fileManager = [NSFileManager defaultManager];
BOOL find = [fileManager fileExistsAtPath:path];
if (find) {
NSLog(@"Database file have already existed.");
if(sqlite3_open([path UTF8String],
&database_) != SQLITE_OK) {
sqlite3_close(database_);
NSLog(@"Error: open database file.");
returnNO;
}
returnYES;
}
else{
sqlite3_close(database_);
NSLog(@"Error: open database file.");
returnNO;
}
returnNO;
}
这个SelectAll的一个方法。 不过目前看来还是不够抽象。因为就目前来看,还是具体问题需要具体分析的, 比如不同的结构,目前还无法查询到一个不同的结果,这是不可以通用的,至少表格的存储数据类型,和顺序的不同,是有很大的差异的。 还是有很大需要完善的地方把。目前也只是提供一个思路给大家参考。功能实现的同时,不要把这门OO的语言抛在脑后,时常想起面向对象。。面向对象。。。
+(void)GetAllCat:(NSMutableArray*)catRet withSQL:(char *)sql
{
//[self checkAndCreateDatabase:databasePath withname:databaseName];
sqlite3_stmt *statement = nil;
if(sqlite3_open([databasePathUTF8String],
&database_) ==SQLITE_OK)
{
//sql ="SELECT * FROM SubCat";
int test = sqlite3_prepare_v2(database_,
sql, -1, &statement, NULL);
if (sqlite3_prepare_v2(database_, sql,
-1, &statement, NULL) != SQLITE_OK)
{
NSLog(@"Error: failed to prepare statement with message:get channels.");
}
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSString*aName = [NSStringstringWithUTF8String:(char*)sqlite3_column_text(statement,1)];
NSString*catID = [NSStringstringWithUTF8String:(char*)sqlite3_column_text(statement,0)];
int catid2 = [catID intValue];
int catid = sqlite3_column_int(statement, 0);
cat* cattable = [[catalloc] init];
cattable.catId = catid;
if(aName)
{
cattable.catname = aName;
}
[catRet addObject:cattable];
[cattable release];
}
}
sqlite3_finalize(statement);
}
通常情况下,应该是返回0。还有一些时候是返回其他数值。我以1为例,简单介绍一下错误解决的思路和方法:
我们尝试用以下代码来进行测试:
// Get the path to the documents directory and append the databaseName
NSString*documentPaths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath= [documentsDirstringByAppendingPathComponent:databaseName];
NSFileManager*fileManager = [NSFileManagerdefaultManager];
BOOL success = [fileManagerfileExistsAtPath:databasePath];
上面的这个path,我们可以看到,我们需要连接的数据库的那个路径。有时候,如果你的工程创建好了以后,在运行时会把database复制到这个路径下面。如果中途数据库发生了变化,随之有可能没有拷贝过去,那么这个路径下的数据库文件会和你工程里面的不一致。也许这个path下面的是一个大小为0字节的空数据库。所以通常即便是发现了数据库的存在,但是也不能保证你数据库的结构体是正确的。因此必须确保该数据库是所需要添加的数据库。操作方法如下:
NSString*defaultDBPath =[[[NSBundlemainBundle]resourcePath]stringByAppendingPathComponent:@"databaseName"];
success = [fileManagercopyItemAtPath:defaultDBPathtoPath:databasePath error:&error];
if(!success)
NSAssert1(0,@"数据库附加失败!'%@'.",
[errorlocalizedDescrip
4000
tion]);
else
NSLog(@"数据库附加成功");
简要说明一下SQLite数据库执行SQL语句的过程
** 调用sqlite3_prepare()将SQL语句编译为sqlite内部一个结构体(sqlite3_stmt).该结构体中包含了将要执行的的SQL语句的信息.
** 如果需要传入参数,在SQL语句中用'?'作为占位符,再调用sqlite3_bind_XXX()函数将对应的参数传入.
** 调用sqlite3_step(),这时候SQL语句才真正执行.注意该函数的返回值,SQLITE_DONE和SQLITE_ROW都是表示执行成功, 不同的是SQLITE_DONE表示没有查询结果,象UPDATE,INSERT这些SQL语句都是返回SQLITE_DONE,SELECT查询语句在 查询结果不为空的时候返回SQLITE_ROW,在查询结果为空的时候返回SQLITE_DONE.
** 每次调用sqlite3_step()的时候,只返回一行数据,使用sqlite3_column_XXX()函数来取出这些数据.要取出全部的数据需要 反复调用sqlite3_step(). (注意, 在bind参数的时候,参数列表的index从1开始,而取出数据的时候,列的index是从0开始).
** 在SQL语句使用完了之后要调用sqlite3_finalize()来释放stmt占用的内存.该内存是在sqlite3_prepare()时分配的.
** 如果SQL语句要重复使用,可以调用sqlite3_reset()来清楚已经绑定的参数.
下面是我的打算的函数调用方式。引用的SqliteHelper之后,里面的方法可以直接调用。
[SqliteHelperopen];
catArray= [[NSMutableArrayalloc]init];
[SqliteHelperGetAllCat:catArray];
self.DataArray=catArray;
[catArrayrelease];
.h文件中的定义部分。
#import "SqliteHelper.h"
static sqlite3 *database_ = nil;
@implementationSqliteHelper
@synthesize databaseName;
@synthesize databasePath;
+可以理解为Static函数的写法把。
open函数不用太多介绍。上一篇里面有详细的讲解。
+(BOOL) open{
databaseName=@"mydatabase.sqlite";
// Get the path to the documents directory and append the databaseName
NSArray*documentPaths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath= [documentsDirstringByAppendingPathComponent:databaseName];
NSFileManager * fileManager = [NSFileManager defaultManager];
BOOL find = [fileManager fileExistsAtPath:path];
if (find) {
NSLog(@"Database file have already existed.");
if(sqlite3_open([path UTF8String],
&database_) != SQLITE_OK) {
sqlite3_close(database_);
NSLog(@"Error: open database file.");
returnNO;
}
returnYES;
}
else{
sqlite3_close(database_);
NSLog(@"Error: open database file.");
returnNO;
}
returnNO;
}
这个SelectAll的一个方法。 不过目前看来还是不够抽象。因为就目前来看,还是具体问题需要具体分析的, 比如不同的结构,目前还无法查询到一个不同的结果,这是不可以通用的,至少表格的存储数据类型,和顺序的不同,是有很大的差异的。 还是有很大需要完善的地方把。目前也只是提供一个思路给大家参考。功能实现的同时,不要把这门OO的语言抛在脑后,时常想起面向对象。。面向对象。。。
+(void)GetAllCat:(NSMutableArray*)catRet withSQL:(char *)sql
{
//[self checkAndCreateDatabase:databasePath withname:databaseName];
sqlite3_stmt *statement = nil;
if(sqlite3_open([databasePathUTF8String],
&database_) ==SQLITE_OK)
{
//sql ="SELECT * FROM SubCat";
int test = sqlite3_prepare_v2(database_,
sql, -1, &statement, NULL);
if (sqlite3_prepare_v2(database_, sql,
-1, &statement, NULL) != SQLITE_OK)
{
NSLog(@"Error: failed to prepare statement with message:get channels.");
}
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSString*aName = [NSStringstringWithUTF8String:(char*)sqlite3_column_text(statement,1)];
NSString*catID = [NSStringstringWithUTF8String:(char*)sqlite3_column_text(statement,0)];
int catid2 = [catID intValue];
int catid = sqlite3_column_int(statement, 0);
cat* cattable = [[catalloc] init];
cattable.catId = catid;
if(aName)
{
cattable.catname = aName;
}
[catRet addObject:cattable];
[cattable release];
}
}
sqlite3_finalize(statement);
}
相关文章推荐
- Xcode8 打开的xib遇到的问题
- 如何解决打开xcode项目是遇到的“cannot be opened because the project file cannot be parsed.”问题?
- Xcode 8最近朋友的项目遇到了关于上架的问题以及xcode8所需要的环境的配置以及ios 10所支持的功能
- unity 使用 sqlite 数据库遇到的问题 unity android 使用sqlite
- Typecho SQLite与MySQL的数据库切换及解决MySQL连接打开缓慢问题
- SQL SERVER 2008中定时备份数据库任务以及遇到”属性ErrorLogFile 不可用于JobServer“[SERVER]......”的问题时的解决方案
- 最近在做ShareSDK的微信分享的时候遇到了点问题,就是分享的时候选择微信好友或者微信朋友圈会打开一下微信然后界面都还没加载出来就闪退。这个问题我在网上找了好多种的可能的情况以及处理办法,最终找到了
- 我在 Mac 下遇到的那些关于 终端、eclipse、Xcode以及 cocos2d-x 的问题
- VS2012 使用MySql的API函数连接数据库(成功), 以及使用mysql-connector-c++-1.1.3遇到的问题!
- SQlite 数据库遇到的问题 “该字符串未被识别为有效的 DateTime
- 不知还有人遇到这个问题没有:数据库 'xxx' 的版本为 706,无法打开。此服务器支持 661 版及更低版本。不支持降级路径。
- Android通过webservice连接SQLServer 详细教程以及所遇到的问题解答(数据库+服务器+客户端)
- 我在安装TFS 2008的时候遇到的问题以及解决方法一sharepoint 安装 打开站点 出现服务器不可用问题
- [sqlite] 数据库遇到的问题 “该字符串未被识别为有效的 DateTime”
- 对于数据库操作可能会遇到的问题(空值问题以及出现的参数不能被重复使用问题)
- 关于打开现有项目时数据库连接配置遇到的问题 连接字符串中的数据源值指定未安装的SQL Server的实例。要解决此问题,可选择安装匹配的SQL Server实例或修改连接字符串中的数据源值
- sqlite打开路径含中文的数据库文件失败的问题
- 数据库加密之Xcode9.0后,sqlcipher加密:Implicit declaration of function ’sqlite3_key‘is invalid in C99问题
- 创建或打开android模拟器时遇到的问题,以及打开后遇到的Failed to install FragmentTest.apk on device 'emulator-5554': timeout
- ios 操作sqlite3数据库遇到的问题