![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Добавление записей в пронумерованную таблицу [D6, IB6.x, Paradox]
REA © (2002-09-09 10:06:00)Тема не нова, но прямого ответа я пока не нашел.
Проблемав следующем: есть таблица (Paradox, но не это важно) с ключом. Ключ - номер элемента (1, 2, 3...).
Задачи: добавить элемент (сгенерировать новый элемент ключа > последнего) и вставить в середину (по логике сдвинуть все, что оказались с большим ключом и сгенерировать ключ > заданного). Есть ли у кого решение проблемы? Очень не хочется изобрести велосипед. По возможности поддержать совместимость с SQL базами (т.е. не использовать RecNo и т.п.)
Max Zyuzin (2002-09-12 08:39:00) [1]>ЮЮ ©
Это без условно понятно. Но прото такая одназначная фраза Между 0 и 100 можно всавить всего только 6 чиселНе очень верна.
ЮЮ (2002-09-12 08:34:00) [2]Max Zyuzin © (12.09.02 07:59)
Это смотря на какой записи оставаться после добавления. Ряд
50,75,87,94,97,99 будет такой же длины, что и в первом случае.
Max Zyuzin (2002-09-12 07:59:00) [3]>ЮЮ ©
Да ну... а как на счет 75 (между 50 и 100), 87 (100,75), ...
ЮЮ (2002-09-12 04:06:00) [4]>Wolf226 (11.09.02 13:29)
бинарный поиск считался всегда достаточно быстрым :-)
Между 0 и 100 можно всавить всего только 6 чисел
50,25,12,6,3,1
Wolf226 (2002-09-11 13:29:00) [5]А если так:
Между X и Y вставить Z,
то Z:=(X+Y)/2
ЮЮ (2002-09-11 03:41:00) [6]>При наличии большой значности дроби в поле ключа вероятность замедления доступа к связанным таблицам увеличивается
Я же говорю, что не следует это поле использовать в кажестве ключа для связи таблиц, а только для сортировки. А над алгоритмом "нумерации" можно подумать, чтобы когда юзер тупо добавляет много записей "под одну и ту же", формировались не
1.11,1.101,1.1001, а 1.101, 1.102, 1.103 ...
MsGuns (2002-09-10 11:34:00) [7]>ЮЮ © (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-10 03:59:00) [8]>В во всей таблице записей порядка 10000, а перенумеровывать одновременно не более 200
Значит есть понятие "порядок внутри некой сущности", а не "порядок по всей таблице".
Сл-но,
1)для организации master-detail использовать "нормальные" ключевые поля.
2) "Номер по-порядку" вынести в отдельное поле использовать его только для сортировки.
3) Я использую не Float, a Integer c шагом 100. При вставке присваиваю среднее значение предыдушего и следующего номера. Если следующий-предыдущий=1 запускаяю перенумерацию с шагом 100
MsGuns (2002-09-09 12:43:00) [9]>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)
Громоздко, зато реализутся поставленная задача без использования доп.индексов и без глюкавых автоинкрементов.
(Честно говоря я вообще горячий противник исп-я автоинкремента как первичных и связующих ключей)
REA (2002-09-09 12:13:00) [10]Попробовать SQL сдвиг тоже можно (я почему то решил не использовать SQL вначале). Спасибо за такой вариант.
REA (2002-09-09 12:11:00) [11]И на том спасибо.
В во всей таблице записей порядка 10000, а перенумеровывать одновременно не более 200. Я в принципе код перенумерации уже писал, просто как-то криво все это. Можно конечно, добавлять каждый раз +10000, а перенумеровывать, когда уже вставить некуда будет, но алгоритм хитрый получится и не лучше чем с Float. Можно организовать нечто вроде однонаправленного списка (ItemID, PrevItemID = ItemID.Value), но тогда не понятно как сортировать средствами СУБД.
Praco (2002-09-09 12:06:00) [12]Ну напрашивается так:
Поле "Порядковый_номер" - уникальный ключ
содержит значения (1..n..m)
при вставке записи перед n надо:
1) update table set Порядковый_номер = Порядковый_номер + 1
where Порядковый_номер >= n;
2) insert into table (Порядковый_номер, ...) values (n, ...);
Все это в рамках одной транзакции.
Sergey13 (2002-09-09 11:55:00) [13]Тот алгоритм, что я описал, я использую при нумерации операций в техпроцессе. Это нормально работает, но НА НЕБОЛЬШОМ НАБОРЕ ДАННЫХ. Тут тебе говорят что относительно ВСЕЙ таблицы, это гибельный путь, если в таблице прилично записей и многопользовательский доступ - заморишься перенумеровывать.
REA (2002-09-09 11:30:00) [14]Есть элементы, которые следуют друг за другом (например ненумерованные вагоны или конфеты на конвейере - не важно), которые не характеризуются никакими другими уникальными свойствами кроме порядкового номера (хотя имеют ряд других - цвет, вес, размер). Важно сохранить их порядок (как например порядок операций при сборке кубика-рубика). Ко времени тоже не привязано.
Sergey13 (2002-09-09 11:25:00) [15]Можно попробовать сделать это индексное(для сортировки) поле не интежером, а флоатом. И увеличивать не на 1, а на 0.01 например. Периодически запускать процедуру перенумерации (в эксклюзивном режиме желательно) - вновь делать все целым по порядку - для новых вставок. Коряво это, но попробовать можно. Только величину инкремента придется анализировать динамически - т.к. следующая запись уже может быть на 0.01 больше -> надо увеличивать не на 0.01 а на 0.001. И т.д. Но ... криво это все. ИМХО концепцию построения базы надо пересматривать. Кому нужно, что бы, например, сегодня Иванов был под номером 13, а завтра 17 или 9? Смысла в этом никакого.
Max Zyuzin (2002-09-09 11:21:00) [16]Уточните тогда, почему возникла необходимость строго места вставки новой записи? (в смысле что бы она строго отображалась в определенном месте?)
REA (2002-09-09 11:18:00) [17]Так подскажите скорее "хороший" способ.
Если есть вопросы по постановке задачи, с радостью уточню.
Max Zyuzin (2002-09-09 11:07:00) [18]Дело в том, что если вы будете пытаться "сдвигать", то это будет медленно работатьдаже на небольших таблицах, а если колличество записей будет больше то вообще программа "встанет" при добавлении.. по этому сдвиг это не хороший способ... ИМХО
REA (2002-09-09 11:05:00) [19]Не понял.
Если идут записи с номерами (ключевым полем) 1, 2, 3, 4, 5... то при вставке между 3 и 4 нужно 4, 5... увеличивать на 1.
Desdechado (2002-09-09 11:00:00) [20]построй индекс по этому полю и при открытии таблицы делай его активным - юзер будет видеть, ка ему нравится, и сдвигать не придется