Вам не нужно количество строк, а вы хотите, чтобы он был последним rowid
.Обычно они одинаковы, но не всегда.Что если вы удалили строку?Вы действительно хотите rowid
, который вы можете получить с помощью sqlite3_last_insert_rowid
сразу после вставки строки.Это даст вам rowid
для ранее вставленной строки.
Например, рассмотрим:
var db: OpaquePointer?
if sqlite3_open(fileURL.path, &db) != SQLITE_OK {
print("error opening database")
}
if sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS author (author_id INTEGER PRIMARY KEY, name TEXT NOT NULL)", nil, nil, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error creating table: \(errmsg)")
}
var statement: OpaquePointer?
if sqlite3_prepare_v2(db, "INSERT INTO author (name) VALUES (?)", -1, &statement, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing insert: \(errmsg)")
}
if sqlite3_bind_text(statement, 1, "William Shakespeare", -1, SQLITE_TRANSIENT) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding: \(errmsg)")
}
if sqlite3_step(statement) != SQLITE_DONE {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure inserting author: \(errmsg)")
}
let authorId = sqlite3_last_insert_rowid(db)
if sqlite3_finalize(statement) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error finalizing prepared statement: \(errmsg)")
}
Итак, если вы намеревались захватить rowid
, точто вы можете ссылаться на него в других таблицах, sqlite3_last_insert_rowid
будет захватывать то, что SQLite сгенерировал для вас.В приведенном выше примере я устанавливаю authorId
константу для любого SQLite, назначенного для этой записи.
Вы, вероятно, знаете это, но ради будущих читателей мы должны вообще позволить SQLite генерировать уникальный rowid
для нас:
используйте INTEGER PRIMARY KEY
(возможно AUTOINCREMENT
, если необходимо) в определении таблицы, как указано выше;и
на самом деле не задают значение для этого ключа при вставке, а позволяют SQLite заполнять его.
Внизу, мы позволяемSQLite присваивает нам rowid
значений, и мы используем sqlite3_last_insert_rowid
для захвата идентификатора предыдущей строки, которая была создана.
Например, теперь я могу использовать это authorId
, когда хочуиспользуйте это в другой таблице:
let sql = """
CREATE TABLE IF NOT EXISTS book (
book_id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
author_id INTEGER,
FOREIGN KEY (author_id) REFERENCES author (author_id))
"""
if sqlite3_exec(db, sql, nil, nil, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error creating table: \(errmsg)")
}
if sqlite3_prepare_v2(db, "INSERT INTO book (title, author_id) VALUES (?, ?)", -1, &statement, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing insert: \(errmsg)")
}
if sqlite3_bind_text(statement, 1, "Henry V", -1, SQLITE_TRANSIENT) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding book title: \(errmsg)")
}
if sqlite3_bind_int64(statement, 2, authorId) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding author id: \(errmsg)")
}
if sqlite3_step(statement) != SQLITE_DONE {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure inserting book: \(errmsg)")
}
if sqlite3_finalize(statement) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error finalizing prepared statement: \(errmsg)")
}