Форум: "Базы";
Текущий архив: 2002.10.03;
Скачать: [xml.tar.bz2];
ВнизДобавление записей в пронумерованную таблицу Найти похожие ветки
← →
REA (2002-09-09 10:06) [0]Тема не нова, но прямого ответа я пока не нашел.
Проблема в следующем: есть таблица (Paradox, но не это важно) с ключом. Ключ - номер элемента (1, 2, 3...).
Задачи: добавить элемент (сгенерировать новый элемент ключа > последнего) и вставить в середину (по логике сдвинуть все, что оказались с большим ключом и сгенерировать ключ > заданного). Есть ли у кого решение проблемы? Очень не хочется изобрести велосипед. По возможности поддержать совместимость с SQL базами (т.е. не использовать RecNo и т.п.)
← →
Turalyon (2002-09-09 10:20) [1]Используйте автоинкрементные поля, для создания таких ключей.
А порядок физический хранения в таблице элементов вас не должен беспокоить.
← →
REA (2002-09-09 10:26) [2]А в середину то как потом вставлять?
Меня волнует именно порядок следования элементов - должно быть так как добавляет юзер. Т.е. если он хочет вставить в середину, то запись должна быть (логически) в этом месте.
← →
Max Zyuzin (2002-09-09 10:32) [3]Т.е. если я правильно понимаю, пользователь может захотеть вставить запись между любыми двумя и хочет что бы она там и отображалась всегда?
Я бы порекомендовал вообще не завязываться с номерами и спрятать их от пользователя что бы не видел. Может вам будет удобней использовать сортировки по полям?
← →
REA (2002-09-09 10:38) [4]Спрятать то конечно можно, но проблема не пропадет.
Тривиальное решение - убрать нумерацию вообще (для парадокса пройдет), но мне нужно ключевое поле для организации master-detail, а в таблице кроме порядкового номера другого ключа нет - записи идентичны (точнее там есть еще другие ключевые поля, но это оставим за кадром).
← →
Anatoly Podgoretsky (2002-09-09 10:39) [5]Физический порядок хранения в таблице элементов тебя не должен беспокоить, если тебе надо упорядочивание при вывода, то надо использовать индексное поле, ну например номер следования.
К сожалению твоя система не сможет работать в многопользовательской среде.
Для однопользовательской среды, задача перенумерации не является сложной, доступна даже самому начинающему, это всего лишь Ni+1.
Это позврлит не только вставлять, но и изменять порядок записей.
← →
REA (2002-09-09 10:47) [6]Среда скорее однопользовательская, чем многопользовательская.
Не хочется просто все записи при вставке в середину вниз сдвигать - некрасиво это. Кстати - есть ли надежная и корректная процедура сдвига записей? Сам я конечно напишу, но хочется посмотреть как эксперты делают.
← →
Desdechado (2002-09-09 10:55) [7]построй индекс по этому полю и при открытии таблицы делай его активным - юзер будет видеть, ка ему нравится, и сдвигать не придется
← →
REA (2002-09-09 10:59) [8]См. выше. Индекс и так по этому полю. Проблема в добавлении в середину - индекс приходится сдвигать.
← →
Desdechado (2002-09-09 11:00) [9]построй индекс по этому полю и при открытии таблицы делай его активным - юзер будет видеть, ка ему нравится, и сдвигать не придется
← →
REA (2002-09-09 11:05) [10]Не понял.
Если идут записи с номерами (ключевым полем) 1, 2, 3, 4, 5... то при вставке между 3 и 4 нужно 4, 5... увеличивать на 1.
← →
Max Zyuzin (2002-09-09 11:07) [11]Дело в том, что если вы будете пытаться "сдвигать", то это будет медленно работатьдаже на небольших таблицах, а если колличество записей будет больше то вообще программа "встанет" при добавлении.. по этому сдвиг это не хороший способ... ИМХО
← →
REA (2002-09-09 11:18) [12]Так подскажите скорее "хороший" способ.
Если есть вопросы по постановке задачи, с радостью уточню.
← →
Max Zyuzin (2002-09-09 11:21) [13]Уточните тогда, почему возникла необходимость строго места вставки новой записи? (в смысле что бы она строго отображалась в определенном месте?)
← →
Sergey13 (2002-09-09 11:25) [14]Можно попробовать сделать это индексное(для сортировки) поле не интежером, а флоатом. И увеличивать не на 1, а на 0.01 например. Периодически запускать процедуру перенумерации (в эксклюзивном режиме желательно) - вновь делать все целым по порядку - для новых вставок. Коряво это, но попробовать можно. Только величину инкремента придется анализировать динамически - т.к. следующая запись уже может быть на 0.01 больше -> надо увеличивать не на 0.01 а на 0.001. И т.д. Но ... криво это все. ИМХО концепцию построения базы надо пересматривать. Кому нужно, что бы, например, сегодня Иванов был под номером 13, а завтра 17 или 9? Смысла в этом никакого.
← →
REA (2002-09-09 11:30) [15]Есть элементы, которые следуют друг за другом (например ненумерованные вагоны или конфеты на конвейере - не важно), которые не характеризуются никакими другими уникальными свойствами кроме порядкового номера (хотя имеют ряд других - цвет, вес, размер). Важно сохранить их порядок (как например порядок операций при сборке кубика-рубика). Ко времени тоже не привязано.
← →
Sergey13 (2002-09-09 11:55) [16]Тот алгоритм, что я описал, я использую при нумерации операций в техпроцессе. Это нормально работает, но НА НЕБОЛЬШОМ НАБОРЕ ДАННЫХ. Тут тебе говорят что относительно ВСЕЙ таблицы, это гибельный путь, если в таблице прилично записей и многопользовательский доступ - заморишься перенумеровывать.
← →
Praco (2002-09-09 12:06) [17]Ну напрашивается так:
Поле "Порядковый_номер" - уникальный ключ
содержит значения (1..n..m)
при вставке записи перед n надо:
1) update table set Порядковый_номер = Порядковый_номер + 1
where Порядковый_номер >= n;
2) insert into table (Порядковый_номер, ...) values (n, ...);
Все это в рамках одной транзакции.
← →
REA (2002-09-09 12:11) [18]И на том спасибо.
В во всей таблице записей порядка 10000, а перенумеровывать одновременно не более 200. Я в принципе код перенумерации уже писал, просто как-то криво все это. Можно конечно, добавлять каждый раз +10000, а перенумеровывать, когда уже вставить некуда будет, но алгоритм хитрый получится и не лучше чем с Float. Можно организовать нечто вроде однонаправленного списка (ItemID, PrevItemID = ItemID.Value), но тогда не понятно как сортировать средствами СУБД.
← →
REA (2002-09-09 12:13) [19]Попробовать SQL сдвиг тоже можно (я почему то решил не использовать SQL вначале). Спасибо за такой вариант.
← →
MsGuns (2002-09-09 12:43) [20]>REA (09.09.02 11:30)
Расскажу как я решал подобную проблему.
Задача: есть Мастер-таблица, в которой записи должны следовать в той посл-ти, в которой их вводит юзер. У каждой записи этой таблицы есть "потомки" в детаил таблице (один-ко-иногим). В свою очередь в детале каждой записи соответствует неск. записей Детала 2. Т.е. 3-х уровневая табличная БД.
Ключи мастера я определил так, что кроме глобалных (Год, месяц),был третий ключ, который я определил как с фиксированной точкой до 12 знаков в дроби. Это поле являлось основным для задания требуемой посл-ти записей. Его я не показываю юзеру.
Т.е. табла имеет такой вид (грид)
Дата Наименование Наименование 1 ...
1 14.09 Ла-ла-ла
2 8.09 бббббббб
3 10.09 ппппппп
4 27.08 ааордлодпол
Когда юзер жмет инсерт (например, между 2 и 3 записью), я вызываю написанный модулек (совсем не такой простой, но и не черезчур заумный, писанный на асме), который "генерит" число или минимально больше 2, или минимально меньше 3, в зависимости от разряности дроби и тот и другого.
Пример генерации
Предыд След Генерируемое
2 3 2.1
2.1 3 2.2
2 2.1 2.09
2 2.09 2.08
и т.д. Чтобы не превысилось предельно допустимое значение дробных знаков, модуль возвращает false, прога дает сообщение типа
Невозможна вставка в текущей позиции
Вставить в другое место Перенумерация
Это работает достаточно хорошо. Минуса:
1. Пришлось писать модуль
2. При перенумерации много мороки с модификацией ключей у потомков, да и долговато оно работает (на БД около 200000 записей или около 5-6 тысяч на месяц, а все делается на месячных "подшивках", перенумерация идет несколько минут (до 15)
Громоздко, зато реализутся поставленная задача без использования доп.индексов и без глюкавых автоинкрементов.
(Честно говоря я вообще горячий противник исп-я автоинкремента как первичных и связующих ключей)
← →
ЮЮ (2002-09-10 03:59) [21]>В во всей таблице записей порядка 10000, а перенумеровывать одновременно не более 200
Значит есть понятие "порядок внутри некой сущности", а не "порядок по всей таблице".
Сл-но,
1)для организации master-detail использовать "нормальные" ключевые поля.
2) "Номер по-порядку" вынести в отдельное поле использовать его только для сортировки.
3) Я использую не Float, a Integer c шагом 100. При вставке присваиваю среднее значение предыдушего и следующего номера. Если следующий-предыдущий=1 запускаяю перенумерацию с шагом 100
← →
MsGuns (2002-09-10 11:34) [22]>ЮЮ © (10.09.02 03:59)
В том-то и трабла, что когда вставляется номер между двумя, имеющими одинаковую значность дроби, требуется добавить еще один знак:
1.1 - 1.2 -> 1.11
1.1 - 1.11 -> 1.101
1.1 - 1.101 -> 1.1001
...
Как видите, ни о каком шагк в 100 не может быть и речи. Т.е. когда юзер тупо добавляет много записей "под одну и ту же", возникает это самое переполнение значности дроби. Выход здесь видится в альтернативе:
либо не давать ему ввести запись в этом месте
либо запустить перенумерацию всего либо "в данном районе", избавляясь от больших дробей.
При наличии большой значности дроби в поле ключа вероятность замедления доступа к связанным таблицам увеличивается
← →
ЮЮ (2002-09-11 03:41) [23]>При наличии большой значности дроби в поле ключа вероятность замедления доступа к связанным таблицам увеличивается
Я же говорю, что не следует это поле использовать в кажестве ключа для связи таблиц, а только для сортировки. А над алгоритмом "нумерации" можно подумать, чтобы когда юзер тупо добавляет много записей "под одну и ту же", формировались не
1.11,1.101,1.1001, а 1.101, 1.102, 1.103 ...
← →
Wolf226 (2002-09-11 13:29) [24]А если так:
Между X и Y вставить Z,
то Z:=(X+Y)/2
← →
ЮЮ (2002-09-12 04:06) [25]>Wolf226 (11.09.02 13:29)
бинарный поиск считался всегда достаточно быстрым :-)
Между 0 и 100 можно всавить всего только 6 чисел
50,25,12,6,3,1
← →
Max Zyuzin (2002-09-12 07:59) [26]>ЮЮ ©
Да ну... а как на счет 75 (между 50 и 100), 87 (100,75), ...
← →
ЮЮ (2002-09-12 08:34) [27]Max Zyuzin © (12.09.02 07:59)
Это смотря на какой записи оставаться после добавления. Ряд
50,75,87,94,97,99 будет такой же длины, что и в первом случае.
← →
Max Zyuzin (2002-09-12 08:39) [28]>ЮЮ ©
Это без условно понятно. Но прото такая одназначная фраза Между 0 и 100 можно всавить всего только 6 чисел Не очень верна.
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2002.10.03;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.007 c