iOS 数据存储之SQLite3的使用

时间:2023-03-08 19:07:49
iOS 数据存储之SQLite3的使用

SQLite3是iOS内嵌的数据库,SQLite3在存储和检索大量数据方面非常有效,它使得不必将每个对象都加到内存中。还能够对数据进行负责的聚合,与使用对象执行这些操作相比,获得结果的速度更快。

SQLite3使用SQL结构化查询语言,SQL是与关系数据库交互的标准语言。

SQLite3的使用:

1、导入头文件

#import <sqlite3.h>

2、创建或者打开数据库

   //创建和打开数据库
sqlite3 *database; //如果sqlite3_open的结果是 SQLITE_OK,表示数据库已经打开成功。
//SQLite3是采用可移植的C,数据库的文件路径必须以C字符串(非NSString)的形式进行传递。
if (sqlite3_open("/path/databaseFile", &database) != SQLITE_OK)
{
     sqlite3_close(database); NSAssert(, @"Failed to open database");
  }

3、创建一个表

    //创建一个新表
NSString *createSQL = @"CREATE TABLE IF NOT EXISTS FIELDS "
"(ROW INTEGER PRIMARY KEY, FIELD_DATA TEXT);";
char *errorMsg; //sqlite3_exec 针对 SQLite3 运行任何不返回数据的命令
if (sqlite3_exec (database, [createSQL UTF8String],
NULL, NULL, &errorMsg) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(, @"Error creating table: %s", errorMsg);
}

注:sqlite3_exec 执行之后,如果值是SQLITE_OK,则表明执行成功;否则,错误信息存储在errorMsg中。

sqlite3_exec这个方法可以执行那些没有返回结果的操作,例如创建、插入、删除等。

4、对表进行操作

4.1存储数据到数据库

    sqlite3 *database;
if (sqlite3_open([[self dataFilePath] UTF8String], &database)
!= SQLITE_OK) {
sqlite3_close(database);
NSAssert(, @"Failed to open database");
} //例子:存储UITextField的值到数据库
for (int i = ; i < ; i++) {
UITextField *field = self.lineFields[i]; //插入操作
char *update = "INSERT OR REPLACE INTO FIELDS (ROW, FIELD_DATA) "
"VALUES (?, ?);";
char *errorMsg = NULL;
//创建stmt
sqlite3_stmt *stmt;
//无论针对哪种数据,任何绑定函数的第一个参数都指向之前在sqlite3_prepare_v2 调用中 使用的sqlite3_stmt
if (sqlite3_prepare_v2(database, update, -, &stmt, nil)
== SQLITE_OK) { //SQLITE_OK 表示执行成功 /*sqlite3_bind_int(stmt, 1, i);有三个参数: 第一个是sqlite3_stmt类型的变量,在之前的sqlite3_prepare_v2中使用的。 第二个是所约束变量的标签index。 第三个参数是要加的值。*/ sqlite3_bind_int(stmt, , i);
sqlite3_bind_text(stmt, , [field.text UTF8String], -, NULL);
} if (sqlite3_step(stmt) != SQLITE_DONE)
NSAssert(, @"Error updating table: %s", errorMsg); //sqlite3_finalize销毁前面被sqlite3_prepare创建的准备语句
sqlite3_finalize(stmt);
}
//sqlite3_close关闭前面使用sqlite3_open打开的数据库连接,任何与这个连接相关的准备语句必须在调用这个关闭函数之前被释放
sqlite3_close(database);

4.2 对数据库进行查询操作

    //创建query 和 sqlite3_stmt
NSString *query = @"SELECT ROW, FIELD_DATA FROM FIELDS ORDER BY ROW";
sqlite3_stmt *statement; //无论针对哪种数据,任何绑定函数的第一个参数都指向之前在sqlite3_prepare_v2 调用中 使用的sqlite3_stmt
if (sqlite3_prepare_v2(database, [query UTF8String],
-, &statement, nil) == SQLITE_OK)
{
//sqlite3_step用于执行有前面sqlite3_prepare创建的准备语句。这个语句执行到结果的第一行可用的位置。继续前进到结果的第二行的话,只需再次调用sqlite3_setp()。继续调用sqlite3_setp()知道这个语句完成,那些不返回结果的语句(如:INSERT,UPDATE,或DELETE),sqlite3_step()只执行一次就返回
while (sqlite3_step(statement) == SQLITE_ROW) {
int row = sqlite3_column_int(statement, );
char *rowData = (char *)sqlite3_column_text(statement, );

NSString *fieldValue = [[NSString alloc]
initWithUTF8String:rowData];
UITextField *field = self.lineFields[row];
field.text = fieldValue;
}
//sqlite3_finalize销毁前面被sqlite3_prepare创建的准备语句
sqlite3_finalize(statement);
}
//sqlite3_close关闭前面使用sqlite3_open打开的数据库连接,任何与这个连接相关的准备语句必须在调用这个关闭函数之前被释放
sqlite3_close(database);

5、使用约束变量

实际操作时经常使用叫做约束变量的东西来构造SQL字符串,从而进行插入、查询或者删除等。

例如,要执行带两个约束变量的插入操作,第一个变量是int类型,第二个是C字符串:

char *sql = "insert into oneTable values (?, ?);";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(database, sql, -, &stmt, nil) == SQLITE_OK) {
sqlite3_bind_int(stmt, , );
sqlite3_bind_text(stmt, , "valueString", -, NULL);
}
if (sqlite3_step(stmt) != SQLITE_DONE)
NSLog(@"Something is Wrong!");
sqlite3_finalize(stmt);

这里,sqlite3_bind_int(stmt, 1, 235);有三个参数:

第一个是sqlite3_stmt类型的变量,在之前的sqlite3_prepare_v2中使用的。

第二个是所约束变量的标签index。

第三个参数是要加的值。

有一些函数多出两个变量,例如

sqlite3_bind_text(stmt, , "valueString", -, NULL);

这句,第四个参数代表第三个参数中需要传递的长度。对于C字符串来说,-1表示传递全部字符串。

第五个参数是一个回调函数,比如执行后做内存清除工作。

6、SQLite3中常用的函数

sqlite3_open():打开数据库,在操作数据库之前,首先要打开数据库。这个函数打开一个sqlite数据库文件的连接并且返回一个数据库连接对象。这个操作同时程序中的第一个调用的sqlite函数,同时也是其他sqlite api的先决条件。许多的sqlite接口函数都需要一个数据库连接对象的指针作为它们的第一个参数。

sqlite3_prepare():将sql文本转换成一个准备语句(prepared statement)对象,同时返回这个对象的指针。这个接口需要一个数据库连接指针以及一个要准备的包含SQL语句的文本。它实际上并不执行(evaluate)这个SQL语句,它仅仅为执行准备这个sql语句。

sqlite3_step():执行有前面sqlite3_prepare创建的准备语句。这个语句执行到结果的第一行可用的位置。继续前进到结果的第二行的话,只需再次调用sqlite3_setp()。继续调用sqlite3_setp()知道这个语句完成,那些不返回结果的语句(如:INSERT,UPDATE,或DELETE),sqlite3_step()只执行一次就返回。

sqlite3_column():执行sqlite3_step()执行一个准备语句得到的结果集的当前行中返回一个列。每次sqlite3_step得到一个结果集的列停下后,这个过程就可以被多次调用去查询这个行的各列的值。对列操作是有多个函数,均以sqlite3_column为前缀。

sqlite3_finalize():销毁前面被sqlite3_prepare创建的准备语句,每个准备语句都必须使用这个函数去销毁以防止内存泄露。在空指针上调用这个函数没有什么影响,同时可以准备语句的生命周期的任一时刻调用这个函数:在语句被执行前,一次或多次调用sqlite_reset之后,或者在sqlite3_step任何调用之后不管语句是否完成执行

sqlite3_close():关闭前面使用sqlite3_open打开的数据库连接,任何与这个连接相关的准备语句必须在调用这个关闭函数之前被释放