Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.10.03;
Скачать: CL | DM;

Вниз

Добавление записей в пронумерованную таблицу   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.022 c
1-8057
vich
2002-09-22 16:44
2002.10.03
Как сделать чтобы программа отображала русские знаки?


6-8108
DikobraZ
2002-08-01 16:07
2002.10.03
Параметры удаленного компа


6-8104
kostik78ua
2002-07-31 14:53
2002.10.03
NMStrm+клиент/сервер


1-7916
Yarovoi Andrei
2002-09-23 18:21
2002.10.03
как можно узнать код любого знака в Memo Редакторе ?


1-8063
Vladislav
2002-09-19 18:33
2002.10.03
Как подавить сообщение.