在Swift中访问SQLite数据库

时间:2014-06-08 03:39:45

标签: sqlite swift

我正在寻找一种使用Swift代码在我的应用中访问SQLite数据库的方法。

我知道我可以在Objective C中使用SQLite Wrapper并使用桥接头,但我完全可以在Swift中完成这个项目。有没有办法做到这一点,如果是这样,有人可以指向我一个显示如何提交查询,检索行等的参考?

12 个答案:

答案 0 :(得分:128)

虽然你应该使用众多SQLite包装器中的一个(我更喜欢自己FMDB),如果你想知道如何自己调用SQLite库,你会:

  1. 配置Swift项目以处理SQLite C调用。如果使用Xcode 9,您只需执行以下操作:

    import SQLite3
    

    在早期版本的Xcode中,您可以:

    • 为项目创建桥接头文件。请参阅Using Swift with Cocoa and Objective-C中的将Objective-C导入Swift 部分。此桥接标头应导入sqlite3.h

      #import <sqlite3.h>
      
    • libsqlite3.tbd(或更旧的版本,libsqlite3.dylib)添加到您的项目中:

      enter image description here

  2. 创建/打开数据库。

    let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
        .appendingPathComponent("test.sqlite")
    
    // open database
    
    var db: OpaquePointer?
    if sqlite3_open(fileURL.path, &db) != SQLITE_OK {
        print("error opening database")
    }
    
  3. 使用sqlite3_exec执行SQL(例如创建表格)。

    if sqlite3_exec(db, "create table if not exists test (id integer primary key autoincrement, name text)", nil, nil, nil) != SQLITE_OK {
        let errmsg = String(cString: sqlite3_errmsg(db)!)
        print("error creating table: \(errmsg)")
    }
    
  4. 使用sqlite3_prepare_v2?占位符准备SQL,我们将绑定值。

    var statement: OpaquePointer?
    
    if sqlite3_prepare_v2(db, "insert into test (name) values (?)", -1, &statement, nil) != SQLITE_OK {
        let errmsg = String(cString: sqlite3_errmsg(db)!)
        print("error preparing insert: \(errmsg)")
    }
    
    if sqlite3_bind_text(statement, 1, "foo", -1, SQLITE_TRANSIENT) != SQLITE_OK {
        let errmsg = String(cString: sqlite3_errmsg(db)!)
        print("failure binding foo: \(errmsg)")
    }
    
    if sqlite3_step(statement) != SQLITE_DONE {
        let errmsg = String(cString: sqlite3_errmsg(db)!)
        print("failure inserting foo: \(errmsg)")
    }
    

    注意,它使用SQLITE_TRANSIENT常量which can be implemented,如下所示:

    internal let SQLITE_STATIC = unsafeBitCast(0, to: sqlite3_destructor_type.self)
    internal let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
    
  5. 重置SQL以插入另一个值。在此示例中,我将插入NULL值:

    if sqlite3_reset(statement) != SQLITE_OK {
        let errmsg = String(cString: sqlite3_errmsg(db)!)
        print("error resetting prepared statement: \(errmsg)")
    }
    
    if sqlite3_bind_null(statement, 1) != SQLITE_OK {
        let errmsg = String(cString: sqlite3_errmsg(db)!)
        print("failure binding null: \(errmsg)")
    }
    
    if sqlite3_step(statement) != SQLITE_DONE {
        let errmsg = String(cString: sqlite3_errmsg(db)!)
        print("failure inserting null: \(errmsg)")
    }
    
  6. 完成预准备语句以恢复与该预准备语句关联的内存:

    if sqlite3_finalize(statement) != SQLITE_OK {
        let errmsg = String(cString: sqlite3_errmsg(db)!)
        print("error finalizing prepared statement: \(errmsg)")
    }
    
    statement = nil
    
  7. 准备新的语句,用于从表中选择值并循环检索值:

    if sqlite3_prepare_v2(db, "select id, name from test", -1, &statement, nil) != SQLITE_OK {
        let errmsg = String(cString: sqlite3_errmsg(db)!)
        print("error preparing select: \(errmsg)")
    }
    
    while sqlite3_step(statement) == SQLITE_ROW {
        let id = sqlite3_column_int64(statement, 0)
        print("id = \(id); ", terminator: "")
    
        if let cString = sqlite3_column_text(statement, 1) {
            let name = String(cString: cString)
            print("name = \(name)")
        } else {
            print("name not found")
        }
    }
    
    if sqlite3_finalize(statement) != SQLITE_OK {
        let errmsg = String(cString: sqlite3_errmsg(db)!)
        print("error finalizing prepared statement: \(errmsg)")
    }
    
    statement = nil
    
  8. 关闭数据库:

    if sqlite3_close(db) != SQLITE_OK {
        print("error closing database")
    }
    
    db = nil
    
  9. 对于Swift 2,请参阅previous revision of this answer

答案 1 :(得分:17)

您可以做的最好的事情是在桥接标头中导入动态库:

  1. 将libsqlite3.dylib添加到您的&#34; Link Binary With Libraries&#34;构建阶段
  2. 创建一个&#34; Bridging-Header.h&#34;并将#import <sqlite3.h>添加到顶部
  3. set&#34; Bridging-Header.h&#34;用于&#34; Objective-C桥接标题&#34;在&#34; Swift编译器 - 代码生成&#34;
  4. 下的构建设置中进行设置

    然后,您就可以从swift代码中访问所有c方法,例如sqlite3_open

    但是,您可能只想使用FMDB并通过桥接头导入它,因为这是一个更面向对象的sqlite包装器。在Swift中处理C指针和结构将很麻烦。

答案 2 :(得分:11)

我也在寻找与SQLite交互的方式,就像我之前在Objective-C中所做的那样。不可否认,由于C兼容性,我只使用了直接的C API。

由于Swift中SQLite当前不存在包装器,并且上面提到的SQLiteDB代码更高级并假设使用了一些,我决定创建一个包装器并在此过程中熟悉Swift。您可以在此处找到它:https://github.com/chrismsimpson/SwiftSQLite

var db = SQLiteDatabase();
db.open("/path/to/database.sqlite");

var statement = SQLiteStatement(database: db);

if ( statement.prepare("SELECT * FROM tableName WHERE Id = ?") != .Ok )
{
    /* handle error */
}

statement.bindInt(1, value: 123);

if ( statement.step() == .Row )
{
    /* do something with statement */
    var id:Int = statement.getIntAt(0)
    var stringValue:String? = statement.getStringAt(1)
    var boolValue:Bool = statement.getBoolAt(2)
    var dateValue:NSDate? = statement.getDateAt(3)
}

statement.finalizeStatement(); /* not called finalize() due to destructor/language keyword */

答案 3 :(得分:4)

我创建了一个优雅的SQLite库,完全用Swift编写,名为SwiftData

它的一些功能是:

  • 将对象方便地绑定到SQL
  • 字符串
  • 支持交易和保存点
  • 内联错误处理
  • 默认情况下完全线程安全

它提供了一种执行“更改”的简便方法(例如INSERT,UPDATE,DELETE等):

if let err = SD.executeChange("INSERT INTO Cities (Name, Population, IsWarm, FoundedIn) VALUES ('Toronto', 2615060, 0, '1793-08-27')") {
    //there was an error during the insert, handle it here
} else {
    //no error, the row was inserted successfully
}

和'queries'(例如SELECT):

let (resultSet, err) = SD.executeQuery("SELECT * FROM Cities")
if err != nil {
    //there was an error during the query, handle it here
} else {
    for row in resultSet {
        if let name = row["Name"].asString() {
            println("The City name is: \(name)")
        }
        if let population = row["Population"].asInt() {
            println("The population is: \(population)")
        }
        if let isWarm = row["IsWarm"].asBool() {
            if isWarm {
                println("The city is warm")
            } else {
                println("The city is cold")
            }
        }
        if let foundedIn = row["FoundedIn"].asDate() {
            println("The city was founded in: \(foundedIn)")
        }
    }
}

还有更多功能!

您可以查看here

答案 4 :(得分:2)

Swift 2和Swift 3的另一个SQLite包装器:http://github.com/groue/GRDB.swift

特点:

  • ccgus/fmdb

  • 的用户看起来很熟悉的API
  • 利用Swift标准库的低级SQLite API

  • 适用于SQL过敏开发者的漂亮Swift查询界面

  • 支持SQLite WAL模式和并发数据库访问以获得额外性能

  • 一个记录类,它包装结果集,吃早餐的自定义SQL查询,并提供基本的CRUD操作

  • Swift类型自由:选择适合您数据的Swift类型。需要时使用Int64,或坚持使用方便的Int。存储和读取NSDate或NSDateComponents。为离散数据类型声明Swift枚举。定义您自己的数据库可转换类型。

  • 数据库迁移

  • 速度:https://github.com/groue/GRDB.swift/wiki/Performance

答案 5 :(得分:2)

AppDelegate.swift

func createDatabase()
{
    var path:Array=NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
    let directory:String=path[0]
    let DBpath=(directory as NSString).appendingPathComponent("Food.sqlite")

    print(DBpath)

    if (FileManager.default.fileExists(atPath: DBpath))
    {
        print("Successfull database create")
    }
    else
    {
        let pathfrom:String=(Bundle.main.resourcePath! as NSString).appendingPathComponent("Food.sqlite")

        var success:Bool
        do {
            try FileManager.default.copyItem(atPath: pathfrom, toPath: DBpath)
            success = true
        } catch _ {
            success = false
        }

        if !success
        {
            print("database not create ")
        }
        else
        {
            print("Successfull database new create")
        }
    }
}

Database.swift

import UIKit

class database: NSObject
{
func databasePath() -> NSString
{
    var path:Array=NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
    let directory:String=path[0] 
    let DBpath=(directory as NSString).appendingPathComponent("Food.sqlite")

    if (FileManager.default.fileExists(atPath: DBpath))
    {
        return DBpath as NSString
    }
    return DBpath as NSString
}

func ExecuteQuery(_ str:String) -> Bool
{
    var result:Bool=false
    let DBpath:String=self.databasePath() as String

    var db: OpaquePointer? = nil
    var stmt:OpaquePointer? = nil

    let strExec=str.cString(using: String.Encoding.utf8)

    if (sqlite3_open(DBpath, &db)==SQLITE_OK)
    {
        if (sqlite3_prepare_v2(db, strExec! , -1, &stmt, nil) == SQLITE_OK)
        {
            if (sqlite3_step(stmt) == SQLITE_DONE)
            {
                result=true
            } 
        }
        sqlite3_finalize(stmt)
    }
    sqlite3_close(db)

    return result
}

func SelectQuery(_ str:String) -> Array<Dictionary<String,String>>
{
    var result:Array<Dictionary<String,String>>=[]
    let DBpath:String=self.databasePath() as String

    var db: OpaquePointer? = nil
    var stmt:OpaquePointer? = nil

    let strExec=str.cString(using: String.Encoding.utf8)

    if ( sqlite3_open(DBpath,&db) == SQLITE_OK)
    {
        if (sqlite3_prepare_v2(db, strExec! , -1, &stmt, nil) == SQLITE_OK)
        {
            while (sqlite3_step(stmt) == SQLITE_ROW)
            {
                var i:Int32=0
                let icount:Int32=sqlite3_column_count(stmt)

                var dict=Dictionary<String, String>()

                while i < icount
                {
                    let strF=sqlite3_column_name(stmt, i)
                    let strV = sqlite3_column_text(stmt, i)

                    let rFiled:String=String(cString: strF!)
                    let rValue:String=String(cString: strV!)
                    //let rValue=String(cString: UnsafePointer<Int8>(strV!))

                    dict[rFiled] = rValue

                    i += 1
                }
                result.insert(dict, at: result.count)
            }
        sqlite3_finalize(stmt)
        }

    sqlite3_close(db)
    }
    return result
}

func AllSelectQuery(_ str:String) -> Array<Model>
{
    var result:Array<Model>=[]
    let DBpath:String=self.databasePath() as String

    var db: OpaquePointer? = nil
    var stmt:OpaquePointer? = nil

    let strExec=str.cString(using: String.Encoding.utf8)

    if ( sqlite3_open(DBpath,&db) == SQLITE_OK)
    {
        if (sqlite3_prepare_v2(db, strExec! , -1, &stmt, nil) == SQLITE_OK)
        {
            while (sqlite3_step(stmt) == SQLITE_ROW)
            {
                let mod=Model()

                mod.id=String(cString: sqlite3_column_text(stmt, 0))
                mod.image=String(cString: sqlite3_column_text(stmt, 1))
                mod.name=String(cString: sqlite3_column_text(stmt, 2))
                mod.foodtype=String(cString: sqlite3_column_text(stmt, 3))
                mod.vegtype=String(cString: sqlite3_column_text(stmt, 4))
                mod.details=String(cString: sqlite3_column_text(stmt, 5))

                result.insert(mod, at: result.count)
            }
            sqlite3_finalize(stmt)
        }
        sqlite3_close(db)
    }
    return result
}

}

Model.swift

import UIKit


class Model: NSObject
{
var uid:Int = 0
var id:String = ""
var image:String = ""
var name:String = ""
var foodtype:String = ""
var vegtype:String = ""
var details:String = ""
var mealtype:String = ""
var date:String = ""
}

访问数据库:

let DB=database()
var mod=Model()

数据库查询:

var DailyResult:Array<Model> = DB.AllSelectQuery("select * from food where foodtype == 'Sea Food' ORDER BY name ASC")

答案 6 :(得分:0)

我写过a SQLite3 wrapper library written in Swift

这实际上是一个非常高级的包装器,具有非常简单的API,但无论如何,它具有低级别的C语言间操作代码,我在这里发布了一个(简化的)部分来显示C inter-op。 / p>

    struct C
    {
        static let  NULL        =   COpaquePointer.null()
    }

    func open(filename:String, flags:OpenFlag)
    {
        let name2   =   filename.cStringUsingEncoding(NSUTF8StringEncoding)!
        let r       =   sqlite3_open_v2(name2, &_rawptr, flags.value, UnsafePointer<Int8>.null())
        checkNoErrorWith(resultCode: r)
    }

    func close()
    {   
        let r   =   sqlite3_close(_rawptr)
        checkNoErrorWith(resultCode: r)
        _rawptr =   C.NULL
    }

    func prepare(SQL:String) -> (statements:[Core.Statement], tail:String)
    {
        func once(zSql:UnsafePointer<Int8>, len:Int32, inout zTail:UnsafePointer<Int8>) -> Core.Statement?
        {
            var pStmt   =   C.NULL
            let r       =   sqlite3_prepare_v2(_rawptr, zSql, len, &pStmt, &zTail)
            checkNoErrorWith(resultCode: r)

            if pStmt == C.NULL
            {
                return  nil
            }
            return  Core.Statement(database: self, pointerToRawCStatementObject: pStmt)
        }

        var stmts:[Core.Statement]  =   []
        let sql2    =   SQL as NSString
        var zSql    =   UnsafePointer<Int8>(sql2.UTF8String)
        var zTail   =   UnsafePointer<Int8>.null()
        var len1    =   sql2.lengthOfBytesUsingEncoding(NSUTF8StringEncoding);
        var maxlen2 =   Int32(len1)+1

        while let one = once(zSql, maxlen2, &zTail)
        {
            stmts.append(one)
            zSql    =   zTail
        }

        let rest1   =   String.fromCString(zTail)
        let rest2   =   rest1 == nil ? "" : rest1!

        return  (stmts, rest2)
    }

    func step() -> Bool
    {   
        let rc1 =   sqlite3_step(_rawptr)

        switch rc1
        {   
            case SQLITE_ROW:
                return  true

            case SQLITE_DONE:
                return  false

            default:
                database.checkNoErrorWith(resultCode: rc1)
        }
    }

    func columnText(at index:Int32) -> String
    {
        let bc  =   sqlite3_column_bytes(_rawptr, Int32(index))
        let cs  =   sqlite3_column_text(_rawptr, Int32(index))

        let s1  =   bc == 0 ? "" : String.fromCString(UnsafePointer<CChar>(cs))!
        return  s1
    }

    func finalize()
    {
        let r   =   sqlite3_finalize(_rawptr)
        database.checkNoErrorWith(resultCode: r)

        _rawptr =   C.NULL
    }

如果您需要此低级包装器的完整源代码,请参阅这些文件。

答案 7 :(得分:0)

配置Swift项目以处理SQLite C调用:

  

为项目创建桥接头文件。请参阅使用Swift with Cocoa和Objective-C将Importing-C导入到Swift部分。这个桥接头应该导入sqlite3.h:

     

将libsqlite3.0.dylib添加到项目中。请参阅Apple关于将库/框架添加到某个项目的文档。

并使用以下代码

    func executeQuery(query: NSString ) -> Int
    {
        if  sqlite3_open(databasePath! as String, &database) != SQLITE_OK
        {
            println("Databse is not open")
            return 0
        }
        else
        {
            query.stringByReplacingOccurrencesOfString("null", withString: "")
            var cStatement:COpaquePointer = nil
            var executeSql = query as NSString
            var lastId : Int?
            var sqlStatement = executeSql.cStringUsingEncoding(NSUTF8StringEncoding)
            sqlite3_prepare_v2(database, sqlStatement, -1, &cStatement, nil)
            var execute = sqlite3_step(cStatement)
            println("\(execute)")
            if execute == SQLITE_DONE
            {
                lastId = Int(sqlite3_last_insert_rowid(database))
            }
            else
            {
                println("Error in Run Statement :- \(sqlite3_errmsg16(database))")
            }
            sqlite3_finalize(cStatement)
            return lastId!
        }
    }
    func ViewAllData(query: NSString, error: NSError) -> NSArray
    {
        var cStatement = COpaquePointer()
        var result : AnyObject = NSNull()
        var thisArray : NSMutableArray = NSMutableArray(capacity: 4)
        cStatement = prepare(query)
        if cStatement != nil
        {
            while sqlite3_step(cStatement) == SQLITE_ROW
            {
                result = NSNull()
                var thisDict : NSMutableDictionary = NSMutableDictionary(capacity: 4)
                for var i = 0 ; i < Int(sqlite3_column_count(cStatement)) ; i++
                {
                    if sqlite3_column_type(cStatement, Int32(i)) == 0
                    {
                        continue
                    }
                    if sqlite3_column_decltype(cStatement, Int32(i)) != nil && strcasecmp(sqlite3_column_decltype(cStatement, Int32(i)), "Boolean") == 0
                    {
                        var temp = sqlite3_column_int(cStatement, Int32(i))
                        if temp == 0
                        {
                            result = NSNumber(bool : false)
                        }
                        else
                        {
                            result = NSNumber(bool : true)
                        }
                    }
                    else if sqlite3_column_type(cStatement,Int32(i)) == SQLITE_INTEGER
                    {
                        var temp = sqlite3_column_int(cStatement,Int32(i))
                        result = NSNumber(int : temp)
                    }
                    else if sqlite3_column_type(cStatement,Int32(i)) == SQLITE_FLOAT
                    {
                        var temp = sqlite3_column_double(cStatement,Int32(i))
                        result = NSNumber(double: temp)
                    }
                    else
                    {
                        if sqlite3_column_text(cStatement, Int32(i)) != nil
                        {
                            var temp = sqlite3_column_text(cStatement,Int32(i))
                            result = String.fromCString(UnsafePointer<CChar>(temp))!

                            var keyString = sqlite3_column_name(cStatement,Int32(i))
                            thisDict.setObject(result, forKey: String.fromCString(UnsafePointer<CChar>(keyString))!)
                        }
                        result = NSNull()

                    }
                    if result as! NSObject != NSNull()
                    {
                        var keyString = sqlite3_column_name(cStatement,Int32(i))
                        thisDict.setObject(result, forKey: String.fromCString(UnsafePointer<CChar>(keyString))!)
                    }
                }
                thisArray.addObject(NSMutableDictionary(dictionary: thisDict))
            }
            sqlite3_finalize(cStatement)
        }
        return thisArray
    }
    func prepare(sql : NSString) -> COpaquePointer
    {
        var cStatement:COpaquePointer = nil
        sqlite3_open(databasePath! as String, &database)
        var utfSql = sql.UTF8String
        if sqlite3_prepare(database, utfSql, -1, &cStatement, nil) == 0
        {
            sqlite3_close(database)
            return cStatement
        }
        else
        {
            sqlite3_close(database)
            return nil
        }
    }
}

答案 8 :(得分:0)

有时,"SQLite in 5 minutes or less"上显示的sqlite.org方法的Swift版本就足够了。  &#34; 5分钟或更短时间&#34;方法使用sqlite3_exec(),它是sqlite3_prepare()sqlite3_step()sqlite3_column()sqlite3_finalize()的便捷包装。

Swift 2.2可以直接支持sqlite3_exec() callback函数指针作为全局非实例过程func或非捕获文字闭包{}

可读typealias

typealias sqlite3 = COpaquePointer
typealias CCharHandle = UnsafeMutablePointer<UnsafeMutablePointer<CChar>>
typealias CCharPointer = UnsafeMutablePointer<CChar>
typealias CVoidPointer = UnsafeMutablePointer<Void>

回调方法

func callback(
    resultVoidPointer: CVoidPointer, // void *NotUsed 
    columnCount: CInt,               // int argc
    values: CCharHandle,             // char **argv     
    columns: CCharHandle             // char **azColName
    ) -> CInt {
    for  i in 0 ..< Int(columnCount) {
        guard let value = String.fromCString(values[i]) 
        else { continue }
        guard let column = String.fromCString(columns[i]) 
        else { continue }
        print("\(column) = \(value)")
    }
    return 0 // status ok
}

func sqlQueryCallbackBasic(argc: Int, argv: [String]) -> Int {
    var db: sqlite3 = nil 
    var zErrMsg:CCharPointer = nil
    var rc: Int32 = 0 // result code

    if argc != 3 {
        print(String(format: "ERROR: Usage: %s DATABASE SQL-STATEMENT", argv[0]))
        return 1
    }

    rc = sqlite3_open(argv[1], &db)
    if  rc != 0 {
        print("ERROR: sqlite3_open " + String.fromCString(sqlite3_errmsg(db))! ?? "" )
        sqlite3_close(db)
        return 1
    }

    rc = sqlite3_exec(db, argv[2], callback, nil, &zErrMsg)
    if rc != SQLITE_OK {
        print("ERROR: sqlite3_exec " + String.fromCString(zErrMsg)! ?? "")
        sqlite3_free(zErrMsg)
    }

    sqlite3_close(db)
    return 0
}

关闭方法

func sqlQueryClosureBasic(argc argc: Int, argv: [String]) -> Int {
    var db: sqlite3 = nil 
    var zErrMsg:CCharPointer = nil
    var rc: Int32 = 0

    if argc != 3 {
        print(String(format: "ERROR: Usage: %s DATABASE SQL-STATEMENT", argv[0]))
        return 1
    }

    rc = sqlite3_open(argv[1], &db)
    if  rc != 0 {
        print("ERROR: sqlite3_open " + String.fromCString(sqlite3_errmsg(db))! ?? "" )
        sqlite3_close(db)
        return 1
    }

    rc = sqlite3_exec(
        db,      // database 
        argv[2], // statement
        {        // callback: non-capturing closure
            resultVoidPointer, columnCount, values, columns in

            for i in 0 ..< Int(columnCount) {
                guard let value = String.fromCString(values[i]) 
                else { continue }
                guard let column = String.fromCString(columns[i]) 
                else { continue }
                print("\(column) = \(value)")
            }
            return 0
        }, 
        nil, 
        &zErrMsg
    )

    if rc != SQLITE_OK {
        let errorMsg = String.fromCString(zErrMsg)! ?? ""
        print("ERROR: sqlite3_exec \(errorMsg)")
        sqlite3_free(zErrMsg)
    }
    sqlite3_close(db)
    return 0
}

要准备一个Xcode项目来调用诸如SQLite之类的C库,需要(1)添加一个Bridging-Header.h文件引用C头像#import "sqlite3.h",(2)添加Bridging-Header.h在项目设置中 Objective-C Bridging Header ,以及(3)将libsqlite3.tbd添加到 Link Binary With Library 目标设置。

sqlite.org"SQLite in 5 minutes or less"示例是在Swift Xcode7项目here中实现的。

答案 9 :(得分:0)

你也可以使用单一类来轻松配置SQLite。

<强>参见

https://github.com/hasyapanchasara/SQLite_SingleManagerClass

创建数据库的方法

func methodToCreateDatabase() -> NSURL?{} 

插入,更新和删除数据的方法

func methodToInsertUpdateDeleteData(strQuery : String) -> Bool{}

选择数据的方法

func methodToSelectData(strQuery : String) -> NSMutableArray{}

答案 10 :(得分:0)

您可以在Swift for SQLite中使用此库 https://github.com/pmurphyjam/SQLiteDemo

SQLiteDemo

使用Swift编写的SQLite Demo与使用Swift编写的SQLDataAccess类

添加到您的项目

您只需要将三个文件添加到项目中 * SQLDataAccess.swift * DataConstants.swift * Bridging-Header.h   必须在Xcode的项目'Swift Compiler - General'下的'Objective-C Bridging Header'中设置Bridging-Header

使用示例

只需按照ViewController.swift中的代码查看如何使用SQLDataAccess.swift编写简单的SQL 首先,您需要打开处理

的SQLite数据库
```swift
let db = SQLDataAccess.shared
db.setDBName(name:"SQLite.db")
let opened = db.openConnection(copyFile:true)
```

如果openConnection成功,现在您可以在表AppInfo

中进行简单的插入
```swift
//Insert into Table AppInfo
let status = db.executeStatement("insert into AppInfo (name,value,descrip,date) values(?,?,?,?)",
”SQLiteDemo","1.0.2","unencrypted",Date())
if(status)
{
    //Read Table AppInfo into an Array of Dictionaries
    let results = db.getRecordsForQuery("select * from AppInfo ")
    NSLog("Results = \(results)")
}
```

看看有多简单!

db.executeStatement中的第一个术语是SQL as String,后面的所有术语都是Any类型的可变参数列表,并且是数组中的参数。所有这些术语在SQL参数列表中用逗号分隔。您可以在续集声明之后输入字符串,整数,日期和Blob,因为所有这些术语都被认为是续集的参数。可变参数数组只是方便您在一个executeStatement或getRecordsForQuery调用中输入所有续集。如果您没有任何参数,请不要在SQL之后输入任何内容。

结果数组是一个Dictionary字典数组,其中'key'是表的列名,'value'是从SQLite获得的数据。您可以使用for循环轻松遍历此数组或直接将其打印出来,或将这些Dictionary元素分配给您在View Controllers中用于模型消费的自定义数据对象类。

```swift
for dic in results as! [[String:AnyObject]] {
   print(“result = \(dic)”)
}


```

SQLDataAccess将存储,文本,双精度,浮点数,blob,日期,整数和长整数。 对于Blob,您可以存储binary,varbinary,blob。

对于Text,您可以存储char,character,clob,国家变化字符,本机字符,nchar,nvarchar,varchar,变体,变化字符,文本。

对于日期,您可以存储日期时间,时间,时间戳,日期。

对于整数,你可以存储bigint,bit,bool,boolean,int2,int8,integer,mediumint,smallint,tinyint,int。

对于双打,你可以存储十进制,双精度,浮点数,数字,真实,双精度。双精度最高。

您甚至可以存储Null类型的Null。

在ViewController.swift中,一个更复杂的例子展示了如何将Dictionary作为'Blob'插入。另外还有SQLDataAccess 了解原生Swift Date(),因此您可以插入这些对象而不进行转换,并将它们转换为文本并存储它们, 检索时将它们从文本转换回日期。

当然,SQLite的真正威力在于它的交易能力。在这里,您可以使用参数排队400个SQL语句 并将它们全部插入,这非常强大,因为它非常快。 ViewController.swift还向您展示了如何执行此操作的示例。 所有你真正要做的就是创建一个名为'sqlAndParams'的字典数组,在这个数组中你存储有两个键的字典 字符串续集语句或查询的'SQL'和'PARAMS',它只是SQLite对该查询理解的本机对象数组。 每个'sqlParams'是一个单独的续集查询字典和参数,然后存储在'sqlAndParams'数组中。 创建此数组后,只需调用。

```swift
let status = db.executeTransaction(sqlAndParams)
if(status)
{
    //Read Table AppInfo into an Array of Dictionaries for the above Transactions
    let results = db.getRecordsForQuery("select * from AppInfo ")
    NSLog("Results = \(results)")
}
```

此外,所有executeStatement和getRecordsForQuery方法都可以使用简单的String for SQL查询和一个数组来完成查询所需的参数。

```swift
let sql : String = "insert into AppInfo (name,value,descrip) values(?,?,?)"
let params : Array = ["SQLiteDemo","1.0.0","unencrypted"]
let status = db.executeStatement(sql, withParameters: params)
if(status)
{
    //Read Table AppInfo into an Array of Dictionaries for the above Transactions
    let results = db.getRecordsForQuery("select * from AppInfo ")
    NSLog("Results = \(results)")
}
```

Objective-C版本也存在并被称为相同的SQLDataAccess,所以现在您可以选择在Objective-C或Swift中编写续集。 此外,SQLDataAccess也可以与SQLCipher一起使用,目前的代码还没有设置好使用它,但它很容易做到,并且 一个如何执行此操作的示例实际上是在SQLDataAccess的Objective-C版本中。

SQLDataAccess是一个非常快速和高效的类,可以用来代替CoreData,它实际上只使用SQLite作为底层数据 存储没有CoreData附带的所有CoreData核心数据完整性故障崩溃。

答案 11 :(得分:0)

到目前为止,这是我在Swift中使用过的最好的Sqlite库:https://github.com/stephencelis/SQLite.swift

查看代码示例。比C API干净得多:

import SQLite

let db = try Connection("path/to/db.sqlite3")

let users = Table("users")
let id = Expression<Int64>("id")
let name = Expression<String?>("name")
let email = Expression<String>("email")

try db.run(users.create { t in
    t.column(id, primaryKey: true)
    t.column(name)
    t.column(email, unique: true)
})
// CREATE TABLE "users" (
//     "id" INTEGER PRIMARY KEY NOT NULL,
//     "name" TEXT,
//     "email" TEXT NOT NULL UNIQUE
// )

let insert = users.insert(name <- "Alice", email <- "alice@mac.com")
let rowid = try db.run(insert)
// INSERT INTO "users" ("name", "email") VALUES ('Alice', 'alice@mac.com')

for user in try db.prepare(users) {
    print("id: \(user[id]), name: \(user[name]), email: \(user[email])")
    // id: 1, name: Optional("Alice"), email: alice@mac.com
}
// SELECT * FROM "users"

let alice = users.filter(id == rowid)

try db.run(alice.update(email <- email.replace("mac.com", with: "me.com")))
// UPDATE "users" SET "email" = replace("email", 'mac.com', 'me.com')
// WHERE ("id" = 1)

try db.run(alice.delete())
// DELETE FROM "users" WHERE ("id" = 1)

try db.scalar(users.count) // 0
// SELECT count(*) FROM "users"

文档还指出“ SQLite.swift还可以作为C API的轻量级,对Swift友好的包装器”,并附带一些示例。