Mysql найти наименьший + уникальный идентификатор
У меня есть идентификатор столбца и что-то вроде 1000 элементов, некоторые из которых были удалены как id=90, id=127, id=326
как я могу сделать запрос для поиска доступных идентификаторов, поэтому я могу повторно использовать его для другого элемента?
его как a min(ID)
, но я хочу найти только идентификаторы, которые НЕ находятся в моей базе данных, поэтому, если я удалю элемент с помощью ID = 90
, в следующий раз, когда я нажму ADD ITEM, я вставляю его как ID = 90
Ответы
Ответ 1
Вы можете получить минимально доступный идентификатор, используя этот запрос:
SELECT MIN(t1.ID + 1) AS nextID
FROM tablename t1
LEFT JOIN tablename t2
ON t1.ID + 1 = t2.ID
WHERE t2.ID IS NULL
Что он делает, так это то, что он соединяет таблицу с собой и проверяет, является ли идентификатор min+1
null
или нет. Если он равен нулю, тогда этот идентификатор доступен. Предположим, у вас есть таблица, где ID
:
1
2
5
6
Затем этот запрос даст вам результат как 3
, который вам нужен.
Ответ 2
Не используйте повторно ID. Обычно у вас достаточно доступных идентификаторов, поэтому вам не нужно заботиться о фрагментации.
Например, если вы повторно используете идентификаторы, ссылки из поисковых систем могут указывать на нечто совершенно не связанное с тем, что находится в индексе поиска - показ ошибки "не найден" в этом случае намного лучше.
Ответ 3
Это против концепции суррогатных ключей, чтобы попытаться повторно использовать идентификаторы
Суррогатный ключ хорош, потому что он сам определяет саму запись, а не какой-то объект в реальной жизни. Если запись исчезла, идентификатор тоже исчез.
Опытные разработчики БД не боятся исчерпать числа, потому что знают, сколько столетий нужно истощать, скажем, длинными целыми числами.
Кстати, вы можете столкнуться с проблемой блокировки или нарушения уникальности в многопоточной среде с одновременными транзакциями, пытаясь найти пробел в последовательности идентификаторов. Генераторы идентификаторов автоматического прироста, предоставляемые серверами БД, обычно работают вне области транзакций и, таким образом, генерируют хорошие суррогатные ключи.
Дополнительная информация: Суррогатные ключи
Ответ 4
запрос как:
SELECT MIN(tableFoo.uniqueid + 1) AS nextID
FROM tableFoo
LEFT JOIN tableFoo tf1
ON tableFoo.uniqueid + 1 = tf1.uniqueid
WHERE tf1.uniqueid IS NULL
Ответ 5
Обратите внимание, что ответы shamittomar и Haim Evgi не работают, если самый низкий ID является бесплатным. Чтобы разрешить перезарядку самого низкого идентификатора, предварительно проверьте, доступна ли она:
SELECT TRUE FROM tablename WHERE ID = 1;
Если это что-то возвращает, то идентификатор 1 не является бесплатным и вы должны использовать свой ответ. Но если идентификатор 1 свободен, просто используйте его.
Ответ 6
По моему личному мнению. Вместо того, чтобы удалять строку из автоматического приращения, было бы дешевле летать дешевле, чтобы иметь Boolean Column для "Removed" или "Deleted", а для дополнительной безопасности над правой строкой с пробелами, когда вы устанавливаете удаленный флаг.
UPDATE table SET data=" ", removed = TRUE WHERE id = ##
(## - фактический id btw)
Тогда вы можете
SELECT * FROM table WHERE removed = TRUE ORDER BY id ASC
Это сделает вашу базу данных более эффективной и сохранит тесто на серверах. Не говоря уже об отсутствии неприятных ошибок.
Ответ 7
Учитывая, что ваша база данных достаточно мала, правильный ответ заключается в не повторять ваши идентификаторы вообще и просто обеспечить его автоматически увеличивающийся первичный ключ. Таблица составляет тысячу записей, поэтому вы можете сделать это без каких-либо затрат.
Однако, если у вас есть таблица несколько миллионов записей/более длинный идентификатор, вы обнаружите, что принятый ответ не закончится в разумное время.
Принятый ответ будет давать вам наименьшее из этих значений, правильно, однако, вы платите цену за не использование столбца автоматического увеличения, или если у вас есть один, не используя авто increment column как фактический идентификатор, как он предназначен (Как и я, иначе меня бы здесь не было). Я нахожусь во власти устаревшего приложения, так как идентификатор не является фактическим первичным ключом, и он случайно генерируется с помощью алгоритма без уважительной причины, поэтому мне нужно было заменить его, так как увеличение диапазона столбцов теперь чрезвычайно дорогостоящие изменения.
Здесь он выясняет всю
соединяйтесь между целым числом t1 и t2, прежде чем сообщать, что такое мин этих объединений. По сути, вы заботитесь только о первом найденном NULL
t1, независимо от того, является ли он на самом деле наименьшим или нет.
Итак, вы берете MIN
и добавляете LIMIT
из 1.
edit: Поскольку это не первичный ключ, вам также нужно будет проверить не null, поскольку поле первичного ключа не может быть null
SELECT t1.ID + 1 AS nextID
FROM tablename t1
LEFT JOIN tablename t2
ON t1.ID + 1 = t2.ID
WHERE t2.ID IS NULL
AND t1.ID IS NOT NULL
LIMIT 1
Это всегда даст вам идентификатор, который вы можете использовать, его просто не гарантировано всегда будет самым маленьким.