Swift で SQLite のテーブルを作成する
ここでは、Swift で SQLite のテーブルを作成する方法をご説明します。
「Swift で SQLite データベースを作成して開く」のコードに、SQLite のテーブルを作成するコードを追加します。
次のような Student 構造体のデータを保持する SQLite のテーブルを作成します。
import Foundation
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
}
}
メニューから File > New > File... で [iOS] の[Swift File] を選択し、Student.swift という名前でファイルを作成し、上のコードを追加しておきます。
「Swift で SQLite データベースを作成して開く」では、DBService クラスのイニシャライザーで SQLite のデータベースを作って開き、db ハンドルを取得しました。
今回はその後に SQLite のテーブルを作成するコードを追加します。
DBService.swift ファイルを開き以下のコードを追加してください。
import Foundation
import SQLite3
final class DBService {
static let shared = DBService()
private let dbFile = "DBVer1.sqlite"
private var db: OpaquePointer?
private init() {
db = openDatabase()
if !createTable() {
print("Failed to create table")
}
}
private func openDatabase() -> OpaquePointer? {
let fileURL = try! FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false).appendingPathComponent(dbFile)
var db: OpaquePointer? = nil
if sqlite3_open(fileURL.path, &db) != SQLITE_OK {
print("Failed to open database")
return nil
}
else {
print("Opened connection to database")
return db
}
}
private func createTable() -> Bool {
let createSql = """
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
);
"""
var createStmt: OpaquePointer? = nil
if sqlite3_prepare_v2(db, (createSql as NSString).utf8String, -1, &createStmt, nil) != SQLITE_OK {
print("db error: \(getDBErrorMessage(db))")
return false
}
if sqlite3_step(createStmt) != SQLITE_DONE {
print("db error: \(getDBErrorMessage(db))")
sqlite3_finalize(createStmt)
return false
}
sqlite3_finalize(createStmt)
return true
}
private func getDBErrorMessage(_ db: OpaquePointer?) -> String {
if let err = sqlite3_errmsg(db) {
return String(cString: err)
} else {
return ""
}
}
}
コードを順を追ってご説明します。
12 行目のイニシャライザーの中で、createTable() 関数を呼んで、false を返した場合は、失敗したというメッセージをプリントしています。
34 ~ 63 行目で createTable() 関数を定義しています。
まず、35 ~ 43 行目で、SQLite の CREATE TABLE 文のスクリプトを createSql に定義しています。
CREATE TABLE IF NOT EXISTS で、students テーブルが存在しない時のみテーブルを作成するようにしています。
カラムは Student 構造体のあわせた名前と SQLite のデータ型を指定しています。
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 */
);
45 行目で、sqlite3_prepare_v2() 関数に渡すステートメントハンドル用の OpaquePointer? 型の変数の createStmt を定義しています。
47 行目で、sqlite3_prepare_v2() 関数に、データベースを開いた時に取得した db ハンドル、SQL文を UTF-8 に変換した文字列、上で定義した &createStmt などを渡して実行しています。
sqlite3_prepare_v2() 関数 は成功したら SQLITE_OK を返し、失敗するとエラーコードを返します。
失敗した時には getDBErrorMessage() 関数を使ってエラーコードをプリントし、false を返しています。
先に 62 ~ 68 行目の getDBErrorMessage() 関数を説明します。
エラーコードを取得するのに sqlite3_errmsg() 関数を使います。
sqlite3_errmsg() 関数は db ハンドルを受け取り 最後に失敗した API コールのエラーメッセージを返す関数です。
getDBErrorMessage() 関数では sqlite3_errmsg() 関数を使って、エラーメッセージを取得し、それを元に Swift の String を生成して返しています。
元に戻って、52 ~ 56 行目では、sqlite3_step() 関数を使って、コンパイルした SQL文を評価して実行しています。
sqlite3_step() 関数は成功すると SQLITE_DONE を返します。
失敗した時は getDBErrorMessage() 関数を使ってエラーコードをプリントしています。
return する前に、sqlite3_finalize() 関数で、prepare したステートメントオブジェクトを destroy しています。
58 ~ 59 行目では、ステートメントの実行が成功した時にも sqlite3_finalize() 関数で、prepare したステートメントオブジェクトを destroy してから true を返しています。
以上、Swift で SQLite のテーブルを作成する方法をご説明しました。
次は Swift で SQLite のテーブルにデータを挿入します。