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

Вниз

Тут пролетал запрос, возвращающий   Найти похожие ветки 

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

Наверх




Память: 0.56 MB
Время: 0.283 c
3-51113
Stas
2003-09-25 09:46
2003.10.16
Когда считывается информация из Blob полей ?


9-51048
Арм
2003-04-15 03:57
2003.10.16
Беда с текстурами в OpeGL


6-51372
Demetrius
2003-08-20 12:50
2003.10.16
Вызывается ли какой-то меssаge при получении сообщения в WinSock


14-51508
andre
2003-09-27 21:42
2003.10.16
Windows XP


3-51145
Alex-kosmonavt
2003-09-24 14:12
2003.10.16
импорт БД