swift -> sqlite3

添加libsqlite3.tbd General -> Linked Frameworks and Libraries -> 添加libsqlite3.tbd

添加桥接 Build Settings -> (搜索 Bridg)Objective-C Bridging Header -> 添加 项目名/Bridge.h

Bridge.h 添加一行如下:

#import

extension String{

/**

将当前字符串拼接到cache目录后面

*/

func cacheDir() -> String{

let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomainMask.UserDomainMask, true).last!  as NSString

return path.stringByAppendingPathComponent((self as NSString).lastPathComponent)

}

/**

将当前字符串拼接到doc目录后面

*/

func docDir() -> String

{

let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last!  as NSString

return path.stringByAppendingPathComponent((self as NSString).lastPathComponent)

}

/**

将当前字符串拼接到tmp目录后面

*/

func tmpDir() -> String

{

let path = NSTemporaryDirectory() as NSString

return path.stringByAppendingPathComponent((self as NSString).lastPathComponent)

}

}

打开数据库 :SQLiteManager.shareManager().openDB("sql.sqlite")

关闭数据库:let bool = closeDB(db)

创建表:let bool = creatTable("T_Class")

查询:let sql = "SELECT * FROM T_Class;"

let res = SQLiteManager.shareManager().execRecordSQL(sql)

删除(更新插入修改下sql语句):

let sql = "DELETE FROM T_Class WHERE age IS 10;"

let bool = SQLiteManager.shareManager().execSQL(sql)

子线程执行插入数据库:

SQLiteManager.shareManager().execQueueSQL { (manager) -> () in

// 1.编写SQL语句

let sql = "INSERT INTO T_Person" +

"(name, age)" +

"VALUES" +

"('\\(self.name!)', \\(self.age));"

// 2.执行SQL语句

manager.execSQL(sql)

print(NSThread.currentThread())

}

事务+预编译 提高效率:

let manager = SQLiteManager.shareManager()

// 开启事务

manager.beginTransaction()

for i in 0..<10000

{

let sql = "INSERT INTO T_Person" +

"(name, age)" +

"VALUES" +

"(?, ?);"

manager.batchExecSQL(sql, args: "yy +\\(i)", 1 + i)

}

// 提交事务

manager.commitTransaction()

class SQLiteManager: NSObject {

private static let manager: SQLiteManager = SQLiteManager()

/// 单粒

class func shareManager() ->SQLiteManager {

return manager

}

// 数据库对象

private var db:COpaquePointer = nil

/**

打开数据库

:param: SQLiteName 数据库名称

*/

func openDB(SQLiteName: String)

{

// 0.拿到数据库的路径

let path = SQLiteName.docDir()

print(path)

let cPath = path.cStringUsingEncoding(NSUTF8StringEncoding)!

// 1.打开数据库

/*

1.需要打开的数据库文件的路径, C语言字符串

2.打开之后的数据库对象 (指针), 以后所有的数据库操作, 都必须要拿到这个指针才能进行相关操作

*/

// open方法特点: 如果指定路径对应的数据库文件已经存在, 就会直接打开

//              如果指定路径对应的数据库文件不存在, 就会创建一个新的

if sqlite3_open(cPath, &db) != SQLITE_OK

{

print("打开数据库失败")

return

}

// 创建一个串行队列

private let dbQueue = dispatch_queue_create("com.xxx.sql", DISPATCH_QUEUE_SERIAL)

/**

子线程执行数据库插入操作

- parameter action:闭包

*/

func execQueueSQL(action: (manager: SQLiteManager)->())

{

// 1.开启一个子线程

dispatch_async(dbQueue) { () -> Void in

print(NSThread.currentThread())

// 2.执行闭包

action(manager: self)

}

}

// 2.创建表

if creatTable("T_Class")

{

print("创建表成功")

}else

{

print("创建表失败")

}

}

/// 自定义一个SQLITE_TRANSIENT, 覆盖系统的

private let SQLITE_TRANSIENT = unsafeBitCast(-1, sqlite3_destructor_type.self)

// MARK: - 预编译 + 事务可以提高效率

func batchExecSQL(sql:String, args: CVarArgType...) -> Bool

{

// 1.将SQL语句转换为C语言

let cSQL = sql.cStringUsingEncoding(NSUTF8StringEncoding)!

// 2.预编译SQL语句

var stmt: COpaquePointer = nil

if sqlite3_prepare_v2(db, cSQL, -1, &stmt, nil) != SQLITE_OK

{

print("预编译失败")

sqlite3_finalize(stmt)

return false

}

// 3.绑定数据

var index:Int32 = 1

for objc in args

{

if objc is Int

{

//                print("通过int方法绑定数据 \\(objc)")

// 第二个参数就是SQL中('?', ?)的位置, 注意: 从1开始

sqlite3_bind_int64(stmt, index, sqlite3_int64(objc as! Int))

}else if objc is Double

{

//                print("通过Double方法绑定数据 \\(objc)")

sqlite3_bind_double(stmt, index, objc as! Double)

}else if objc is String

{

//                print("通过Text方法绑定数据 \\(objc)")

let text = objc as! String

let cText = text.cStringUsingEncoding(NSUTF8StringEncoding)!

// 第三个参数: 需要绑定的字符串, C语言

// 第四个参数: 第三个参数的长度, 传入-1系统自动计算

// 第五个参数: OC中直接传nil, 但是Swift传入nil会有大问题

/*

typedef void (*sqlite3_destructor_type)(void*);

#define SQLITE_STATIC      ((sqlite3_destructor_type)0)

#define SQLITE_TRANSIENT   ((sqlite3_destructor_type)-1)

第五个参数如果传入SQLITE_STATIC/nil, 那么系统不会保存需要绑定的数据, 如果需要绑定的数据提前释放了, 那么系统就随便绑定一个值

第五个参数如果传入SQLITE_TRANSIENT, 那么系统会对需要绑定的值进行一次copy, 直到绑定成功之后再释放

*/

sqlite3_bind_text(stmt, index, cText, -1, SQLITE_TRANSIENT)

}

index += 1

}

// 4.执行SQL语句

if sqlite3_step(stmt) != SQLITE_DONE

{

print("执行SQL语句失败")

return false

}

// 5.重置STMT

if sqlite3_reset(stmt) != SQLITE_OK

{

print("重置失败")

return false

}

// 6.关闭STMT

// 注意点: 只要用到了stmt, 一定要关闭

sqlite3_finalize(stmt)

return true

}

/**

关闭数据库

- parameter db: 数据库

*/

func closeDB(db: COpaquePointer) -> Bool{

if sqlite3_close(db) == SQLITE_OK {

return true

}

return false

}

// MARK: - 事务相关 (可以提高性能)

// 1.开启事务

func beginTransaction()

{

execSQL("BEGIN TRANSACTION")

}

// 2.提交事务

func commitTransaction()

{

execSQL("COMMIT TRANSACTION")

}

// 3.回滚

func rollbackTransaction()

{

execSQL("ROLLBACK TRANSACTION")

}

//创建表

func creatTable(table: String) -> Bool

{

// 1.编写SQL语句

let sql = "CREATE TABLE IF NOT EXISTS \\(table)( \\n" +

"id INTEGER PRIMARY KEY AUTOINCREMENT, \\n" +

"name TEXT, \\n" +

"age INTEGER \\n" +

"); \\n"

// 2.执行SQL语句

return execSQL(sql)

}

/**

执行除查询以外的SQL语句

:param: sql 需要执行的SQL语句

:returns: 是否执行成功 true执行成功 false执行失败

*/

func execSQL(sql: String) -> Bool

{

// 0.将Swift字符串转换为C语言字符串

let cSQL = sql.cStringUsingEncoding(NSUTF8StringEncoding)!

// 在SQLite3中, 除了查询意外(创建/删除/新增/更新)都使用同一个函数

/*

1. 已经打开的数据库对象

2. 需要执行的SQL语句, C语言字符串

3. 执行SQL语句之后的回调, 一般传nil

4. 是第三个参数的第一个参数, 一般传nil

5. 错误信息, 一般传nil

*/

if sqlite3_exec(db, cSQL, nil, nil, nil) != SQLITE_OK

{

return false

}

return true

}

/**

查询所有的数据

:returns: 查询到的字典数组

*/

func execRecordSQL(sql: String) ->[[String: AnyObject]]

{

// 0.将Swift字符串转换为C语言字符串

let cSQL = sql.cStringUsingEncoding(NSUTF8StringEncoding)!

// 1.准备数据

// 准备: 理解为预编译SQL语句, 检测里面是否有错误等等, 它可以提供性能

/*

1.已经开打的数据库对象

2.需要执行的SQL语句

3.需要执行的SQL语句的长度, 传入-1系统自动计算

4.预编译之后的句柄, 已经要想取出数据, 就需要这个句柄

5. 一般传nil

*/

var stmt: COpaquePointer = nil

if sqlite3_prepare_v2(db, cSQL, -1, &stmt, nil) != SQLITE_OK

{

print("准备失败")

}

// 准备成功

var records = [[String: AnyObject]]()

// 2.查询数据

// sqlite3_step代表取出一条数据, 如果取到了数据就会返回SQLITE_ROW

while sqlite3_step(stmt) == SQLITE_ROW

{

// 获取一条记录的数据

let record = recordWithStmt(stmt)

// 将当前获取到的这一条记录添加到数组中

records.append(record)

}

// 注意点: 只要用到了stmt, 一定要关闭

sqlite3_finalize(stmt)

// 返回查询到的数据

return records

}

/**

获取一条记录的值

:param: stmt 预编译好的SQL语句

:returns: 字典

*/

private func recordWithStmt(stmt: COpaquePointer) ->[String: AnyObject]

{

// 2.1拿到当前这条数据所有的列

let count = sqlite3_column_count(stmt)

//            print(count)

// 定义字典存储查询到的数据

var record  = [String: AnyObject]()

for index in 0..

{

// 2.2拿到每一列的名称

let cName = sqlite3_column_name(stmt, index)

let name = String(CString: cName, encoding: NSUTF8StringEncoding)!

//                print(name)

// 2.3拿到每一列的类型 SQLITE_INTEGER

let type = sqlite3_column_type(stmt, index)

//                print("name = \\(name) , type = \\(type)")

switch type

{

case SQLITE_INTEGER:

// 整形

let num = sqlite3_column_int64(stmt, index)

record[name] = Int(num)

case SQLITE_FLOAT:

// 浮点型

let double = sqlite3_column_double(stmt, index)

record[name] = Double(double)

case SQLITE3_TEXT:

// 文本类型

let cText = UnsafePointer(sqlite3_column_text(stmt, index))

let text = NSString(CString: cText, encoding: NSUTF8StringEncoding)!

record[name] = text

case SQLITE_NULL:

// 空类型

record[name] = NSNull()

print(record)

default:

// 二进制类型 SQLITE_BLOB

// 一般情况下, 不会往数据库中存储二进制数据

print("")

}

}

return record

}

}

SQLite函数总结

1.打开数据库

int sqlite3_open(

const char *filename,   // 数据库的文件路径

sqlite3 **ppDb          // 数据库实例

);

2.执行任何SQL语句

int sqlite3_exec(

sqlite3*,                                  // 一个打开的数据库实例

const char *sql,                           // 需要执行的SQL语句

int (*callback)(void*,int,char**,char**),  // SQL语句执行完毕后的回调

void *,                                    // 回调函数的第1个参数

char **errmsg                              // 错误信息

);

3.检查SQL语句的合法性(查询前的准备)

int sqlite3_prepare_v2(

sqlite3 *db,            // 数据库实例

const char *zSql,       // 需要检查的SQL语句

int nByte,              // SQL语句的最大字节长度

sqlite3_stmt **ppStmt,  // sqlite3_stmt实例,用来获得数据库数据

const char **pzTail

);

4.查询一行数据

int sqlite3_step(sqlite3_stmt*); // 如果查询到一行数据,就会返回SQLITE_ROW

5.利用stmt获得某一字段的值(字段的下标从0开始)

double sqlite3_column_double(sqlite3_stmt*, int iCol);  // 浮点数据

int sqlite3_column_int(sqlite3_stmt*, int iCol); // 整型数据

sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); // 长整型数据

const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); // 二进制文本数据

const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);  // 字符串数据

SQLite语句

/*简单约束*/

CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER);

CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER NOT NULL);

CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER);

CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER DEFAULT 1);

/*分页*/

SELECT * FROM t_student ORDER BY id ASC LIMIT 30, 10;

/*排序*/

SELECT * FROM t_student WHERE score > 50 ORDER BY age DESC;

SELECT * FROM t_student WHERE score < 50 ORDER BY age ASC , score DESC;

/*计量*/

SELECT COUNT(*) FROM t_student WHERE age > 50;

/*别名*/

SELECT name as myName, age as myAge, score as myScore FROM t_student;

SELECT name myName, age myAge, score myScore FROM t_student;

SELECT s.name myName, s.age myAge, s.score myScore FROM t_student s WHERE s.age > 50;

/*查询*/

SELECT name, age, score FROM t_student;

SELECT * FROM t_student;

/*修改指定数据*/

UPDATE t_student SET name = 'MM' WHERE age = 10;

UPDATE t_student SET name = 'WW' WHERE age is 7;

UPDATE t_student SET name = 'XXOO' WHERE age < 20;

UPDATE t_student SET name = 'NNMM' WHERE age < 50 and score > 10;

/*删除数据*/

DELETE FROM t_student;

/*更新数据*/

UPDATE t_student SET name = 'LNJ';

/*插入数据*/

INSERT INTO t_student(age, score, name) VALUES ('28', 100, 'jonathan');

INSERT INTO t_student(name, age) VALUES ('lee', '28');

INSERT INTO t_student(score) VALUES (100);

/*插入数据*/

INSERT INTO t_student(name, age, score) VALUES ('lee', '28', 100);

/*添加主键*/

CREATE TABLE IF NOT EXISTS t_student (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, score REAL);

/*添加主键*/

CREATE TABLE IF NOT EXISTS t_student (id INTEGER, name TEXT, age INTEGER, score REAL, PRIMARY KEY(id));

/*删除表*/

DROP TABLE IF EXISTS t_student;

/*创建表*/

CREATE TABLE IF NOT EXISTS t_student(id INTEGER , name TEXT, age , score REAL);

推荐阅读更多精彩内容