iOS上数据库SQLite的简单操作

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

    };

  使用sqlite3_open函数,两个参数,第一个是文件地址字符串,要转成C字符串,第二个是sqlite3**类型的变量,c函数中,一般这种指针的指针的形式形参,传入的都是一个指针的地址,例如这里的&_dataBase(_dataBase是sqlite*的指针),而且都是用来给传入的指针赋值的,这里传入_dataBase的地址,方法执行成功后,_dataBase就指向了刚打开的sqlite数据库,之后使用它进行一系列操作。
  然后创建一个表:

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

    }

  这里的product是我自定义的一个类,属性和表中的列对应。这里同样使用insert语句,但是不是直接在values后面写入数据,而是使用问好?代替(1位置),然后使用sqlite3_prepare_v2函数,初始化一个sqlite3_stmt类型的指针(2位置),再将需要插入的数据绑定到这个sqlite3_stmt类型指针上(3位置),就可以了。sqlite3_bind_?这个类型的函数有许多个,分别对应了各个不同的数据类型。

  3、删除数据:
    语句:const char * sql = [[NSString stringWithFormat:@"delete from products where id = %d",product.rowID] cStringUsingEncoding:NSUTF8StringEncoding];
    同样再使用sqlite3_exec函数执行就可以了。
    删除就是使用delete语句就可以,但这里的关键问题是正确找到需要删除的那一条数据,也就是说筛选其实是关键。筛选使用where语句,如where id = 4,就是筛选id等于的4的所有数据。还有许多其他的运算法,参考where语句,然后多个条件是可以一起使用的,使用AND、OR关键词,它们的作用就和它们的单词意思一样。

  4、更改数据:
   使用update语句:"update products set price = 5000 where id = 4"。格式是:update 表名 set 列名 = 需要更改的值,…… 筛选条件。当有多个值需要修改时,可以一起写出来,中间用逗号隔开。最后同样可以使用where语句来实现筛选,一边对特定的数据进行修改。

  5、查询、读取数据:
   

    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;


 上面的例子实现从表products里面读取所有的数据,然后使用一个数据保存起来。查询使用select语句结合where语句,这里因为是获取所有数据,所以没有使用where筛选,使用where可以让你获取想要的特定的数据。select语句格式为:select 列表名1,列表名2,…… from 表名 筛选条件。这里同样使用sqlite3_prepare_v2执行语句字符串,然后初始化一个sqlite3_stmt类型的指针statement,可以理解为,执行了查询之后,我们获得了一些符合条件的数据,然后它们构成一张小表,接下来就是读这张小表,然后把数据提取出来。
   通过“while (sqlite3_step(statement) == SQLITE_ROW) {}”这个循环来不断执行sqlite3_step,一开始读取的是第一行的数据,然后再运行一次就向下移动一行,这样一直读到数据的结尾。sqlite3_step的返回值为SQLITE_ROW说明现在还是读到一列数据,而当为SQLITE_DONE时,是读到最后了,所以使用它来作是否结束的标志。每次读取的时候,从statement里面把数据取出来,使用sqlite3_column_?这类的函数,不同的数据类型使用不同的函数。整个过程有点像是使用磁带放歌,这里的sqlite3_stmt类型指针statement就显示磁头,不断的读取数据,然后切换到写一个数据,知道最后磁带到头了,就结束了。
 
  简单的使用就这些,更好的使用可能还要考虑数据更快的存取、怎么更合理建表以及多个表之间的联系操作、多线程下数据库操作的线程安全问题等等。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值