ios-SQLite基本使用创建多表

鲁景山
2023-12-01

有一些基本的概念学习了下就是

SQLite的框架是纯C语言的框架

所有函数都是以 sqlite_开头的

SQLite操作是持久化的连接,在整个过程中我们不需要管理数据库的连接,先打开,使用完毕之后,我们再通过sqlite3_close()关闭就可以了。

什么是持久化连接,就是一直的去占用这个数据库的资源,就好比我们在网络中的持久化连接,即时通讯的过程应该就是持久化连接的。不然的话一下子断一下,一下子断一下,接受消息就有可能在某个时间段接受不到,之后才接受的到。

sqlite3_open(path,&dataBase),
参数1:数据库的全路径,Int8 对应的是一个字节,数据库的全路径是C语言的字符串,在Swift中我们可以用String来传递
参数2:就是全局数据库访问的'句柄' -> 指针 后续如果要对数据库的操作,全部基于此句柄
返回值 如果 == SQLITE_OK 表示成功

此函数如果数据库不存在的话,就会创建数据库,然后再打开

如果已经存在的,就直接打开数据库

打开数据库的这个函数的第二个参数是需要一个OpaquePointer的类型的对象的地址

这个类型就是不透明的类型,为什么说是不透明的类型,因为因为在C语言中没有对象的概念,只有结构体,然后结构体里面有什么也是无法得知的所有

var dataBase: OpaquePointer? = nil

执行SQL语句的函数

       参数
            1、数据库的全局句柄用来操作数据库
            2、要执行的SQL语句
            3、callback 是执行完SQL之后,调用的C语言函数指针,通常传入nil
            4、第三个参数 callBack 是函数参数的地址,通常传入nil
            5、错误信息,我们可以在通过char *error = NULL 然后传入&error,当然也可以传入nil
           返回值,如果是SQLITE_OK 就表示成功

sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK

在实际开发中,如果我们对自己写的SQL语句可能会出错,我们可以在一个软件中,先去运行下这条语句能不能运行,然后我们再去继续写下面的代码

下面是SWift中SQL语句的编写

let sql = "CREATE TABLE 'T_Person'(" +
            "'id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," +
            "'name' TEXT," +
            "'age'  INTEGER," +
            "'height' REAL" +
        ");"
我们在调试的时候,方便我们查看,可以在拼接字符串的时候,往后面添加一个\n,这样我们就方便查看了,输出的时候都有换行

 let sql = "CREATE TABLE 'T_Person'(\n" +
            "'id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\n" +
            "'name' TEXT,\n" +
            "'age'  INTEGER,\n" +
            "'height' REAL\n" +
        ");"

由于用上面的利用字符串来构造表的方式太过繁琐,就比如说我们要建立100个文件,这样建立会显得很麻烦,所以我们可以通过创建一个空的文件,然后再这个空的文件中写入,我们要创建表的SQL语句,然后我们再进行读取。其中exexSQL函数是我们自己定义的

 //执行SQL指令
    func execSQL(sql:String) -> Bool
    {
        /**
         参数
            1、数据库的全局句柄用来操作数据库
            2、要执行的SQL语句
            3、callback 是执行完SQL之后,调用的C语言函数指针,通常传入nil
            4、第三个参数 callBack 是函数参数的地址,通常传入nil
            5、错误信息,我们可以在通过char *error = NULL 然后传入&error,当然也可以传入nil
           返回值,如果是SQLITE_OK 就表示成功
         */
     return sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK
    }


 //MARK: 创建多个表,我们可以在一个文件中进行写入SQL语句,然后再读取再进行创建
    private func creatTable1() -> Bool
    {
        //1、从bundle中加载sql文件
        let path = Bundle.main.path(forResource: "information.sql", ofType: nil)!
        
        //读取SQL字符串
        let sql = try! String(contentsOfFile:path)
        
        return exexSQL(sql: sql)
    }

sqlite3_changes(dataBase),其中dataBase是全局数据库的句柄,也就是操作对象,这条语句的意思就是返回影响的行数,也就是说我们可以在更新表中数据或者删除表中数据的时候可以用到。

使用sqlite3来进行查询数据的话,我们可以通过调用sqlite3_prepare_v2来获取预编译的结果stmt,然后再通过sqlite3_step(stmt)来一个一个的取每一个数据。

具体步骤其实就是这样,先获取SQL预编译的句柄

func execRecordSet(sql:String)
    {
        //1、预编译 SQL
        /**
        参数1、全局数据库的句柄
        参数2、要执行的SQL的C语言字符串
        参数3、要执行的SQL的以字节为单位的长度,如果我们传入-1,SQLite框架会自动计算
        参数4、stmt- 就是预编译的指令句柄
            后续我们针对本地查询的所有的操作,全部是基于此句柄的
            我们需要注意的是,句柄一定要释放
           编译完成之后,我们其实可以把这个句柄理解成一个临时的数据的集合,通过step函数
           我们能够顺序的取得其中的结果,其实就是使用C语言字符串来获得sql准备语句(prepared statement),然后转化为可被SQLite3识别的执行语句
         参数5、关于stmt尾部参数的指针,通常会传入nil
         返回值,如果编译成功了,就表示SQL能正常的执行,返回SQLITE_OK
         sqlite3_prepare和sqlite3_perpare_v2的区别在于前面的函数是向前兼容的,有v2的推荐给新程序使用
         */
        var stmt:OpaquePointer?
        
       if sqlite3_prepare_v2(db, sql, -1, &stmt, nil) != SQLITE_OK
       {
        print("SQL错误")
       //释放句柄
       sqlite3_finalize(stmt)
        }
        print("SQL正确")
       //释放句柄
       sqlite3_finalize(stmt)
    }

遍历每一条记录,从stmt中取,这里用while循环是因为sqlite3_step是一条一条记录去取的,如果取到了就会返回SQLITE_ROW

          while sqlite3_step(stmt) == SQLITE_ROW
        {
       //1、知道记录的列数
        let columns = sqlite3_column_count(stmt)
        //循环每一列,获得每一列对应的内容
        for colu in 0..<columns
        {
            //1、获取相应的列名 Int8 /CChar /Byte是一样的
            let cname = sqlite3_column_name(stmt,colu)
            //根据C语言字符串转换成Swift中的String字符串
            let name = String(cString: cname!, encoding:String.Encoding.utf8)
            
            //2、获取数据的类型
            let type = sqlite3_column_type(stmt, colu)
            
            var value:AnyObject?
            
            switch type
            {
             //小数
            case SQLITE_FLOAT:
                value = sqlite3_column_double(stmt, colu) as AnyObject
            //整数
            case SQLITE_INTEGER:
                value = Int(sqlite3_column_int(stmt, colu)) as AnyObject
            //字符串
            case SQLITE3_TEXT:
                let cText = sqlite3_column_text(stmt, colu)
                value = String(cString: cText!) as AnyObject
            //空值,数据库允许字段为空
            case SQLITE_NULL:
                value = NSNull()
                
            default:
                print("不支持的数据类型")
            }
            print(value)
        }
}





 类似资料: