class SQLiteManager: NSObject {
private static let manager: SQLiteManager =
SQLiteManager()
/// 单粒
class func shareManager() ->
SQLiteManager {
return manager
}
// 数据库对象
private var db:COpaquePointer = nil
// 创建一个串行队列
private let dbQueue = dispatch_queue_create(
"com.520it.lnj", DISPATCH_QUEUE_SERIAL)
func execQueueSQL(action: (manager: SQLiteManager)->
())
{
// 1.开启一个子线程
dispatch_async(dbQueue) { () -> Void
in
print(NSThread.currentThread())
// 2.执行闭包
action(manager: self)
}
}
/**
打开数据库
: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
}
// 2.创建表
if creatTable()
{
print("创建表成功")
}else
{
print("创建表失败")
}
}
private func creatTable() ->
Bool
{
// 1.编写SQL语句
// 建议: 在开发中编写SQL语句, 如果语句过长, 不要写在一行
// 开发技巧: 在做数据库开发时, 如果遇到错误, 可以先将SQL打印出来, 拷贝到PC工具中验证之后再进行调试
let sql =
"CREATE TABLE IF NOT EXISTS T_Person( \n" +
"id INTEGER PRIMARY KEY AUTOINCREMENT, \n" +
"name TEXT, \n" +
"age INTEGER \n" +
"); \n"
// print(sql)
// 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)
}
// 返回查询到的数据
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..<
count
{
// 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<Int8>
(sqlite3_column_text(stmt, index))
let text = NSString(CString: cText, encoding: NSUTF8StringEncoding)!
record[name] =
text
case SQLITE_NULL:
// 空类型
record[name] =
NSNull()
default:
// 二进制类型 SQLITE_BLOB
// 一般情况下, 不会往数据库中存储二进制数据
print(
"")
}
}
return record
}
}
使用事务插入数据:
let manager = SQLiteManager.shareManager()
// 开启事务
manager.beginTransaction()
for i in 0..<10000
{
let p = Person(dict: ["name": "zs + \(i)", "age": 3 + i])
p.insertPerson()
if i == 1000
{
manager.rollbackTransaction()
// 注意点: 回滚之后一定要跳出循环停止更新
break
}
}
// 提交事务
manager.commitTransaction()
预编译绑定:
//1、打开数据库
sqlite3 *db = [self sqlite3_open_database];
//2、建立预编译语句对象并编译
charchar *sql = "INSERT INTO student(name,age) VALUES(?,?)";//?为占位符,代表此处将来用变量值替换
//2.1、准备预编译语句对象
sqlite3_stmt *stmt = NULL;
//2.2、预编译sql语句
int result = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
//2.3、预编译成功,绑定值
if (result == SQLITE_OK) {
//绑定界面数据到预编译sql语句中
sqlite3_bind_text(stmt, 1, [self.txtName.text UTF8String], -1, NULL);
sqlite3_bind_int(stmt, 2, [self.txtAge.text intValue]);
//3、执行预编译语句对象,4、使用结果
result = sqlite3_step(stmt);
if (result == SQLITE_DONE) {
[self myAlert:@"插入数据成功!"];
} else {
[self myAlert:@"插入数据失败!"];
}
}
//5、销毁预编译语句对象,关闭数据库
sqlite3_finalize(stmt);
sqlite3_close(db);
第十二篇、Swift----Sqlite的使用
标签: