Как удалить элемент в sqlite с помощью swift - PullRequest
0 голосов
/ 14 апреля 2019

Я пытаюсь удалить первичный ключ, который пользователь может передать. Когда я пытаюсь удалить элемент, ничего не происходит.По сути, из таблицы я получаю 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)

        }
    }

Ответы [ 2 ]

3 голосов
/ 14 апреля 2019

Ваша главная проблема в том, что вы никогда не вызываете 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

}
2 голосов
/ 14 апреля 2019

Как сказал Рмадди,

  1. Вам нужно позвонить sqlite3_step, чтобы фактически выполнить подготовленный оператор.

Не имеет отношения, но я бы также предложил:

  1. Вызовите sqlite3_close независимо от того, была ли процедура успешной или нет. Даже если sqlite3_open не удалось, вы должны позвонить sqlite3_close. Как говорят документы ,

    Независимо от того, возникает ли ошибка при ее открытии, ресурсы, связанные с дескриптором соединения с базой данных, должны быть освобождены путем передачи ее в sqlite3_close(), когда она больше не требуется.

  2. sqlite3_finalize подготовленное заявление.

  3. Я бы использовал guard операторы, чтобы избежать башен с вложенными if операторами.

  4. Также проверьте код возврата sqlite3_bind_xxx.

  5. Я бы позвонил sqlite3_changes, чтобы фактически подтвердить, были ли удалены какие-либо строки.

  6. Я начну с имен моих методов строчными буквами.

* * Таким образом тысяча сорок-девять:
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
}

Я бы также предложил:

  1. Этот шаблон открытия и закрытия базы данных для каждого оператора SQL немного неэффективен. Я бы однажды открыл базу данных и оставил все как есть.

  2. Я беспокоюсь о том, что ID для строки в таблице соответствует indexPath.row. Что произойдет, если у вас есть 10 записей и удалить первую. Затем вы перезапускаете приложение, и теперь есть 9 записей, но теперь первая строка в таблице соответствует идентификатору 2. Я бы предложил создать массив значений идентификаторов, когда вы читаете в таблице, и использовать эти значения для последующих операций, а не при условии, что ID равно indexPath.row + 1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...