我正在尝试删除用户可以传递的主键。当我尝试删除项目时,什么也没有发生。基本上从表视图中,我将获得indexpath.row来找出用户向左滑动的项目,并使用该值删除该行。
func DeleteRowDatabase(inputId : Int32) -> Bool
{
var db: OpaquePointer? = nil
var returnCode : Bool = true
if sqlite3_open(self.databasePath, &db) == SQLITE_OK {
print("Successfully opened connection to database at \(self.databasePath)")
// step 16d - setup query - entries is the table name you created in step 0
var deleteStatement: OpaquePointer? = nil
var deleteStatementString : String = "delete from entries where ID = ?"
if sqlite3_prepare_v2(db, deleteStatementString, -1, &deleteStatement, nil) == SQLITE_OK {
sqlite3_bind_int(deleteStatement, inputId, inputId)
sqlite3_close(db);
}
}
return returnCode
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
//books.remove(at: indexPath.row)
print("INDEX PATH")
print(indexPath.row)
var x: Int32 = Int32(indexPath.row)
x = x + 1
let mainDelegate = UIApplication.shared.delegate as! AppDelegate
let returnCode : Bool = mainDelegate.DeleteRowDatabase(inputId: x)
}
}
答案 0 :(得分:3)
您的主要问题是,您永远不会调用sqlite3_step
来真正执行查询。
但是您还有其他问题。如果试图打开数据库(无论语句是否准备好),都需要调用sqlite3_close
。完成后,还需要在准备好的语句上调用sqlite3_finalize
。并且您为sqlite3_bind_int
中的索引传递了错误的参数值。
func DeleteRowDatabase(inputId : Int32) -> Bool {
var db: OpaquePointer? = nil
var returnCode : Bool = false
if sqlite3_open(self.databasePath, &db) == SQLITE_OK {
print("Successfully opened connection to database at \(self.databasePath)")
// step 16d - setup query - entries is the table name you created in step 0
var deleteStatement: OpaquePointer? = nil
var deleteStatementString : String = "delete from entries where ID = ?"
if sqlite3_prepare_v2(db, deleteStatementString, -1, &deleteStatement, nil) == SQLITE_OK {
sqlite3_bind_int(deleteStatement, 1, inputId)
if sqlite3_step() == SQLITE3_DONE {
returnCode = true
}
sqlite3_finalize(deleteStatement)
}
}
sqlite3_close(db)
return returnCode
}
答案 1 :(得分:2)
像rmaddy所说的
sqlite3_step
来实际执行准备好的语句。无关,但我也建议:
调用sqlite3_close
,无论例程是否成功。即使sqlite3_open
没有成功,您也必须致电sqlite3_close
。作为docs say,
无论打开时是否发生错误,与数据库连接句柄关联的资源都应在不再需要时通过将其传递给
sqlite3_close()
来释放。
sqlite3_finalize
准备好的语句。
我将使用guard
语句来避免嵌套if
语句的塔楼。
还要检查sqlite3_bind_xxx
的返回码。
我会致电sqlite3_changes
来确认是否删除了任何行。
我将以小写字母开头的方法名称。
因此:
func deleteRowDatabase(inputId: Int32) -> Bool {
var db: OpaquePointer?
defer { sqlite3_close(db) }
guard sqlite3_open(databasePath, &db) == SQLITE_OK else {
return false
}
print("Successfully opened connection to database at \(self.databasePath)")
// step 16d - setup query - entries is the table name you created in step 0
var statement: OpaquePointer?
let sql = "DELETE FROM entries WHERE id = ?"
guard sqlite3_prepare_v2(db, sql, -1, &statement, nil) == SQLITE_OK else {
return false
}
defer { sqlite3_finalize(statement) }
guard sqlite3_bind_int(statement, 1, inputId) == SQLITE_OK else {
return false
}
guard sqlite3_step(statement) == SQLITE_DONE else {
return false
}
guard sqlite3_changes(db) == 1 else {
return false
}
return true
}
我还建议:
这种为每个SQL语句打开和关闭数据库的模式效率低下。我将打开数据库一次,然后将其保留。
我担心假设表中某行的ID
对应于indexPath.row
。如果您有10条记录并删除第一个记录,该怎么办。然后,您重新启动应用程序,现在有9条记录,但是现在表中的第一行对应于ID为2。我建议您在读表时构建一个ID值数组,并将这些值用于后续操作,而不是使用假设ID
等于indexPath.row + 1
。