Прогнозировать следующий автоматически вставленный идентификатор строки (SQLite)

Я пытаюсь найти надежный способ (используяSQLite) чтобы найти идентификатор следующей строки для вставки,before it gets inserted, Мне нужно использовать идентификатор для другого оператора вставки, но у меня нет возможности мгновенно вставить и получить следующую строку.

Предсказывать ли следующий идентификатор так же просто, как получить последний идентификатор и добавить его? Это гарантия?

Изменить: немного больше рассуждений ... Я не могу вставить сразу, потому что пользователь может отменить вставку. Пользователь внесет некоторые изменения, операторы SQL будут сохранены, и оттуда пользователь может либо сохранить (вставив все строки сразу), либо отменить (ничего не меняя). В случае сбоя программы желаемая функциональность заключается в том, что ничего не меняется.

 foobar20 сент. 2008 г., 06:19
да, если я не могу получить что-либо еще для этого, это то, что я должен сделать.
 Solid I06 апр. 2012 г., 02:23
Так есть ли ответ о том, как получить последний идентификатор автоинкремента?
 BCS20 сент. 2008 г., 06:15
У меня есть интересная куча кода, который делает что-то более простое и использует «транзакцию» int col, равное нулю для реальных данных и некоторое значение для ожидающих изменений. Все изменения пользователя имеют одинаковое значение

Ответы на вопрос(10)

select max(id) from particular_table is unreliable for the reason below..

http://www.sqlite.org/autoinc.html

& quot; Обычный алгоритм выбора ROWID, описанный выше, будет генерировать монотонно увеличивающиеся уникальные ROWID, если вы никогда не используете максимальное значение ROWID и не удаляете запись в таблице с наибольшим ROWID. Если вы когда-либо удаляете строки или создаете строку с максимально возможным ROWID, то ROWID из ранее удаленных строк могут использоваться повторно при создании новых строк, а вновь созданные ROWID могут быть не в строго возрастающем порядке. & Quot;

Решение Вопроса

либо совершение серии операций с базой данных одновременно - это как раз то, для чего нужны транзакции. запросBEGIN; до того, как пользователь начнет возиться иCOMMIT; как только он / она закончит. Вы гарантировано, что либо все изменения будут применены (если вы делаете коммит), либо все будет отменено (если вы запросите)ROLLBACK;, если программа вылетает, питание отключается и т. д.). После прочтения базы данных вы также гарантируете, что данные сохраняются до конца транзакции, так что вы можете получитьMAX(id) или что угодно, не беспокоясь о состоянии гонки.

http://www.sqlite.org/lang_transaction.html

sqlite3_last_insert_rowid при определенных условиях, например, с использованием того же соединения с базой данных, и нет других одновременных авторов. Конечно, вы можете обратиться к исходному коду sqlite для подтверждения этих предположений.

Однако вы могли бы также серьезно рассмотреть возможность использования другого подхода, который не требует прогнозирования следующего идентификатора. Даже если вы правильно поняли версию sqlite, которую вы используете, в будущем все может измениться, и это, безусловно, затруднит переход на другую базу данных.

 04 нояб. 2014 г., 07:07
Благодарю. эта команда была именно тем, что я искал, потому что у меня была проблема. знак равно

что ваше приложение, использующее SQLite, невелико, а SQLite имеет свою семантику. Другие решения, опубликованные здесь, вполне могут иметь тот эффект, который вам нужен в этом конкретном случае, но, на мой взгляд, каждое из них, которое я читал до сих пор, в корне неверно, и его следует избегать.

В обычной среде проведения транзакции пользовательский ввод следует избегать любой ценой. Чтобы справиться с этим, если вам необходимо сохранить промежуточные данные, это записать информацию в таблицу операций для этой цели, а затем попытаться записать всю информацию в элементарной транзакции. Проведение транзакций порождает тупики и ночные кошмары в многопользовательской среде.

В большинстве сред вы не можете предполагать, что данные, полученные с помощью SELECT в транзакции, являются повторяемыми. Например

SELECT Balance FROM Bank ...
UPDATE Bank SET Balance = valuefromselect + 1.00 WHERE ...

После ОБНОВЛЕНИЯ значение баланса вполне может быть изменено. Иногда вы можете обойти это путем обновления строки (й), интересующей вас в банке, сначала в рамках транзакции, так как это гарантированно блокирует строку, предотвращая дальнейшее изменение значения, пока ваша транзакция не будет завершена.

Однако иногда лучшим способом обеспечения согласованности в этом случае является проверка ваших предположений о содержании данных в предложении WHERE обновления и проверка количества строк в приложении. В приведенном выше примере, когда вы «ОБНОВЛЯЕТЕ Банк» предложение WHERE должно содержать ожидаемое текущее значение баланса:

WHERE Balance = valuefromselect

Если ожидаемый баланс больше не совпадает, то условие WHERE также не выполняется - UPDATE ничего не делает, а rowcount возвращает 0. Это говорит о том, что возникла проблема с параллелизмом, и вам нужно повторно запустить операцию, когда что-то еще не пытается изменить ваши данные в в то же время.

SELECT * FROM SQLITE_SEQUENCE WHERE name='TABLE';, Это будет содержать поле с именемseq который является наибольшим числом для выбранной таблицы. Добавьте 1 к этому значению, чтобы получить следующий идентификатор.

Также см.Статья об автоинкременте SQLite, откуда вышла вышеуказанная информация.

Ура!

 27 нояб. 2018 г., 12:37
Это кажется неправильным, так как вы предполагаете, что 1) таблица имеет AUTOINCREMENT, 2) следующий идентификатор будет точно следующим целым числом, котороеnot гарантировано только то, что оно будет больше, чем это.
 04 авг. 2017 г., 15:51
SELECT seq FROM SQLITE_SEQUENCE WHERE name = 'TABLE' LIMIT 1;

However, be very careful of race conditions когда делаешь это. Если два человека одновременно откроют ваше приложение / веб-страницу / что угодно, и один из них добавит строку, другой пользователь попытается вставить строку с тем же идентификатором, и у вас возникнет множество проблем.

select max(id) from particular_table;

 04 дек. 2014 г., 11:35
Понижено, потому что это не работает, как только вы удаляете последнюю вставленную строку: при удалении последней строки, скажем, с ID 15, MAX (id) вернет 14 или ниже, но следующий вставленный ID будет 16 из-за Таблица SQLITE_SEQUENCE, запоминающая последний вставленный идентификатор.

получите идентификатор, отредактируйте его, если необходимо, удалите, если необходимо, или отметьте как действительный. Это и не беспокоиться о пробелах в последовательности

Кстати, вам нужно будет выяснить, как сделать недействительную часть самостоятельно. Маркировка чего-либо как NULL может работать в зависимости от специфики.

Edit: Если можете, воспользуйтесь предложением Eevee об использовании правильных транзакций. Это намного меньше работы.

 20 сент. 2008 г., 06:54
Идея Евы хороша, но не всегда выполнима. Если изменения должны охватывать сеансы, или механизм хранения не поддерживает переводы, значит, вы потерпели неудачу.
 foobar20 сент. 2008 г., 06:21
Хорошо, перечитываю, я думаю, я понимаю, что вы имеете в виду, то же самое, что и в вашем комментарии. Я думал, что вы говорите о функции sqlite. Ну что ж...

вы сможете +1 самый последний идентификатор. Я хотел бы взглянуть на все (на некоторое время назад) существующих идентификаторов в упорядоченной таблице. Являются ли они последовательными, и является ли идентификатор каждой строки на единицу больше, чем последний? Если так, то с вами, вероятно, все будет в порядке. Однако я оставляю комментарии в коде, поясняющие допущение. Выполнение блокировки поможет гарантировать, что вы не получите дополнительных строк, пока вы это делаете.

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

Кстати, я использовал только MySQL, но не думаю, что это что-то изменит)

 20 сент. 2008 г., 06:00
Вы не можете быть уверены, если вы не единственный пользователь.
 foobar20 сент. 2008 г., 05:55
На самом деле, я могу быть уверен, что ничего не вставлено, так как это простая клиентская программа.

Ваш ответ на вопрос