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
}
入力引数の 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
シミュレーターで実行して、DB Browser for SQLite でできた SQLite のファイルを開いて確認してみます。
SQLite のファイルの場所は「SQLite ファイルの場所を確認する方法」でご確認ください。
DB Browser for SQLite については後ほど別の記事でご紹介します。
students テーブルに入っていたデータが更新されています。
以上、Swift で SQLite のテーブルのデータを更新する方法をご説明しました。
次は Swift で SQLite のデータを取得します。