本节内容目录: 一、SQLite3 二、Core Data 一、SQlite3 SQLite3是⼀款开源的嵌入式关系型数据库,可移植性好、易使用、内存开销小SQLite3是⽆类型的,意味着你可以保存任何类型的数据到任意表的任意字段中。⽐如下列的创表语句是合法的:create table t_person(name, age);为了保证可读性,建议还是把字段类型加上: create table t_person(name text, age integer); SQLite3常用的5种数据类型:text、integer、float、boolean、blob 在iOS中使用SQLite3,⾸先要添加库文件libsqlite3.dylib和导入主头文件 1.sqlite3的基本操作(增删改查) #import "ViewController.h"#import <sqlite3.h>@interface ViewController (){ sqlite3 *_db;}@end@implementation ViewController-(void)queryAll{ //准备结果集 sqlite3_stmt *pStmt = NULL; /* 第一个参数为sqlite3 *类型,为指向sqlite3_open()类函数打开的数据库连接。 第二个参数为需要编译成字节码的sql语句。如果输入的参数有多条sql语句,只有第一个SQL语句被编译。 第三个参数,若为小于0的值,系统会自动读取第一个参数一直到出现字符结束符。若该参数大于0,则它表明要读入的SQL的最大的程度,建议设置其值为sql语句的字节数加上字符结束符后的值,此时执行的效率会有提升。 第四个参数,返回编译好的sqlite3_stmt指针,若第一个参数不包含SQL语句或传进来的SQL语句有错,则此函数返回时被置为NULL。 第五个参数若不为NULL,则它会指向第一条SQL语句结尾后面的第一个字节。这个参数用于指向剩下的未编译的语句。 */ sqlite3_prepare_v2(_db, "select *from user", -1, &pStmt, NULL); while (sqlite3_step(pStmt) == SQLITE_ROW) { //取出对应列的字段值, int ID = sqlite3_column_int(pStmt, 0); const unsigned char *name = sqlite3_column_text(pStmt, 1); const unsigned char *password = sqlite3_column_text(pStmt, 2); NSLog(@"%d,%s,%s",ID,name,password); }}-(void)execSql:(NSString *)sql{ char *errorMsg = nil; /* 第一个参数为sqlite3 *类型。通过sqlite3_open()函数得到 第二个参数是一个指向一个字符串的指针,该字符串的内容为一条完整的SQL语句(不需要在语句结束后加";"),字符串都是以/0结尾的,这个也不例外。 第三个参数为一个回调函数,当这条语句执行之后,sqlite3会去调用这个函数。其原型为 typedef int (*sqlite_callback)(void *,int,char **colvalue,char **colname); 第四个参数为提供给回调函数的参数。如果不需要传递参数,则可以写为NULL。 第五个参数为错误信息。注意,是指针的指针。通过打印printf("%s\n",errmsg),可以知道错误发生在什么地方。 */ sqlite3_exec(_db, [sql UTF8String], nil, nil, &errorMsg); if (errorMsg) { NSLog(@"执行失败:%s",errorMsg); } else { NSLog(@"执行成功"); }}- (void)viewDidLoad { [super viewDidLoad]; //拼接数据库保存路径 NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *path = [documents lastObject]; NSString *dbName = [path stringByAppendingPathComponent:@"test.db"]; //打开数据库 if (sqlite3_open([dbName UTF8String], &_db) == SQLITE_OK) { //创建表 [self execSql:@"create table user(ID integer,name text,password text)"]; //插入两条新纪录 [self execSql:@"insert into user values(1,'admin','123456')"]; [self execSql:@"insert into user values(2,'guest','123456')"]; //查询记录 [self queryAll]; //更新记录 [self execSql:@"update user set password = password + 10 where name = 'admin'"]; [self queryAll]; //关闭数据库 sqlite3_close(_db); } else { NSLog(@"打开失败"); } }@end 以上案例中通过C语言函数的形式实现了简单地Sqlite基本操作,这并不符合面向对象程序设计的基本思想,接下来案例中,通过自定义对象来创建数据库。 Student.h头文件代码如下:#import <Foundation/Foundation.h>@interface Student : NSObject@property(assign,nonatomic)NSInteger ID;@property(copy,nonatomic)NSString *name;@property(assign,nonatomic)int age;@property(assign,nonatomic)char gender;@property(assign,nonatomic)float chineseScore;@property(assign,nonatomic)float mathScore;@property(assign,nonatomic)float englishScore;@endStudent.m代码如下:#import "Student.h"@implementation Student-(NSString *)description{ return [NSString stringWithFormat:@"%ld,%@,%d,%c,%.2f,%.2f,%.2f",_ID,_name,_age,_gender,_chineseScore,_mathScore,_englishScore];}@end 以上代码,构建了Student模型。 StudentDAO.h头文件代码如下: #import <Foundation/Foundation.h>#import <sqlite3.h>@class Student;@interface StudentDAO : NSObject{ sqlite3 *_db;}+(StudentDAO *)shardManger;//初始化:创建表,添加数据;-(void)initDataBase;//添加学生记录-(BOOL)addStudent:(Student *)student;//删除学生记录-(BOOL)deleteStudentByName:(NSString *)name;//更新学生记录-(BOOL)updateStudent:(Student *)student;//查询学生记录-(NSArray *)queryStudentAll;-(Student*)queryStudentByName:(NSString *)name;@end StudentDAO.m代码如下: #import "StudentDAO.h"#import "Student.h"#import <sqlite3.h>static StudentDAO *instace = nil;@implementation StudentDAO//创建单例对象,确保数据库只被初始化一次,+(StudentDAO *)shardManger{ static dispatch_once_t once; dispatch_once(&once,^{ instace = [StudentDAO new]; [instace initDataBase]; }); return instace;}//拼接数据库路径-(NSString *)dbPath{ NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *path = [documents lastObject]; return [path stringByAppendingPathComponent:@"test.db"];}//此方法会多次被调用,用户创建表-(BOOL)execSql:(NSString *)sql{ char *errorMsg = NULL; //参数详解,请参考⬆️上个案例 sqlite3_exec(_db, [sql UTF8String], nil, nil, &errorMsg); if (errorMsg) { NSLog(@"执行失败:%s",errorMsg); return NO; } else { NSLog(@"执行成功"); return YES; }}-(void)initDataBase{ //打开数据库 if (sqlite3_open([[self dbPath]UTF8String], &_db) == SQLITE_OK) { //创建表 if ([self execSql:@"create table student (ID integer primary key autoincrement,name text,age integer,gender integer,chineseScore real,mathScore real,englishScore real)"]) { for (int i = 0; i < 5; i++) { Student *stu = [[Student alloc]init]; stu.name = [NSString stringWithFormat:@"name%d",i+1]; stu.age = 22+i; stu.gender = (i % 2 == 0 ? 'F':'M'); stu.chineseScore = 74+i; stu.mathScore = 85+i; stu.englishScore = 92+i; [self addStudent:stu]; } } } sqlite3_close(_db);}//添加学生记录-(BOOL)addStudent:(Student *)student{ NSString *insertSql = @"insert into student(name text,age integer,gender integer,chineseScore real,mathScore real,englishScore real)"; sqlite3_stmt *pStmt = nil; if (sqlite3_prepare_v2(_db, [insertSql UTF8String], -1, &pStmt, nil) == SQLITE_OK) { //使用sqlite3_bind_xxx()对字段进行绑定,通配符与绑定的字段一一对应。序号从1开始。 sqlite3_bind_text(pStmt, 1, [student.name UTF8String], -1, NULL); sqlite3_bind_int(pStmt, 2, student.age); sqlite3_bind_int(pStmt, 3, student.gender); sqlite3_bind_double(pStmt, 4, student.chineseScore); sqlite3_bind_double(pStmt, 5, student.mathScore); sqlite3_bind_double(pStmt, 6, student.englishScore);// SQLITE_DONE:SQL语句执行完成 if (sqlite3_step(pStmt) == SQLITE_DONE) { return YES; } //释放结果集 sqlite3_finalize(pStmt); } return NO;}//更新学生记录-(BOOL)updateStudent:(Student *)student{ NSString *updateSql = @"update student set math = ? where name = ?"; //准备结果集 sqlite3_stmt *pStmt = NULL; if (sqlite3_prepare_v2(_db, [updateSql UTF8String], -1, &pStmt, NULL)== SQLITE_OK) { sqlite3_bind_int(pStmt, 1, student.mathScore); sqlite3_bind_text(pStmt, 2, [student.name UTF8String], -1, NULL); if (sqlite3_step(pStmt) == SQLITE_DONE) { return YES; } } //清理结果集 sqlite3_finalize(pStmt); return NO;}//通过姓名进行删除-(BOOL)deleteStudentByName:(NSString *)name{ NSString *deleteSql = @"delete from student where name = ?"; sqlite3_stmt *pStmt = NULL; if (sqlite3_prepare_v2(_db, [deleteSql UTF8String], -1, &pStmt, nil) == SQLITE_OK) { sqlite3_bind_text(pStmt, 1, [name UTF8String], -1, NULL); if (sqlite3_step(pStmt) == SQLITE_OK) { return YES; } } sqlite3_finalize(pStmt); return NO;}//查询学生记录-(NSArray *)queryStudentAll{ NSMutableArray *array = [NSMutableArray array]; //准备结果集 sqlite3_stmt *pStmt = NULL; if (sqlite3_prepare_v2(_db, [@"select * from student" UTF8String], -1, &pStmt, NULL) == SQLITE_OK) { //遍历结果集 while (sqlite3_step(pStmt) == SQLITE_ROW) { Student *stu = [[Student alloc]init]; stu.ID = sqlite3_column_int(pStmt, 0); stu.name = [NSString stringWithFormat:@"%s",sqlite3_column_text(pStmt, 1)]; stu.age = sqlite3_column_int(pStmt, 2); stu.gender = sqlite3_column_int(pStmt, 3); stu.chineseScore = sqlite3_column_double(pStmt, 4); stu.mathScore = sqlite3_column_double(pStmt, 5); stu.englishScore = sqlite3_column_double(pStmt, 6); [array addObject:stu]; } } //清理结果集 sqlite3_finalize(pStmt); return array;}//通过姓名进行查找-(Student *)queryStudentByName:(NSString *)name{ NSString *sql = @"select * from student where name = ?"; //准备结果集 sqlite3_stmt *pStmt = NULL; if (sqlite3_prepare_v2(_db,[sql UTF8String], -1, &pStmt, NULL) == SQLITE_OK) { sqlite3_bind_text(pStmt, 1, [name UTF8String], -1, NULL); //执行语句 if(sqlite3_step(pStmt)== SQLITE_ROW) { Student *stu = [Student new];// 使用sqlite3_column_xxx()进行获取某列的字段值。 stu.ID = sqlite3_column_int(pStmt, 0); stu.name = [NSString stringWithFormat:@"%s",sqlite3_column_text(pStmt, 1)]; stu.age = sqlite3_column_int(pStmt, 2); stu.gender = sqlite3_column_int(pStmt, 3); stu.chineseScore = sqlite3_column_double(pStmt, 4); stu.mathScore = sqlite3_column_double(pStmt, 5); stu.englishScore = sqlite3_column_double(pStmt, 6); return stu; } } sqlite3_finalize(pStmt); return nil;}@end 以下内容是从网络中摘抄的一些东西,供大家学习参考。 sqlite提供了一些C函数的接口,有100多个,可以通过这些接口操作数据库,传递一些标准sql语句(以char * 类型)给sqlite函数,sqlite就会为你操作数据库。关于SQL语句,在本目录下已经由文章详细介绍,读者自己查看。 大部分函数,如 sqlite3_open()一般还有sqlite3_open16()的版本,前一个表示使用的是UTF-8编码,后一个表示使用的是UTF-16编码。本文为节省篇幅和考虑实用性,仅介绍sqlite3_open()系列,即UTF-8编码的函数,一些不常用或基本不用的系统API将被忽略。 SQLITE关键数据结构:sqlite3 * 包含于头文件 :#include <sqlite3.h> ,关于这个类型的原型自然可以找到,但是对于数据库的操作不需要知道这个,因此,我也没去关注它。sqlite3 *类型,从数据库打开到关闭,都需要使用到它。 SQLITE打开数据库:sqlite3_open() 1】函数原型:int sqlite3_open(const char *filename,sqlite3 **ppDb); 2】函数参数: 第一个是数据库文件名,可以包含路径。如 "./sqlite3/student.db" 第二个参数为指向sqlite *类型的一个指针。 3】返回值:操作成功,返回SQLITE_OK。否则返回其他宏。定义在#include <sqlite3.h>中 例句: sqlite3_open([dbName UTF8String], &_db); SQLITE关闭数据库:sqlite3_close() 函数原型:int sqlite3_close(sqlite3 *ppDb); SQLITE错误消息:sqlite3_errmsg() 1】函数原型:const char *sqlite3_errmsg(sqlite3 *ppDb); 2】返回值:提示出错信息的字符串,可以直接用%s打印 SQLITE操作SQL语句:sqlite3_exec() 1】函数原型:int sqlite3_exec(sqlite3 *ppDb,const char *sql,sqlite3_callback,void *,char **errmsg); 2】参数说明: 第一个参数为sqlite3 *类型。通过sqlite3_open()函数得到 第二个参数是一个指向一个字符串的指针,该字符串的内容为一条完整的SQL语句(不需要在语句结束后加";"),字符串都是以/0结尾的,这个也不例外。 第三个参数为一个回调函数,当这条语句执行之后,sqlite3会去调用这个函数。其原型为 typedef int (*sqlite_callback)(void *,int,char **colvalue,char **colname); 第四个参数为提供给回调函数的参数。如果不需要传递参数,则可以写为NULL。 第五个参数为错误信息。注意,是指针的指针。通过打印printf("%s\n",errmsg),可以知道错误发生在什么地方。 3】返回值:执行成功,返回SQLITE_OK,失败返回其他值。 -(void)execSQL:(NSString *)sql { char *errormessage = NULL; sqlite3_exec(_db, [sql UTF8String],NULL,NULL, &errormessage); if (errormessage) { NSLog(@"执行%@失败:%s",sql,errormessage); } else { NSLog(@"执行成功"); } } SQLITE非回调方法查询数据库:sqlite3_get_table() 1】函数原型:int sqlite3_get_table(sqlite3 *,const char *sql,char ***resultp,int *nrow,int *ncolumn,char **errmsg); 2】参数说明: 第一个参数为sqlite3 *类型 第二个参数为一条SQL语句,与sqlite3_exec()函数的第二个参数相同。 第三个参数为查询结果。注意,这个仍然是一个一维数组(不是三维,更不是二维)。在内存中的布局是第一行是字段名称,后面紧接着是每个字段的值。 第四个参数是查询出多少条数据(即查出多少行) 第五个参数为多少个字段,即查出多少列。 第六个参数为错误信息。与sqlite3_exec()的第五个参数相同。 3】例程:省略。在本文开头的引用页内有详细代码,读者自己理解。 SQLITE中sqlite3_exec()的替代:sqlite3_prepare()、sqlite3_step()、sqlite3_finalize() 1】共同涉及到的类型sqlite3_stmt typedef struct sqlite3_stmt sqlite3_stmt; 2】函数版本说明:则三个函数实现将sql语句编译成字节码,然后执行和释放。这三个函数都有V2版本,应该尽量使用新版本。v2版本和原版本都是基于UTF-8编码说明。v2版本和原版本一个很大的不同,在于返回值上,v2版本要更丰富。 3】函数原型 int sqlite3_prepare(sqlite3 *db,const char *zSql,int nByte,sqlite3_stmt **ppStmt,const char **pzTail); int sqlite3_prepare_v2(sqlite3 *db,const char *zSql,int nByte,sqlite3_stmt **ppStmt,const char **pzTail); 例如: sqlite3_stmt *pStmt = NULL; //*stmt, 这个相当于ODBC的Command对象,用于保存编译好的SQL语句 sqlite3_prepare_v2(_db, "select *from user", 256, &pStmt, NULL); int sqlite3_step(sqlite3_stmt*); int sqlite3_finalize(sqlite3_stmt *pStmt); 4】参数说明:(针对 sqlite3_prepare()函数进行参数说明) 第一个参数为sqlite3 *类型,为指向sqlite3_open()类函数打开的数据库连接。 第二个参数为需要编译成字节码的sql语句。如果输入的参数有多条sql语句,只有第一个SQL语句被编译。 第三个参数,若为小于0的值,系统会自动读取第一个参数一直到出现字符结束符。若该参数大于0,则它表明要读入的SQL的最大的程度,建议设置其值为sql语句的字节数加上字符结束符后的值,此时执行的效率会有提升。 第四个参数,返回编译好的sqlite3_stmt指针,若第一个参数不包含SQL语句或传进来的SQL语句有错,则此函数返回时被置为NULL。 第五个参数若不为NULL,则它会指向第一条SQL语句结尾后面的第一个字节。这个参数用于指向剩下的未编译的语句。 5】函数功能说明:sqlite3_prepare()函数用于将sql语句编译成字节码,并通过sqlite3_stmt类型的参数返回,sqlite3_step()函数,通过使用这个参数一次或者多次来执行这个SQL语句。根据sqlite3_prepare()函数使用的版本,其操作也不同。最后需要调用sqlite3_finalize()函数将这个准备的SQL声明(sqlite3_stmt类型的参数)销毁,避免内存泄露。 6】 返回值:sqlite3_prepare()系列函数和sqlite3_finalize()函数执行成功返回SQLITE_OK,否则返回错误码。 sqlite3_step()函数返回值(根据sqlite3_prepare()的版本不同)如下: 老版本里面: SQLITE_BUSY:无法获取数据库锁来执行此操作 SQLITE_DONE:SQL语句执行完成,在没有再次调用sqlite3_reset()重设SQL到初始状态前不能再调用sqlite3_step() SQLITE_ROW:如果执行的SQL语句返回了数据,则每次返回一行新的数据 SQLITE_ERROR:执行SQL语句出错。 SQLITE_MISUSE:未知 新版本里面返回任何可能的结果编号。 SQLITE重置一个SQL声明的状态sqlite3_reset() 1】函数原型:int sqlite3_reset(sqlite3_stmt *stmt); 2】返回值,执行成功返回SQLITE_OK,否则返回错误码 3】功能说明:sqlite3_reset()函数用来重置一个SQL声明的状态,使得它可以被再次执行。任何的SQL声明中使用sqlite3_bind_*()绑定的变量仍然保留原来的值,可以用sqlite3_clear_bindings()来重设这些绑定的值。 SQLITE表内写入二进制步骤: 1、create table Tbl_2(ID interger,file_content blob)。要插入二进制,前提是这个表的字段的类型是blob类型。 2、声明sqlite3_stmt *stat变量,运用sqlite3_prepare(db,"insert into Tbl_2(ID,file_content)VALUES(10,?)",-1,&stat,NULL);将SQL语句解析到stat结构里去。与前面不同的是,第二个参数sql语句中,在values里面有个"?",表示一个未定的值,也可以理解为是一个占位符。其值通过后续步骤才能插入。 3、使用 sqlite3_bind_blob()绑定一个blob类型的值。调用语句为: sqlite3_bind_blob(stat,1,pdata,(int)(length_of_data_in_bytes),NULL); 1】函数原型为:int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); 2】参数说明: 第一个参数为sqlite3_stmt *类型,由sqlite3_prepare()函数返回。 第二个参数为"?"的索引,表示第几个"?"的位置。如果有多个问号,那就写多个sqlite3_bind_blob()函数。 第三个参数为二进制数据的起始指针。 第四个参数为二进制数据的长度,以字节为单位。 第五个参数是个析构回调函数,告诉sqlite当把数据处理完后,调用此函数来析构数据。通常设为NULL,调用完后自己释放。 4、上步的bind操作将二进制数据写入到了经过字节编码的sql语句里面了,调用sqlite3_step(stat)将其保存到数据库中。最后用sqlite3_finalize(stat)函数对其进行释放。 SQLITE表内读出二进制步骤: 1、读出数据,就是写入过程的一个逆过程。首先定义一个sqlite3_stmt *stat 变量,调用sqlite3_prepare(db,"select * from Tbl_2",-1,&stat,NULL)将一个sql语句解析到stat结构里去。 2、调用sqlite3_step(stat)来查询数据,当返回值为SQLITE_ROW时表示成功(注意不是SQLITE_OK),可以循环执行sqlite3_step函数,一次step查询出一条记录。直到返回值不是SQLITE_ROW时表示查询结束。 3、调用 sqlite3_column_int(stat,0)获取第一个字段的数值id。调用 sqlite3_column_blob(stat,1)获取const void *pFileContent,即file_content二进制数据的指针,调用 sqlite3_column_bytes(stat,1)获取它的长度len。这样就得到了二进制的值。 这三个函数 sqlite3_column_int()、 sqlite3_column_blob()、 sqlite3_column_bytes()是同一个系列的函数。其通用的函数原型为 int sqlite3_column_xxx(sqlite3_stmt*, int iCol);其中第二个参数为列数,即第几个参数。关于这个系列函数的更多细节,请自行查看CSDN上大神的解读,引用页 http://blog.csdn.net/mamong/article/details/8441091 4、经过上面3步后,第四步就是保存pFileContent指向的内容,同时不要忘记释放sqlite3_stmt结构。调用sqlite3_finalize(stat),把刚才分配的内容析构掉。 SQLITE事务处理: sqlite支持事务处理。通常一次sqlite3_exec()就是一次事务,如果要删除1万条数据,开始新事务->删除一条数据->提交事务->开始新事务->删除一条数据->提交事务-> ......用这种方法是很慢的。你可以把这些同类的操作做成一个事务,这样如果操作错误,还能够回滚事务。事务的操作没有特别的接口函数,它就是一个普通的sql语句而已,分别如下: int result; result = sqlite3_exec(db,"begin transaction",0,0,&zErrorMsg);//开始一个事务 result = sqlite3_exec(db,"commit transaction",0,0,&zErrorMsg);//提交事务 result = sqlite3_exec(db,"rollback transaction",0,0,&zErrorMsg);//回滚事务 SQLITE数据库加密: SQLITE支持加密扩展,首先要定义一个宏SQLITE_HAS_CODEC。在代码最前面(也可以在sqlite3.h文件的第一行)定义: #ifndef SQLITE_HAS_CODEC #define SQLITE_HAS_CODEC #endif 。。。。。。 在使用Sqlite3进行数据库操作时我大致划分: 准备工作:导入系统框架(C语言)。(libsqlite3) libsqlite3.dylib 1.初始化数据,其中在初始化阶段要做的工作有: ( 1)设置数据库的存储路径 NSArray *document = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentPath = [document lastObject]; return [documentPath stringByAppendingPathComponent:@"student1.db"]; ( 2)在数据库建立成功之后,使用sqlite3_open()进行打开数据库,如果返回值等于SQLITE_OK则表示打开成功。 if (sqlite3_open([[self pathForDB]UTF8String], &_db)== SQLITE_OK) { } (3)接下来要做的就在数据库中进行创建表; 1).编写SQL语句 NSString *insertSql = @"insert into student (name,age,gender,math,english,chinese)values(?,?,?,?,?,?)"; 2).通过sqlite3_prepare_v2()函数对象SQL语句进行编译执行,在执行成功之后,将结果保存到sqlite3_stmt()结果集中。 //准备结果集 sqlite3_stmt *pStmt = NULL; if(sqlite3_prepare_v2(_db, [insertSql UTF8String], -1, &pStmt, NULL)== SQLITE_OK) {} 以上代码中注意:参数3:若为小于0的值,系统会自动读取第一个参数一直到出现字符结束符。若该参数大于0,则它表明要读入的SQL的最大的程度,建议设置其值为sql语句的字节数加上字符结束符后的值,此时执行的效率会有提升。 2.在对数据进行修改操作时(比如:插入,修改,删除),SQL语句中在为之字段值是可以使用通配符“?”进行代替 (1)使用sqlite3_bind_xxx()对字段进行绑定,通配符与绑定的字段一一对应。序号从1开始。 其中:xxx表示的是字段类型 例如: sqlite3_bind_int(pStmt, 1, (int)student.age); 3.在对数据进行查询操作时,SQL语句中在也可为之字段值是可以使用通配符“?”进行代替。 ( 1)使用sqlite3_column_xxx()进行获取某列的字段值。 例如:stu.age = sqlite3_column_int(pStmt, 2); 4.在对结果集使用结束之后,使用sqlite3_finalize函数进行清理结果集。 //清理结果集 sqlite3_finalize(pStmt); 5.最后就是关闭数据库。 sqlite3_close(_db); SQLite支持的常见数据类型如下所示。 INTEGER 有符号的整数类型 REAL 浮点类型 TEXT 字符串类型,采用UTF-8和UTF-16字符编码 BLOB 二进制大对象类型,能够存放任何二进制数据