Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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
1-8048
Shadow
2002-09-22 16:46
2002.10.03
Рисование


4-8230
Yaro
2002-08-18 14:59
2002.10.03
Как узнать закрыт ли процесс, созданный CreateProcess?


3-7840
cherepovets
2002-09-12 15:03
2002.10.03
DBGrid


8-8068
ork
2002-06-05 00:14
2002.10.03
Как сделать Delphi DFX из Delphi 5


14-8139
pag77
2002-09-08 01:08
2002.10.03
где скачать delphi_6





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский