美文网首页数据库架构设计
数据库连接-静态构建表

数据库连接-静态构建表

作者: 架构师的一小步 | 来源:发表于2019-04-02 10:47 被阅读0次
静态构建表-指手动创建数据库,自己写sql代码

第一步:新建一个Connection类?
作用:管理我们数据库
功能:
打开数据库
关闭数据库
执行SQL语句
数据库基本属性使用(后面会用到)->铺垫

第二步:定义数据库位置方式(类型)
三种类型:内存数据库、临时数据库、URI方式(地址)
枚举->Location
三种数据库存储位置不同
网址:https://www.sqlite.org/inmemorydb.html#sharedmemdb

第三步:定义数据库SQL操作类(操作表)
种类:
插入数据-insert
更新数据-update
删除数据-delete
枚举->定义表操作

第四步:打开数据库
通过构造方法实现

第五步:检测数据库结果

第六步:创建数据库执行队列
数据库所有表操作->什么样队列中执行
串行队列->一个个排队执行(线下买票)
并行队列->同时执行(网上购票)
问题:什么时候串行队列、什么时候并行队列?
挖个坑?后面我们在讨论?

第七步:执行SQL语句

第八步:定义数据库基本操作属性
1、关闭数据库
2、数据库状态->是否是可读性数据库
3、最后插入的一条数据所返回的行id->rowid
4、数据库受影响行数->changes
5、数据库自从打开到目前为止数据库受影响行数
insert、delete、update总共操作几次
insert->10次(插入10条数据)
delete->删除5条->干坏事5次
update->更新2次->干坏事2次
总共:到目前为止17次
6、中断任何长时间运行的查询操作(客户端少见)
服务器开发->我开发服务器->100万数量级->耗费时间长
7、数据库超时

第九步:测试

具体代码

import UIKit
import SQLite3

//太监类
//第一步:新建一个Connection类?
public final class Connection {

//   第二步:定义数据库位置方式(类型)->几种位置方式->指定存储位置
//   三种类型:内存数据库、临时数据库、URI方式(地址)
//   枚举->Location
    //网址:https://www.sqlite.org/inmemorydb.html#sharedmemdb
    public enum Location {
        //内存数据库->相当于->uri(":memory")
        case inMemory
        //临时数据库->相当于->uri("")
        case temporary
        //URI方式(地址)->相当于->uri("/user/test.db")
        case uri(String)
    }
  
//    第三步:定义数据库SQL操作类(操作表)
//    种类:
//    插入数据-insert
//    更新数据-update
//    删除数据-delete
//    枚举->定义表操作
    public enum Operation {
        //    插入数据-insert
        case insert
        //    更新数据-update
        case update
        //    删除数据-delete
        case delete
        //数据库类型转换
        fileprivate init(rawValue:Int32){
            switch rawValue {
            case SQLITE_INSERT:
                self = .insert
            case SQLITE_UPDATE:
                self = .update
            case SQLITE_DELETE:
                self = .delete
            default:
                fatalError("没有这个操作类型...")
            }
        }
    }
    
    
//    第四步:打开数据库
//    通过构造方法实现
    //第一个默认构造方法
    fileprivate var _handle: OpaquePointer? = nil
    public init(_ location: Location = .inMemory, readonly: Bool = false) throws {
        //打开数据库
        //参数一:数据位置
        //参数二:数据库指针(用于操作数据库)
        //参数三:打开数据库方式
        //SQLITE_OPEN_READONLY:只读数据库
        //SQLITE_OPEN_CREATE:创建数据库(没有就创建)
        //SQLITE_OPEN_READWRITE:可读可写数据库
        //SQLITE_OPEN_FULLMUTEX:设置数据库链接运行队列模式->串行队列、并行队列
        //支持多线程操作
        let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
        let result = sqlite3_open_v2(location.description, &_handle, flags | SQLITE_OPEN_FULLMUTEX, nil)
        //判定数据库是否成功状态(面向形式设计)
        //将result->变为对象->枚举->关心可选项
        //关心 = 1,0,-1->枚举->对象->代码阅读可读性高
        //检测数据库返回值
        try check(result)
        
        
        //第六步:定义队列->并行队列
        //主队列:串行队列
        //设置队列值(缓存当前Connaction所在的队列)
        queue.setSpecific(key: queueKey, value: queueContext)
    }
    
    //第二个默认构造方法
    //第二个构造方法调用第一个构造方法
    //普及一个语法->遍历构造器
    public convenience init(_ filename: String, readonly: Bool = false) throws {
        try self.init(.uri(filename), readonly: readonly)
    }
    
    
    //第五步:检测数据库结果
    //检测是否成功,还是失败
    //resultCode->数据库返回结果
    //throws->向外抛异常->客户端处理异常
    //大家都是用代码,很少自己写(成长很少)
    //第一次接触,蒙蔽很正常
    //相当于异常传递->事件传递
    @discardableResult func check(_ resultCode: Int32) throws -> Int32 {
        guard let error = Result(errorCode: resultCode, connection: self) else {
            return resultCode
        }
        //失败了->数据库打开失败了
        //抛异常(我不处理异常)
        throw error
    }
    
    
//    第六步:创建数据库执行队列
//    数据库所有表操作->什么样队列中执行
//    串行队列->一个个排队执行(线下买票)
//    并行队列->同时执行(网上购票)
//    问题:什么时候串行队列、什么时候并行队列?
//    挖个坑?后面我们在讨论?
    //课后记得复习
    //注意:这个队列执行一个操作->方法->闭包->执行闭包(核心:还是方法)->代码块
    //同步代码块->主线程执行的
    //方法泛型
    //代码块动态
    //串行队列定义:DispatchQueue(label: "database")
    //并行队列定义(加了一个attributes):DispatchQueue(label: "database", attributes: [])
    //百度搜索查看并行队列参数
    fileprivate var queue = DispatchQueue(label: "database", attributes: [])
    //根据key获取值
    fileprivate var queueKey = DispatchSpecificKey<Int>()
    //当前Connection指针->将Connection类对象引用->转为Int类型指针(引用)->强制类型转换
    //根据这个指针判定当前是串行队列,还是并行队列
    fileprivate lazy var queueContext: Int = unsafeBitCast(self, to: Int.self)
    func sync<T>(_ block: () throws -> T) rethrows -> T {
        //定义队列
        if DispatchQueue.getSpecific(key: queueKey) == queueContext {
            //串行队列->直接执行->主队列->排队执行
            return try block()
        } else {
            //并行队列->子队列->指通过queue管理执行,同时执行
            return try queue.sync(execute: block)
        }
    }
    
    
    //第七步:执行SQL语句
    func execute(_ SQL: String) throws {
        //同步代码块
        //"_"表示返回变量名接受"_"默认->变量通配符->没有类型
        _ = try sync {
            try self.check(sqlite3_exec(self._handle, SQL, nil, nil, nil))
        }
    }
    
    
//    第八步:定义数据库基本操作属性
//    1、关闭数据库
    deinit {
        //析构函数
        sqlite3_close(_handle)
    }
//    2、数据库状态->是否是可读性数据库
    public var readonly: Bool {
        return sqlite3_db_readonly(_handle, nil) == 1
    }
//    3、最后插入的一条数据所返回的行id->rowid
    public var lastInsertRowId: Int64 {
        return sqlite3_last_insert_rowid(_handle)
    }
//    4、数据库受影响行数->changes
    public var changes: Int {
        return Int(sqlite3_changes(_handle))
    }
//    5、数据库自从打开到目前为止数据库受影响行数
//    insert、delete、update总共操作几次
//    insert->10次(插入10条数据)
//    delete->删除5条->干坏事5次
//    update->更新2次->干坏事2次
//    总共:到目前为止17次
    public var totalChanges: Int {
        return Int(sqlite3_total_changes(_handle))
    }
//    6、中断任何长时间运行的查询操作(客户端少见)
//    服务器开发->我开发服务器->100万数量级->耗费时间长
    public func interrupt(){
        sqlite3_interrupt(_handle)
    }
//    7、数据库超时
    public var busyTimeout: Double = 0 {
        didSet{
            sqlite3_busy_timeout(_handle, Int32(busyTimeout * 1_000))
        }
    }
    
}


extension Connection.Location : CustomStringConvertible {
    
    //数据库位置
    public var description: String {
        switch self {
        case .inMemory:
            return ":memory"
        case .temporary:
            return ""
        case .uri(let URI):
            return URI
        }
    }
    
}


//定义Result枚举类
//普及:枚举泛型
public enum Result : Error {
    
    //SQLITE_OK->执行成功
    //SQLITE_ROW->执行下一行(成功)
    //SQLITE_DONE->执行完成
    fileprivate static let successCodes: Set = [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]
    
    case error(message: String, code: Int32)
    
    //errorCode->数据库返回结果
    init?(errorCode: Int32, connection: Connection){
        guard !Result.successCodes.contains(errorCode) else {
            return nil
        }
        //获取错误信息(封装数据库错误信息)
        let message = String(cString: sqlite3_errmsg(connection._handle))
        //初始化error信息
        self = .error(message: message, code: errorCode)
    }
    
}

调用

  let path = Bundle.main.path(forResource: "test", ofType: ".db")
        print(path!)
        let db = try! Connection(path!)
        try! db.execute("create table t_teacher(name text, email text)")

相关文章

  • 数据库连接-静态构建表

    静态构建表-指手动创建数据库,自己写sql代码 第一步:新建一个Connection类?作用:管理我们数据库功能:...

  • 数据库设计

    数据库连接 表结构

  • 数据库左连接、右连接、内连接+全连接

    声明:本文参考:数据库左连接、右连接、内连接、全连接笔记 1、新建表 表 table_a 表 table_b 2、...

  • 数据库的表连接

    数据库中的表连接包括三种:内连接、外连接、交叉连接 t1(表): t2(表): 内连接(inner join) 查...

  • 2018-07-12 SSH连接远程服务器、MySQL数据库

    SSH连接远程服务器 连接数据库: 查看数据库: 选择数据库: 查看数据表: 查看数据表结构: 查看数据库: ex...

  • mongodb基本命令

    连接数据库 显示所有数据库 使用数据库 查看表 插入数据 查询表数据 修改表数据 删除表数据 删除表 删除数据库

  • python 教程笔记day10

    Python3 MySQL 数据库连接 数据库连接 创建数据库表 数据库插入操作 数据库查询操作 数据库更新操作 ...

  • Laravel数据库操作之-DB facade

    数据库操作之-DB facade 新建数据表与连接数据库 使用DB facade实现CURD 创建数据表 连接数据...

  • Mysql

    mysql 基础语法 // 数据库 表 insert select update delete 连接查询 内连接:...

  • 数据库笔记-SQL表连接

    表操作 创建表 修改表 添加列 删除列 删除表 表连接 关系型数据库,一个表就是数据之间的关系,而表与表的关系连接...

网友评论

    本文标题:数据库连接-静态构建表

    本文链接:https://www.haomeiwen.com/subject/yjflbqtx.html