Форум: "Базы";
Текущий архив: 2003.10.16;
Скачать: [xml.tar.bz2];
ВнизТут пролетал запрос, возвращающий Найти похожие ветки
← →
dtm (2003-09-24 18:28) [40]Alex_Raider [32]
> У тебя сама постановка алгоритмики и способа решения неправильная.
>Следует сделать иначе - ничего не удалять,
а просто помечать записи(документы) как "удалено, недоступно, заблокировано".
;) Всё у меня правильно.
Пользователь вызывают новую операцию, она должна уже на этапе создания иметь уникальный номер - она его и имеет, получая от генератор. Если пользователь отменил во время оформления операцию - номер теряется, так как уже был сгенерирован. Естественно, что в базе ничего не остаётся, так что помечать "удалено, недоступно, заблокировано" просто нечего.
А есть ещё софтина, обрабатывающая информацию об операциях, поступающих из разных концов Беларуси, и по правилам ведения работы заказчика (а они определяются международной конвенцией) номера у документов должны быть по возможности последовательные, то есть без "дырок". Может, "дырки" всё равно будут, но для сертификации программы перед использованием я обязан вложить подобную функцию в программу. Иначе никак.
Так что не надо говорить, что кто-то поставил задачу неправильно...
← →
alex_raider (2003-09-24 19:40) [41]>Пользователь вызывают новую операцию, она должна уже на этапе >создания иметь уникальный номер - она его и имеет, получая от >генератор. Если пользователь отменил во время оформления >операцию - номер теряется, так как уже был сгенерирован. >Естественно, что в базе ничего не остаётся, так что >помечать "удалено, недоступно, заблокировано" просто нечего
А генерировать новый ID не на OnNewRecord, а в триггере BeforeInsert самой БД нельзя?
Тогда даже если юзер и отменит транзакцию(вставку документа), то номер не сгенерится.
Если вставил документ, а он не нужен, то
"САМ ДУРАК", все шито-крыто.
Короче, хочу подытожить,
резюме:
"Шаманство" с получением максимального номера -
есть дурной тон и его нужно избегать. Ты автоматически налетаешь на проблему с блокировками и транзакционностью (т.е. не safe для многопользовательской системы) и никак ее не избежишь, кроме как блокировкой таблицы в момент SELECT`a.
Я решал подобную задачу 4 года назад, правду тебе говорю :-)))
← →
alex_raider (2003-09-24 19:41) [42]так что постановку задачи нужно пересмотреть :-)
← →
MsGuns (2003-09-24 20:00) [43]>dtm (24.09.03 18:28) [40]
Конечно, alex_raider © насчет неверной постановки всей задачи маненько загнул, но вот что действительно непонятно, так это твои попытки дергать генератор ДО вставки записи в таблицу (не путать с добавлением новой строки в грид).
Возможно, следует отказаться от редактирования данных в гриде, вынеся всю юзерскую активность в не DB-контролы в отд.панельке (или мод.форме), где и сделать кнопульки "Записать", "Отменить" и т.д. ?
← →
kaif (2003-09-24 20:18) [44]2 alex_raider © (24.09.03 19:40) [41]
А генерировать новый ID не на OnNewRecord, а в триггере BeforeInsert самой БД нельзя?
Тогда даже если юзер и отменит транзакцию(вставку документа), то номер не сгенерится.
Боюсь, сгенерится. Генераторы IB работают вне контекста транзакции, а триггеры - в контексте.
Так что при откате транзакции дырка все равно будет.
Вопрос в другом. На фиг вообще операции нумеровать? Если же эти номера имеют какое-то философское значение, то их нельзя уже менять и дырки от удалений (если таковые законодательством не возбраняются) обязаны будут присуствовать. Если же кому-то в международных организациях или налоговых инспекциях не нравятся дырки, то причину этого странного явления нужно искать при помощи психоанализа З.Фрейда в их глубоком детстве или в арбитражном суде.
Если же просто хочется уменьшить кол-во дырок, возникающих из-за отката транзакций по вставке, то можно сделать какой-нибудь банальный код типа:
NewN := QueryMaxN - 1; //функция, возвращающая максимальный номер
//SELECT MAX(N) FROM TABLE1
while True do
try
DataSet.Edit;
DataSet.FieldByName("N").AsInteger := NewN;
DataSet.Post; //тут может вылететь на нарушении ключа
Transaction.CommitRetaining; //тут на еще каком конфликте
break;
except
NewN := NewN + 1; //пробуем следующий номер
end;
И никаких генераторов.
Генераторы использовать только для суррогатных ключей типа ID. Нумерация "без дырок" к таким ключам не относится, хотя поле N должно иметь уникальный индекс, который вызовет исключительную ситуацию в приведенном коде.
Решение может не самое быстрое, но практически приемлемое, ИМХО.
Правда сам я пока никогда так не делал :)
Но как-нибудь попробую.
← →
kaif (2003-09-24 20:21) [45]Пардон, в коде нужно в начале:
вместо NewN := QueryMaxN - 1
написать NewN := QueryMaxN + 1
← →
Zacho (2003-09-24 20:36) [46]
> kaif © (24.09.03 20:18) [44]
Не надо так делать. Я уже как-то (и вроде даже не раз) приводил пример, как надо делать. Если кратко, то получение следующего номера (SELECT MAX(..)+1) и вставка записи - в отдельной короткой транзакции c параметрами consistency wait lock_write=<имя таблицы> exclusive. И не надо будет никаких циклов и обработок нарушений ПК.
← →
kaif (2003-09-24 21:10) [47]2 Zacho © (24.09.03 20:36) [46
Я уже как-то (и вроде даже не раз) приводил пример, как надо делать
Ни разу не читал об этом...
Век живи - век учись. Я никогда не использовал такие хитрые параметры транзакции...
consistency wait lock_write=<имя таблицы> exclusive
Мне это нравится. Конечно транзакция должна быть короткой. Но это как раз не проблема.
Ты это сам придумал или есть хорошая книга (статья) о примерах использования разных параметров транзакций IB? Я знал о существованиии режима wait lock write, но мне в голову не пришло использовать это для решения подобных задач с нумерацией...
Причем решение-то действительно классное!
← →
Zacho (2003-09-24 21:37) [48]
> kaif © (24.09.03 21:10) [47]
> Ты это сам придумал или есть хорошая книга (статья) о примерах
> использования разных параметров транзакций IB?
Единственная известная мне хорошая и подробная статья о транзакциях в IB - http://www.ibase.ru/devinfo/ibtrans.htm Правда, примера именно для такого использования SNAPSHOT TABLE STABILITY с явным резервированием таблицы protected write там вроде бы нет (и вообще с примерами не густо), но именно этой статьей я и руководствовался, когда понадобилось сделать "бездырочную" нумерацию.
Страницы: 1 2 вся ветка
Форум: "Базы";
Текущий архив: 2003.10.16;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.014 c