我需要在现有SQLite
数据库中插入超过1,000条记录。为此,我有一个带有一些静态函数的类,如下所示。
class Application {
static func openDatabase(path: String) -> OpaquePointer? {
var db: OpaquePointer? = nil
if sqlite3_open(path, &db) == SQLITE_OK {
return db
} else {
return nil
}
}
static func createTable(path: String) {
let open = openDatabase(path: path)
var createTableStatement: OpaquePointer? = nil
let sqlCreate = "CREATE TABLE IF NOT EXISTS data (ID INTEGER PRIMARY KEY AUTOINCREMENT, year text, month text, day text, x1 text, x2 text, x3 text)"
if sqlite3_prepare_v2(open, sqlCreate, -1, &createTableStatement, nil) == SQLITE_OK {
if sqlite3_step(createTableStatement) == SQLITE_DONE {
print("Table created.")
} else {
print("Table could not be created.")
}
} else {
print("CREATE TABLE statement could not be prepared.")
}
sqlite3_finalize(createTableStatement)
}
static func insertRecord(path: String, year: String, month: String, day: String) {
let open = openDatabase(path: path)
var insertStatement: OpaquePointer? = nil
let sqlInsert = "INSERT INTO data (year, month, day) VALUES (?, ?, ?)"
if sqlite3_prepare_v2(open, sqlInsert, -1, &insertStatement, nil) == SQLITE_OK {
let yearStr = year as NSString
let monthStr = month as NSString
let dayStr = day as NSString
sqlite3_bind_text(insertStatement, 1, yearStr.utf8String, -1, nil)
sqlite3_bind_text(insertStatement, 2, monthStr.utf8String, -1, nil)
sqlite3_bind_text(insertStatement, 3, dayStr.utf8String, -1, nil)
if sqlite3_step(insertStatement) == SQLITE_DONE {
print("Successfully inserted row.")
} else {
print("Could not insert row.")
}
} else {
print("INSERT statement could not be prepared.")
}
// 5
sqlite3_finalize(insertStatement)
}
}
我从AppDelegate
插入记录。如果我第二次运行它,以便按如下方式将记录插入数据库,
class AppDelegate: UIResponder, UIApplicationDelegate {
var appFile = String()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
appFile = folderPath(s: 0, name: "Application")
if !pathExists(path: appFile) {
Application.createTable(path: appFile)
} else {
for i in 0..<10 {
for j in 0..<12 {
for k in 0..<31 {
let yearStr = String(i + 2018)
let monthStr = String(j + 1)
let dayStr = String(k + 1)
Application.insertRecord(path: appFile, year: yearStr, month: monthStr, day: dayStr)
}
}
}
}
return true
}
}
将250条记录插入数据库后,应用程序将崩溃。调试器说“NSInternalInconsistencyException”我相信它会崩溃,因为该应用程序一次打开250个文件。多年前,这不是问题,因为我们可以关闭数据库,如
sqlite3_close(statement)
每次应用程序打开一个声明。现在,我们不能。那么我们可以做些什么来一次插入一些记录呢?感谢。
答案 0 :(得分:1)
使用SQLite时,正确清理所有资源非常重要。您的主要问题是您在每次调用insertRecord
时打开数据库,但您从不关闭数据库。那太糟糕了。
每次成功拨打sqlite_open
,都必须拨打相应的sqlite_close
电话。
对于sqlite3_prepare_v2
的每次成功通话,都必须对sqlite3_finalize
进行相应的通话,并对sqlite3_reset
进行零次或多次通话。
你的方法应该是:
static func insertRecord(path: String, year: String, month: String, day: String) {
if let open = openDatabase(path: path) {
var insertStatement: OpaquePointer? = nil
let sqlInsert = "INSERT INTO data (year, month, day) VALUES (?, ?, ?)"
if sqlite3_prepare_v2(open, sqlInsert, -1, &insertStatement, nil) == SQLITE_OK {
let yearStr = year as NSString
let monthStr = month as NSString
let dayStr = day as NSString
sqlite3_bind_text(insertStatement, 1, yearStr.utf8String, -1, nil)
sqlite3_bind_text(insertStatement, 2, monthStr.utf8String, -1, nil)
sqlite3_bind_text(insertStatement, 3, dayStr.utf8String, -1, nil)
if sqlite3_step(insertStatement) == SQLITE_DONE {
print("Successfully inserted row.")
} else {
print("Could not insert row.")
}
sqlite3_finalize(insertStatement)
} else {
print("INSERT statement could not be prepared.")
}
sqlite3_close(open)
} else {
print("Database couldn't be open.")
}
}