Как получить последний автоинкрементный идентификатор из таблицы SQLite? - PullRequest
67 голосов
/ 24 января 2010

У меня есть таблица сообщений с идентификаторами столбцов (первичный ключ, автоинкремент) и содержимым (текст).
У меня есть таблица Users с колонками username (первичный ключ, текст) и Hash.
Сообщение отправляется одним отправителем (пользователем) нескольким получателям (пользователю), а получатель (пользователь) может иметь много сообщений.
Я создал таблицу Messages_Recipients с двумя столбцами: MessageID (ссылается на столбец ID таблицы Messages и Recipient (ссылается на столбец username в таблице Users). Эта таблица представляет отношение многие ко многим между получателями и сообщениями.

Итак, у меня вопрос заключается в следующем. Идентификатор нового сообщения будет создан после его сохранения в базе данных. Но как я могу хранить ссылку на MessageRow, который я только что добавил, чтобы получить этот новый MessageID?
Конечно, я всегда могу искать в базе данных последнюю добавленную строку, но это может привести к возвращению другой строки в многопоточной среде?

РЕДАКТИРОВАТЬ: Как я понимаю, для SQLite вы можете использовать SELECT last_insert_rowid(). Но как мне назвать это утверждение из ADO.Net?

Код моей персистентности (сообщения и сообщения-получатели являются таблицами данных):

public void Persist(Message message)
{
    pm_databaseDataSet.MessagesRow messagerow;
    messagerow=messages.AddMessagesRow(message.Sender,
                            message.TimeSent.ToFileTime(),
                            message.Content,
                            message.TimeCreated.ToFileTime());
    UpdateMessages();
    var x = messagerow;//I hoped the messagerow would hold a
    //reference to the new row in the Messages table, but it does not.
    foreach (var recipient in message.Recipients)
    {
        var row = messagesRecipients.NewMessages_RecipientsRow();
        row.Recipient = recipient;
        //row.MessageID= How do I find this??
        messagesRecipients.AddMessages_RecipientsRow(row);
        UpdateMessagesRecipients();//method not shown
    } 

}

private void UpdateMessages()
{
    messagesAdapter.Update(messages);
    messagesAdapter.Fill(messages);
}

Ответы [ 5 ]

98 голосов
/ 07 февраля 2010

Еще один вариант - посмотреть на системную таблицу sqlite_sequence. Ваша база данных sqlite будет иметь эту таблицу автоматически, если вы создали любую таблицу с автоинкрементным первичным ключом. Эта таблица предназначена для sqlite для отслеживания поля автоинкремента, чтобы он не повторял первичный ключ даже после удаления некоторых строк или после неудачной вставки (подробнее об этом см. Здесь http://www.sqlite.org/autoinc.html).

Таким образом, с этой таблицей есть дополнительное преимущество, заключающееся в том, что вы можете узнать первичный ключ вновь вставленного элемента даже после того, как вставили что-то еще (в других таблицах, конечно!) Убедившись, что ваша вставка прошла успешно (в противном случае вы получите ложное число), вам просто нужно сделать:

select seq from sqlite_sequence where name="table_name"
69 голосов
/ 24 января 2010

С SQL Server вы бы выбрали SELECT SCOPE_IDENTITY (), чтобы получить последнее значение идентификатора для текущего процесса.

С SQlite это похоже на автоинкремент, который вы бы сделали

SELECT last_insert_rowid()

сразу после вставки.

http://www.mail-archive.com/sqlite-users@sqlite.org/msg09429.html

В ответ на ваш комментарий, чтобы получить это значение, вы захотите использовать код SQL или OleDb, например:

using (SqlConnection conn = new SqlConnection(connString))
{
    string sql = "SELECT last_insert_rowid()";
    SqlCommand cmd = new SqlCommand(sql, conn);
    conn.Open();
    int lastID = (Int32) cmd.ExecuteScalar();
}
8 голосов
/ 30 января 2010

У меня были проблемы с использованием SELECT last_insert_rowid() в многопоточной среде. Если другой поток вставляет в другую таблицу, в которой есть autoinc, last_insert_rowid вернет значение autoinc из новой таблицы.

Вот где они утверждают, что в документе:

Если отдельный поток выполняет новый INSERT для того же соединения с базой данных во время работы функции sqlite3_last_insert_rowid () и, таким образом, изменяет последний идентификатор строки вставки, то значение, возвращаемое sqlite3_last_insert_rowid (), непредсказуемо и может не совпадать ни со старым, ни новая последняя вставка rowid.

Это от sqlite.org doco

5 голосов
/ 04 апреля 2017

Пример кода из решения @polyglot

SQLiteCommand sql_cmd;
sql_cmd.CommandText = "select seq from sqlite_sequence where name='myTable'; ";
int newId = Convert.ToInt32( sql_cmd.ExecuteScalar( ) );
2 голосов
/ 21 августа 2018

Согласно Android Sqlite получить идентификатор последней вставки строки существует другой запрос:

SELECT rowid from your_table_name order by ROWID DESC limit 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...