SQLite是个轻型的数据库,适合用于手机中小型的数据存储。app有时需要持久化的存储数据,以保证在程序下次开启的时候能够获取上一次的数据。而数据极少的时候,可以使用plist文件、归档来存储,比如只需要保存用户的用户名、密码用于自动登录,当数据多一些、并且有一定复杂的结构的时候,就需要使用数据库。而且plist有个致命问题是,每次修改都需要把整个文件的数据全部替换,对于存取频繁的操作很不适合。
SQLite的操作是使用C函数和SQL语句来实现的,基本都是这样的组合。SQL语句以字符串的形式作为参数传入C函数,然后执行对数据库的操作。按照增、删、改、查的顺序讲一下简单应用。
1、创建数据库、创建表:
对于iOS app来说,文件存放在程序所在的沙盒目录下,持久化的文件放在documents文件夹里,所以先获取文件路径:
NSArray * documentsDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
_filePath = [[documentsDir objectAtIndex:0] stringByAppendingPathComponent:@"mysql.db"]
先获取沙盒中documents文件夹的目录,然后在后面拼接上需要创建的文件名,构成路径。
然后打开数据库:
if(sqlite3_open([_filePath cStringUsingEncoding:NSUTF8StringEncoding], &_dataBase) != SQLITE_OK){
return @"sqlite open error";
};
const char * sql = "create table if not exists products (id integer primary key autoincrement,price real,weight real,name text,cover blob)";
char * errorMsg = nil;
if (sqlite3_exec(_dataBase, sql, NULL, NULL, &errorMsg) != SQLITE_OK) {
sqlite3_close(_dataBase);
return [NSString stringWithCString:errorMsg encoding:NSUTF8StringEncoding];
}
使用sqlite3_exec函数来执行相应的SQL语句,5个参数,第一个参数是前面打开的数据库指针,指定对哪个数据库操作,第二个参数是想要执行的SQL语句,第三个和第四个分别是方法执行后的回调函数和给回调函数的参数,最后一个参数传递错误信息。SQLITE_OK用来做函数执行判断,如果返回值等于SQLITE_OK那么表示执行成功。
建表的语句格式为:create table 表名 (列名 列的数据属性,……)。上面的语句中products就是表名,然后每个表是分成很多列来管理的,每一列需要取一个名字,然后需要指定这一列中数据以何种类型存放,例如上面的 price real,这一列的名字为price,数据是浮点数类型。而sqlite支持5种数据类型:空值 null,整数 integer,浮点 real,字符串 text,数据块 blob。有个特殊的列是表的主键列,使用整数给每一行的数据标上一个特定的id,如id integer primary key,后面加上primary key。关于SQL语句的写法,可以参考W3C School的教程,挺详细的。
2、增,插入数据:
语句为: const char * sql = "insert into products (price,weight) values(111,2222.0)",然后使用函数sqlite3_exec执行这句插入语句就可以。一般格式为:insert into 表名 (列名,……) values(对应的数据名,……)。指定表名,然后对应的把要插入的数据和插入到哪个列写好就可以了。例如上面这句就是只插入一个数据到表products,然后这个数据的price值为111,weight值为2222.0.其他列没有指定数据,就会补为null值,而且默认插入到标的最后一行。
但是有时可能无法直接的写明插入的数据,或说无法在字符串里面写明,例如blob类型,这是可以使用绑定数据:
sql = "insert into products (id,price,weight,name,cover) values(?,?,?,?,?)"; //(1)
sqlite3_stmt * statement ;
if (sqlite3_prepare_v2(_dataBase, sql, -1, &statement, NULL) != SQLITE_OK) { //(2)
sqlite3_close(_dataBase);
return @"sqlite prepare_v2 error";
}else{
sqlite3_bind_null(statement, 1); //(3)
sqlite3_bind_double(statement, 2,product.price);
sqlite3_bind_double(statement, 3, product.weight);
sqlite3_bind_text(statement, 4, [product.name cStringUsingEncoding:NSUTF8StringEncoding], -1, NULL);
NSData * imgData = UIImageJPEGRepresentation(product.cover, 1.0);
sqlite3_bind_blob(statement, 5, imgData.bytes, imgData.length, NULL);
if (sqlite3_step(statement) == SQLITE_DONE) {
NSLog(@"已经写入数据");
}
sqlite3_finalize(statement);
}
const char * sql = "select * from products";
sqlite3_stmt * statement = nil;
if (sqlite3_prepare_v2(_dataBase, sql, -1, &statement, NULL) != SQLITE_OK) {
*errmsg = @"prepare select error";
return nil;
}else{
NSMutableArray * dataArr = [NSMutableArray array];
while (sqlite3_step(statement) == SQLITE_ROW) {
Products * pro = [[Products alloc]init];
pro.rowID = sqlite3_column_int(statement, 0);
pro.price = sqlite3_column_double(statement, 1);
pro.weight = sqlite3_column_double(statement, 2);
const char * text = (const char*)sqlite3_column_text(statement, 3);
pro.name = text==NULL?nil:[NSString stringWithCString:text encoding:NSUTF8StringEncoding];
const void * bytes = sqlite3_column_blob(statement, 4);
NSInteger length = sqlite3_column_bytes(statement, 4);
NSData * imgData = [NSData dataWithBytes:bytes length:length] ;
pro.cover = [UIImage imageWithData:imgData];
[dataArr addObject:pro];
}
return (NSArray *)dataArr;