Swift - SQLite でデータを更新 (UPDATE)

ここでは、Swift で SQLite のテーブルのデータを更新する方法をご説明します。

Swift - SQLite でデータを挿入 (INSERT)」のコードに、SQLite でデータを更新するコードを追加します。

students テーブルのデータを更新する関数を定義する

前回は次のような Student 構造体のデータを保持する SQLite の students テーブルにデータを挿入しました。

struct Student {
    var StudentID: Int
    var StudentNumber: String
    var FirstName: String
    var LastName: String
    var Age: Int?
    
    init(studentID: Int, studentNumber: String, firstName: String, lastName: String, age: Int?) {
        self.StudentID = studentID
        self.StudentNumber = studentNumber
        self.FirstName = firstName
        self.LastName = lastName
        self.Age = age
    }
}
CREATE TABLE IF NOT EXISTS students (
    student_id INTEGER NOT NULL PRIMARY KEY,
    student_number TEXT NOT NULL,
    first_name TEXT NULL,
    last_name TEXT NULL,
    age INTEGER NULL
);

今回は、Student オブジェクトを受け取り、students テーブルのデータを更新する updateStudent 関数を作ります。

DBService.swift ファイルを開き以下のコードを追加してください。

func updateStudent(student: Student) -> Bool {    
    let updateSql = """
    UPDATE  students
    SET     student_number = ?,
            first_name = ?,
            last_name = ?,
            age = ?
    WHERE   student_id = ?
    """
    var updateStmt: OpaquePointer? = nil
    
    if sqlite3_prepare_v2(db, (updateSql as NSString).utf8String, -1, &updateStmt, nil) != SQLITE_OK {
        print("db error: \(getDBErrorMessage(db))")
        return false
    }
    
    sqlite3_bind_text(updateStmt, 1, (student.StudentNumber as NSString).utf8String, -1, nil)
    sqlite3_bind_text(updateStmt, 2, (student.FirstName as NSString).utf8String, -1, nil)
    sqlite3_bind_text(updateStmt, 3, (student.LastName as NSString).utf8String, -1, nil)
    
    if student.Age == nil {
        sqlite3_bind_null(updateStmt, 4)
    } else {
        sqlite3_bind_int(updateStmt, 4, Int32(student.Age!))
    }
    
    sqlite3_bind_int(updateStmt, 5, Int32(student.StudentID))
    
    if sqlite3_step(updateStmt) != SQLITE_DONE {
        print("db error: \(getDBErrorMessage(db))")
        sqlite3_finalize(updateStmt)
        return false
    }
    sqlite3_finalize(updateStmt)
    return true
}

Swift - SQLite でデータを更新 (UPDATE) 1


入力引数の student の StudentID を持つレコードが students テーブルに存在している前提です。

updateStudent 関数のコードを順を追ってご説明します。

まず、2 ~ 9 行目で、SQLite の UPDATE 文のスクリプトを updateSql に定義しています。


SQLite で SQL 文を実行するには、その前にステートメントを準備用の関数をつかって、バイトコードプログラムにコンパイルする必要があります。

ここでは、sqlite3_prepare_v2() 関数を使って SQL 文をコンパイルしています。

int sqlite3_prepare_v2(
  sqlite3 *db,            /* Database handle */
  const char *zSql,       /* SQL statement, UTF-8 encoded */
  int nByte,              /* Maximum length of zSql in bytes. */
  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
  const char **pzTail     /* OUT: Pointer to unused portion of zSql */
);

10 行目で、sqlite3_prepare_v2() 関数に渡すステートメントハンドル用の OpaquePointer? 型の変数の updateStmt を定義しています。

12 行目で、sqlite3_prepare_v2() 関数に、データベースを開いた時に取得した db ハンドル、updateSql を UTF-8 に変換した文字列、上で定義した &updateStmt などを渡して実行しています。


sqlite3_prepare_v2() 関数 は成功したら SQLITE_OK を返し、失敗するとエラーコードを返します。

失敗した時には getDBErrorMessage() 関数を使ってエラーコードをプリントし、false を返しています。


17 ~ 27 行目では、上で準備したステートメントに、値をバインドしています。

文字列をバインドするには sqlite3_bind_text()、整数をバインドするには sqlite3_bind_int() のようにデータ型によって違う関数を使います。

17 行目では sqlite3_bind_text() を使って、updateSql 文のひとつ目の ? に student.StudentNumber を UTF-8 に変換してバインドしています。

同様に 18、19 行目では sqlite3_bind_text() を使って、二つ目と三つ目の ? に student.FirstName と student.LastName をバインドしています。

21 ~ 25 行目では、四つ目の ? に student.Age が null の時は sqlite3_bind_null() を使って null をバインドして、null 出ない時は sqlite3_bind_int() を使って student.Age をバインドしています。

27 行目では sqlite3_bind_int() を使って、五つ目の ? に student.StudentID を Int32 に変換してバインドしています。


29 ~ 33 行目では、sqlite3_step() 関数を使って、コンパイルした SQL文を評価して実行しています。

sqlite3_step() 関数は成功すると SQLITE_DONE を返します。

失敗した時は getDBErrorMessage() 関数を使ってエラーコードをプリントしています。

return する前に、sqlite3_finalize() 関数で、prepare したステートメントオブジェクトを destroy しています。


34、35 行目で、sqlite3_finalize() 関数で、prepare したステートメントオブジェクトを destroy してから true を返しています。


students テーブルのデータを更新する

それでは、作った updateStudent() 関数を使って、データを更新してみます。

前回、「Swift - SQLite でデータを挿入 (INSERT)」でインサートしたデータを更新します。


ViewController.swift の viewDidLoad() のコードを次のように変更してください。

var student1 = Student(studentID: 1, studentNumber: "S000001", firstName: "Yuta", lastName: "Tanaka", age: 16)
        
//        if DBService.shared.insertStudent(student: student1) {
//            print("Insert success")
//        } else {
//            print("Insert Failed")
//        }

student1.LastName = "Yamada"
student1.Age = 17

if DBService.shared.updateStudent(student: student1) {
    print("Update success")
} else {
    print("Update Failed")
}

9 ~ 10 行目で student1 の LastName と Age の値を変更しています。

12 ~ 16 行目では、先ほど作った関数 DBService.shared.updateStudent() に student1 を渡してデータを更新しています。


これを実行して、データの更新が成功すると、デバッガーのアウトプットコンソールに次のように表示されます。

Opened connection to database
Update success

Swift - SQLite でデータを更新 (UPDATE) 2


シミュレーターで実行して、DB Browser for SQLite でできた SQLite のファイルを開いて確認してみます。

SQLite のファイルの場所は「SQLite ファイルの場所を確認する方法」でご確認ください。

DB Browser for SQLite については後ほど別の記事でご紹介します。


students テーブルに入っていたデータが更新されています。

Swift で SQLite のテーブルを作成する 4

Swift - SQLite でデータを更新 (UPDATE) 3


以上、Swift で SQLite のテーブルのデータを更新する方法をご説明しました。

次は Swift で SQLite のデータを取得します。

次の記事 「Swift - SQLite でデータを取得 (SELECT)」

© 2024 iOS 開発入門