Форум: "Базы";
Текущий архив: 2003.10.27;
Скачать: [xml.tar.bz2];
ВнизЗацените дурацкое решение Найти похожие ветки
← →
kaif (2003-10-07 18:01) [0]Метод Insert наследников DataSet вставляет запись перед текущей записью в наборе. При наборе накладной пользователю привычнее вставлять запись в конец набора, то есть использовать метод Append. Тем более, что наборы в накладных бывают не столь уж обширные.
Однако компонент DBNavigator умеет делать только Insert, как впрочем и DBGrid при нажатии клавиши <Insert> именно инсертит, а не аппендит, к сожалению.
Желая использовать стандартный DBNavigator и ища приемлемое практическое решение этой проблемы я написал такой обработчик для события AfterInsert компонента IBDataSet:
var
lock_insert: boolean;
procedure TStockInForm.qryDetailAfterInsert(DataSet: TDataSet);
begin
if not lock_insert then
begin
lock_insert := True;
qryDetail.Cancel; //отменяем режим вставки
qryDetail.Append; //вставляем в конец набора
end;
lock_insert := False;
end;
Переменная lock_insert предотвращает рекурсивный бесконечный вызов.
Работает очень хорошо. Но можно ли так поступать? Не слишком ли это выглядит по-идиотски? Дело в том, что я описываю пример склада в документации к своей системе и рекомендую там такой код... Использовать другие компоненты нежелательно.
Кто что может сказать?
← →
Anatoly Podgoretsky (2003-10-07 18:13) [1]Для большинства баз данных, нет такого понятия, как физический номер записи, исключение dBase/FoxPro
А уж для IB6 совсем нет этого понятия, при выборке непредсказуема последовательность записей (без упорядочивания) одна и таже выборка в разные моменты времени может выдать разные последовательности.
Очень плохо, что ты используешь навигационный методы, они просто тебя сбивают с толку, на самом деле на сервер будет послан запрос примерно следующего типа - INSERT INTO TABLE данные, никаких позиций и в помине нет.
Если тебе нужны позиции в накладной, то введи поле номер позиции.
← →
Johnmen (2003-10-07 18:13) [2]Пока читал пост, до кода, мне тоже пришло такое решение, т.е. подменять, где надо, инсерт на аппенд. В том же гриде можно просто обработать клаву...:) и по кл.инсерт сделать Append.
Может и в навигаторе можно перехватить нажатие (не знаю не работал с ним).
По поводу кода - думаю, нормально.
:)
← →
Johnmen (2003-10-07 18:15) [3]>Anatoly Podgoretsky © (07.10.03 18:13)
Нет, здесь дело несколько в другом...:)
← →
Sandman25 (2003-10-07 18:20) [4]Insert не является Virtual, поэтому переписать его не получится.
В данных условиях Ваше решение самое лучшее ИМХО.
← →
Anatoly Podgoretsky (2003-10-07 18:25) [5]Johnmen © (07.10.03 18:15) [3]
А уточнить, а то я в недоумении?
← →
Sandman25 (2003-10-07 18:26) [6][5] Anatoly Podgoretsky © (07.10.03 18:25)
Наверное, в гриде нужен Append - добавление в конец, чтобы новая запись была самой нижней.
← →
Anatoly Podgoretsky (2003-10-07 18:28) [7]Может быть, ну тогда мой пост недействителен.
← →
MsGuns (2003-10-07 18:31) [8]1. DBNavigator - полный отстой (с месяца 2 назад я подробно описывал большинство его недостатков, главный из которых - корявость и негибкость визуализации)
2. Нельзя однозначно заменять Insert на Append, т.к. юзеру иногда надо именно вставить запись между двумя смежными. Лучше всего иметь 2 кнопки: "Новая перед", "Новая после". Или даже 3 ("Новая в конце"). Это решает все проблемы удобства интерфейса редактирования документов (выделено специально для АП)
3. Проблема последовательности записей в документе не есть такая праздная как многим представляется. Некоторые документы (к примеру, счета-фактуры) заполняются внешними контрагентами вручную и ни о какой упорядоченности по наименованию, цене и т.д. речи итти не может. Упорядоченность типа "как Маше было удобно". Но трабла в том, что частенько ее-то и надо сохранить в БД ! И я лично понимаю того юзера, который вынужден с карандашом в руках сверять электронную накладную с ее бумажным оригиналом (самому приходилось не раз, как вспомню-так вздрогну !)
Я ничего лучшего не придумал, как ввести в таблицу фактуры (к примеру) доп.поле "Ordering", в которое записываю № записи внутри курсора (фактуры). Алгоритм его определения несколько замудрен, но работает ! А вот если б кто мне показал пример эффективного алгоритма определения этого самого номера по двум смежным, я б был в большом долгу (свой алгоритм я оптимальным не считаю).
← →
Sandman25 (2003-10-07 18:36) [9]> алгоритма определения этого самого номера по двум смежным
Что имеется в виду?
← →
Vlad (2003-10-07 18:38) [10]>MsGuns © (07.10.03 18:31) [8]
Алгоритм достаточно несложен.
Если данные хранить в таблице в иерархическом виде (т.е. ID,PARENT_ID).
Тогда, если тебе нужно вставить запись между двумя другими, достаточно в следующей записи поменять ссылку на родительскую запись.
Оракл легко позволяет работать с иерархическими таблицами, в IB c этим конечно более проблемно, но тем не менее можно.
← →
Sandman25 (2003-10-07 18:42) [11]1. пробежаться по всем записям dataset и увеличить nomer на 1, если он больше вставляемого.
2. вставить нужную запись.
← →
MsGuns (2003-10-07 18:47) [12]>Sandman25 © (07.10.03 18:36) [9]
>Что имеется в виду?
Запись i-я Запись i+1-я Запись новая
------------------------------------------------
23 26 24 (25)
1 2 1.9 (1.1)
1.1 1.2 1.19 (1.11)
>Vlad © (07.10.03 18:38) [10]
>Если данные хранить в таблице в иерархическом виде (т.е. ID,PARENT_ID).
Иерархия для линейного множества линейных объектов ? Речь идет о последовательности строк документа, необходимой только для визуального отображения. И больше абсолютно ни для чего !
Т.е. это самое поле Ordering не используется нигде кроме оператора ORDER BY или индекса. НИГДЕ И НИКОГДА ! Это чисто клиентская проблема. Причем здесь иерархические данные в БД ?
← →
MsGuns (2003-10-07 18:51) [13]>Sandman25 © (07.10.03 18:42) [11]
Я так делал скубентом, когда лабы сдавал. А если строчек 200 (Редко, но бывает) ? А если табла - парадокс и юзается 15 челами ? А слетит на перенумерации ? Да мне совесть не позволит лепить такую лабуду.
← →
Vlad (2003-10-07 18:52) [14]>Иерархия для линейного множества линейных объектов
Именно линейного множества.
Год назад у меня была задача показывать в гриде некие данные, причем так, чтоб пользователь мог перетаскивать мышкой строки на ту позицию, которую ему нужно. Естественно, при close/open позиция должна сохраняться. Я тоже много изобретал, и такой способ ка ты использовал, но в конце концов пришел к иерархическому хранению, как ты говоришь, линейного множества.
Работало все четко и красиво.
← →
Sandman25 (2003-10-07 18:53) [15]Я так понимаю, что номер имеет тип real или BCD? Иначе бы сортировка не работала.
Сейчас я уже ухожу, а завтра попытаюсь чего-нибудь придумать.
← →
kaif (2003-10-07 18:53) [16]2 Anatoly Podgoretsky © (07.10.03 18:13) [1]
Я знаю, как работает SQL. Проблема у меня в другом.
2 Johnmen © (07.10.03 18:13) [2]
Спасибо! Именно Ваше мнение я очень ждал услышать и рад, что Вы находите решение приемлемым.
2 MsGuns © (07.10.03 18:31) [8]
Вы совершенно правы. Последовательность записей в счетах фактурах имеет огромное значение, так как часто менеджеры по телефону, обсуждая те или иные вопросы, отыскивают позиции в портянках, длиной более 200 строк их именно по номеру позиции.
Но я пишу пример "простейшего" склада в виде примера. И мне достаточно решить проблему с добавлением в конец. Перед посылкой строки у меня генерится первичный ключ подчиненной таблицы документа (поле N). Таким образом, так как при SELECT я запрашиваю ORDER BY N, то порядок будет всегда одинаков, как при вводе, так и при выводе. Нумерацию я делаю в вычисляемом поле просто выводя RecNo. Чтобы "дырка" не возникла в RecNo после удаления строки, переоткрываю весь набор.
Вставку в середину документа не планирую вообще. Максимум, что я использую, это перестановка соседних строк внутри документа относительно друг друга (обмен ключами N через третье состояние, равное минус N). Кстати, все это очень неплохо работает с помощью кнопочек "вверх" "вниз" в реальных приложениях. В примере я перестановку показывать не буду. И так там много сложного материала.
В общем, я чувствую, что я нашел достаточно оптимальное и не очень сложное решение. Хотя дурацкое, конечно. :)
← →
Sandman25 (2003-10-07 18:55) [17]Delta, Nomer1, Nomer2: real;
...
Delta := 10;
repeat
Delta := Delta/10;
NewNomer := Nomer1 + Delta;
until NewNomer < Nomer2;
← →
MsGuns (2003-10-07 19:13) [18]>Sandman25 © (07.10.03 18:55) [17]
Я с этого начинал когда-то ;)) Типа метод добавления разряда ?
Недостаток (при вставке нескольких подряд, как они (Машки) часто делают):
1 2 > 1.1
1.1 2 > 1.11
1.11 2 > 1.111
....
Через относительно небольшое кол-во вставок происходят понятные проблемы с погрешностью.
У меня так
1 2 > 1.9
1 1.9 > 1.8
...
1 1.1 > 1.09
1 1.09 > 1.08
...
Работает безотказно ! С учетом женской психологии и некоторой мамы ;))
← →
Johnmen (2003-10-08 00:24) [19]>kaif ©
Ашот, если мне не изменяет память, мы с тобой давно на "ты" :)
>MsGuns © (07.10.03 18:31) [8]
> А вот если б кто мне показал пример эффективного алгоритма
>определения этого самого номера по двум смежным
Предлагаю простой, понятный и эффективный алгоритм.
Каждая вновь добавленная запись отстоит от последней (по этому самому номеру N, где N - integer) на 1000000 (1 млн). Номер вновь вставляемой = ближайшее целое среднеарифметического соседних.
>...я б был в большом долгу
Все, Серега, ты попал :))))))))))))))))))))))))
PS Все, кто хочет поспорить по поводу данного алгоритма, прошу учесть специфику данной таблицы, указанную MsGuns ©.
← →
kaif (2003-10-08 01:04) [20]2 Johnmen © (08.10.03 00:24) [19]
Ашот, если мне не изменяет память, мы с тобой давно на "ты" :)
Извини, засиделся в "Потрепаться". :)
...у меня манера в том форуме всегда использовать "Вы".
Каждая вновь добавленная запись отстоит от последней (по этому самому номеру N, где N - integer) на 1000000 (1 млн).
А что там всего 2000 новых записей намечается?
Я как бы не спорю (боюсь), но просто... интересно
← →
Johnmen (2003-10-08 01:10) [21]>kaif © (08.10.03 01:04) [20]
:)))
Это для примера 1 млн. Можно и 100 000.
Лично я не видел счетов-фактур на количества более 1 тыс.
Кстати, не 2000, а 4000 :)
← →
kaif (2003-10-08 01:14) [22]2 Johnmen © (08.10.03 01:10) [21]
Так это о счет-фактуре речь шла... Я думал, о дереве каком-то плоском и испугался. А integer всего до 2000 потянет, если только отрицательные числа не использовать. Кстати, а есть ли такой CAST в IB, чтобы типа usigned integer получился? Типа от нуля и выше и так до 4*10^9 ?
← →
Johnmen (2003-10-08 01:24) [23]>kaif © (08.10.03 01:14) [22]
>А integer всего до 2000 потянет, если только отрицательные числа не использовать.
Да. Это я погорячился ;-)
>... а есть ли такой CAST в IB
Да вроде неоткуда ему там взяться...:)
А если версия позволяет и есть желание, то можно и int64.
← →
Deniz (2003-10-08 07:30) [24]Мож я не так понял, но если требуется вставить № между 1 и 2( как в примере MsGuns © (07.10.03 19:13) [18]), можно сделать чуть по другому(если конечно логика позволяет) 2-мя операциями:
update Table set
N = N + 1
where N >=2
Insert into Table(N) values (2)
Где N - № записи в документе по порядку, у меня такой алгоритм работает
← →
Alexandr (2003-10-08 08:05) [25]таки непонял.
Попробуйте в гриде нажать стрелку вниз на последней записи...
вот вам и визуальное добавление в конец датасета.
Другой вопрос, как быть после переоткрытия, но это изврат.
← →
Sandman25 (2003-10-08 10:20) [26][18] MsGuns © (07.10.03 19:13)
Да нет, у меня тоже будет все нормально.
1 2 > 1.1
1.1 2 > 1.2
1.2 2 > 1.3
...
1.9 2 > 1.91
А вообще я тоже делаю как [24] Deniz © (08.10.03 07:30)
И проблем с точностью не бывает :)
Способ [19] Johnmen © (08.10.03 00:24) тоже хорош, но только если не нужно эти идентификаторы отображать для пользователя.
И есть небольшое ограничение - нельзя добавлять log(2)N записей между двумя соседними. При N=100000 нельзя добавлять больше 16 записей.
← →
Жук (2003-10-08 10:24) [27]
> Deniz © (08.10.03 07:30) [24]
"Очень правильная постановка вопроса !"(с) :-)))
← →
Sandman25 (2003-10-08 11:02) [28][13] MsGuns © (07.10.03 18:51)
Сначала не заметил это сообщение.
Если пользователей много, и все они редактируют один документ, то без проблем все равно не обойдется. Простейший случай - после последнего пункта двое пользователей одновременно добавляют строку. Строку второго пользователя добавлять после строки первого пользователя или до?
Если в документе 200 строк, ничего страшного - отключаем все гриды, и обработчики, и за пару миллисекунд все записи изменены.
← →
Johnmen (2003-10-08 11:04) [29]>Sandman25 © (08.10.03 10:20) [26]
>И есть небольшое ограничение ...
Да у нас весь мир построен на ограничениях :)
Важно заранее опрелелиться с параметрами так, чтобы не выходить на граничные значения...
← →
Sandman25 (2003-10-08 11:07) [30][29] Johnmen © (08.10.03 11:04)
Наксолько я понимаю, при использовании int54 невозможно подобрать N так, чтобы можно было сделать больше чем 64 вставки подряд.
← →
Sandman25 (2003-10-08 11:08) [31][29] Johnmen © (08.10.03 11:04)
Наксолько я понимаю, при использовании int64 невозможно подобрать N так, чтобы можно было сделать больше чем 64 вставки подряд.
← →
Johnmen (2003-10-08 11:27) [32]>Sandman25 © (08.10.03 11:08) [31]
Я так понимаю, что не больше 63
:)
← →
Sandman25 (2003-10-08 11:36) [33][32] Johnmen © (08.10.03 11:27)
Может и так. Я много об этом не думал :)
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2003.10.27;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.015 c