Как избавиться от провалов в id? sql

261
18 июня 2017, 15:58

Здравствуйте, есть таблица, id генерируется базой данных, после удаления строки образуется провал пример:

ID name
1  vlad
2  sergey
3  ivan
5  tolik
8  gesha

как этого избежать и можно ли это исправить в существующей таблице?

Благодарю всех за помощь!

Answer 1

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

Если вам нужно выбрать случайную запись из таблицы, поручите это СУБД, так будет по фен-шую.

PostgreSQL и SQLite:

SELECT * FROM table_name ORDER BY RANDOM() LIMIT 1

MySQL:

SELECT * FROM table_name ORDER BY RAND() LIMIT 1

MS SQL Server:

SELECT TOP 1 * FROM table_name ORDER BY NEWID()

Oracle:

SELECT * FROM (SELECT column FROM table_name ORDER BY dbms_random.value) WHERE rownum = 1
Answer 2

Да, по id вы не сможете с уверенностью забирать запись, так как могут быть дыры. Их не надо "заделывать", это основа структуры SQL, почитайте. Считаю, что все колонки-велосипеды с номерами "без дыр" - огромный костыль. Как вы будете обновлять их номера при удалении самой первой записи, если их всего под миллион? 999999 запросов update?

Предлагаю, следующее. Не проще ли сразу получать рандомную запись из таблицы?

Cursor randomCursor = db.query(DB_TABLE, new String[] { /* тут все колонки */ }, null, null, null, null, "RANDOM()", "1");
if(cursor != null && cursor.getCount() > 0) {
    randomCursor.moveToFirst();
}
//берем из курсора данные рандомной записи

Если записей очень много, то операция может занять много времени. Подойдет для мелких таблиц. В случае работы с большими данными, я думаю, что лучше будет передавать массив не всех колонок, а только колонки с айдишником (BaseColumns._ID). А потом уже по полученному рандомному id через where выполнить второй запрос, уже получив все колонки. Примерно так:

Cursor randomId = db.query(DB_TABLE, new String[] { BaseColumns._ID }, null, null, null, null, "RANDOM()", "1");
    if(randomId != null && randomId.getCount() > 0) {
        //удалено. Курсор и так содержит одну запись
        //randomCursor.moveToFirst();
        int id = randomId.getInt(BaseColumns._ID);
        Cursor randomRow = db.query(DB_TABLE, new String[] { /* а вот тут уже все колонки */ }, BaseColumns._ID + "=?", new String[] { Integer.toString(id) }, null, null, null);
        //в курсоре randomRow лежит рандомная запись, получаем значения в колонках и используем
    }

Я думаю что так правильнее и будет быстрее, если это не так, поправьте меня в комментариях

Answer 3

А для чего это исправлять? Ты добавляешь запись в таблицу, она получает уникальный номер. Инкремент сделал +1. Ты удаляешь эту запись - инкремент не изменился.

Если ты запариваешься по этому поводу, то:

  1. При записи/удалении записей выбираем все записи
  2. Транкейт этой таблицы
  3. Изменение начального инкремент на 1
  4. Заливаем обратно эти данные.

Но этот план, он нецелесообразен.

Answer 4

Предлагаю вот такой вариант:

  1. Вытаскиваем список id в массив типа int[]

  2. Генерируем уникальное число от 0 до int[].size - 1

  3. По индексу вытаскиваем id

  4. Делаем запрос к БД.

Такой подход защищает от пробелов в id по крайней мере если в этот момент времени не было delete row

READ ALSO
Как десериализовать объект на другом ПК?

Как десериализовать объект на другом ПК?

Я сериализовал класс и отправил его по сети от сервера к клиентуКлиент должен восстановить состояние класса

266
JavaFX Polygon пересечение

JavaFX Polygon пересечение

есть два корабляу них есть хитбоксы в виде полигонов

297
Как настроить Search View из библиотеки appcompat-v7-25.3.1-sources.jar

Как настроить Search View из библиотеки appcompat-v7-25.3.1-sources.jar

Некорректно выполняется поиск элементов из списка, при вводе какого либо значенияЕсть элемент, но в поиске его не находит

264
Type Erasure в Java [требует правки]

Type Erasure в Java [требует правки]

Почему в Java есть Type Erasure?

265