Я пытаюсь найти последний идентификатор в моей таблице в базе данных, чтобы я мог поместить его в другую таблицу. Как я могу найти этот идентификатор?
Вы не хотите количество строк, но вы хотите, чтобы его последний 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)")
}
AUTOINCREMENT
: sqlite.org/autoinc.html