web-dev-qa-db-ja.com

SwiftのSQLiteデータベースへのアクセス

Swiftコードを使用して、アプリのSQLiteデータベースにアクセスする方法を探しています。

Objective CでSQLite Wrapperを使用し、ブリッジングヘッダーを使用できることは知っていますが、このプロジェクトを完全にSwiftで行うことができます。これを行う方法はありますか?もしそうであれば、誰かがクエリを送信する方法、行を取得する方法などを示す参照を私に指すことができますか?

99
Jase

おそらく多くのSQLiteラッパーの1つを使用する必要があります(私は FMDB を好みます)が、SQLiteライブラリを自分で呼び出す方法を知りたい場合は、次のようにします。

  1. Swiftプロジェクトを構成して、SQLite C呼び出しを処理します。 Xcode 9を使用している場合、次のことが簡単にできます。

    import SQLite3
    

    Xcodeの以前のバージョンでは、次のことができます。

    • プロジェクトへのブリッジングヘッダーファイルを作成します。 CocoaとObjective-CでのSwiftの使用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定数 実装可能 を使用していることに注意してください。

    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
    

Swift 2については、 この回答の以前のリビジョン を参照してください。

130
Rob

できる最善の方法は、ブリッジングヘッダー内に動的ライブラリをインポートすることです。

  1. Libsqlite3.dylibを「Link Binary With Libraries」ビルドフェーズに追加します
  2. 「Bridging-Header.h」を作成し、#import <sqlite3.h>を上部に追加します
  3. 「Swiftコンパイラ-コード生成」のビルド設定の「Objective-Cブリッジングヘッダー」設定に「Bridging-Header.h」を設定します

その後、Swiftコードからsqlite3_openなどのすべてのcメソッドにアクセスできるようになります。

ただし、単に FMDB を使用し、ブリッジヘッダーを介してインポートすることもできます。これは、sqliteのよりオブジェクト指向のラッパーです。 Swiftでは、Cのポインターと構造体を扱うのは面倒です。

18
drewag

私も、以前Objective-Cで行っていたのと同じ方法でSQLiteとやり取りする方法を探していました。確かに、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 */
11
Chris Simpson

SwiftData と呼ばれるSwiftで完全に記述されたエレガントなSQLiteライブラリを作成しました。

その機能の一部は次のとおりです。

  • オブジェクトを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
}

および「クエリ」(例: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)")
        }
    }
}

さらに多くの機能とともに!

あなたはそれをチェックアウトすることができます こちら

5
ryanfowler

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")
2
Jayesh Miruliya

Swift 2およびSwift 3:のさらに別のSQLiteラッパー3: http://github.com/groue/GRDB.Swift

特徴:

  • ccgus/fmdb のユーザーに馴染みのあるAPI

  • Swift標準ライブラリを活用する低レベルのSQLite API

  • SQLアレルギー開発者向けのかなりSwiftクエリインターフェイス

  • SQLite WALモードのサポート、および追加のパフォーマンスのための同時データベースアクセス

  • 結果セットをラップし、朝食にカスタムSQLクエリを処理し、基本的なCRUD操作を提供するRecordクラス

  • Swift型の自由度:データに適合する適切なSwift型を選択します。必要に応じてInt64を使用するか、便利なIntを使い続けます。 NSDateまたはNSDateComponentsを保存して読み取ります。離散データ型のSwift列挙型を宣言します。独自のデータベース変換可能な型を定義します。

  • データベースの移行

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

2
Gwendal Roué

時々、 sqlite.org に示されている "5分以内のSQLite" アプローチのSwiftバージョンで十分です。 「5分以内」のアプローチでは、sqlite3_exec()sqlite3_prepare()sqlite3_step()、およびsqlite3_column()の便利なラッパーであるsqlite3_finalize()を使用します。

Swift 2.2は、グローバルな非インスタンスプロシージャcallbackまたは非キャプチャリテラルクロージャ{}としてsqlite3_exec()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
}

SQLiteなどのCライブラリを呼び出すXcodeプロジェクトを準備するには、(1)#import "sqlite3.h"などのBridging-Header.hファイル参照Cヘッダーを追加するか、(2)Bridging-Header.hをプロジェクト設定のObjective-Cブリッジヘッダー、および(3)libsqlite3.tbdLink Binary with Libraryに追加ターゲット設定。

sqlite.org"5分以内のSQLite" の例は、Swift Xcode7プロジェクトに実装されています here

0
l --marc l

このライブラリは、SQLiteのSwiftで使用できます https://github.com/pmurphyjam/SQLiteDemo

SQLiteDemo

Swiftで記述されたSQLDataAccessクラスでSwiftを使用したSQLiteデモ

プロジェクトに追加する

プロジェクトに追加するのに必要なファイルは3つだけです* SQLDataAccess.Swift * DataConstants.Swift * Bridging-Header.h

使用例

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です。その後に続く用語はすべてAny型の可変引数リストであり、配列内のパラメーターです。これらすべての用語は、SQL引数のリスト内でコンマで区切られています。これらの用語はすべて続編のパラメーターと見なされるため、文字列、整数、日付、ブロブを続編ステートメントの直後に入力できます。可変引数の配列は、1つのexecuteStatementまたはgetRecordsForQuery呼び出しですべての続編を入力するのに便利です。パラメータがない場合は、SQLの後に何も入力しないでください。

結果の配列は辞書の配列で、「キー」はテーブルの列名、「値」はSQLiteから取得したデータです。 forループでこの配列を簡単に反復したり、直接印刷したり、モデルの消費のためにView Controllerで使用するカスタムデータオブジェクトクラスにこれらのDictionary要素を割り当てることができます。

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


```

SQLDataAccessは、text、double、float、blob、Date、integer、long long integerを保存します。 Blobには、バイナリ、varbinary、blobを保存できます。

テキストの場合、char、character、clob、各国の可変文字、ネイティブ文字、nchar、nvarchar、varchar、variant、variing character、textを保存できます。

日付には、日時、時刻、タイムスタンプ、日付を保存できます。

整数の場合、bigint、bit、bool、boolean、int2、int8、integer、mediumint、smallint、tinyint、intを格納できます。

Doubleの場合、10進数、倍精度、浮動小数点、数値、実数、倍精度を格納できます。 Doubleが最も精度が高くなります。

Null型のNullも保存できます。

ViewController.Swiftでは、より複雑な例が実行され、辞書を「Blob」として挿入する方法が示されています。さらに、SQLDataAccessはネイティブのSwift Date()を理解するため、これらのオブジェクトを変換せずに挿入でき、テキストに変換して保存し、取得時にテキストから日付に変換します。

もちろん、SQLiteの真の力はトランザクション機能です。ここでは、パラメーターを使用して文字通り400個のSQLステートメントをキューに入れ、それらをすべて一度に挿入できます。これは非常に高速であるため、非常に強力です。 ViewController.Swiftは、これを行う方法の例を示しています。あなたが本当にしているのは、「sqlAndParams」と呼ばれる辞書の配列を作成することです。この配列には、文字列の続きのステートメントまたはクエリ用の2つのキー「SQL」と、ネイティブオブジェクトの配列である「PARAMS」を含む辞書を格納しますそのクエリを理解します。その後、各クエリとパラメータの個別のディクショナリである各「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メソッドは、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の代わりに使用できます。CoreDataは、CoreDataに付属するすべてのCoreDataコアデータ整合性フォールトクラッシュなしでSQLiteを基礎データストアとして使用するだけです。

0
Frost

これは、私が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 <- "[email protected]")
let rowid = try db.run(insert)
// INSERT INTO "users" ("name", "email") VALUES ('Alice', '[email protected]')

for user in try db.prepare(users) {
    print("id: \(user[id]), name: \(user[name]), email: \(user[email])")
    // id: 1, name: Optional("Alice"), email: [email protected]
}
// 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の軽量でスウィフトフレンドリーなラッパーとしても機能する」と記載されており、その例をいくつか示します。

0
Andrew Koster

Swiftプロジェクトを構成して、SQLite C呼び出しを処理します。

プロジェクトへのブリッジングヘッダーファイルを作成します。 CocoaおよびObjective-CでSwiftを使用するのSwiftセクションへのObjective-Cのインポートを参照してください。このブリッジングヘッダーは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
        }
    }
}
0
chirag shah

シングルトンクラスを使用してSwiftでSQLiteを簡単に構成することもできます。

参照

https://github.com/hasyapanchasara/SQLite_SingleManagerClass

データベースの作成方法

func methodToCreateDatabase() -> NSURL?{} 

データを挿入、更新、削除する方法

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

データを選択する方法

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

Swiftで記述されたSQLite3ラッパーライブラリ と記述しました。

これは実際には非常に単純なAPIを備えた非常に高レベルのラッパーですが、とにかく、低レベルのC相互運用コードがあり、C相互運用を示すためにここに(簡略化した)部分を投稿します。

    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
    }

この低レベルラッパーの完全なソースコードが必要な場合は、これらのファイルを参照してください。

0
Eonil