Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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.013 c
3-51138
Amayak
2003-09-22 07:56
2003.10.16
BD


1-51182
zumo
2003-10-04 18:25
2003.10.16
получение консольного вывода


3-51123
sergg
2003-09-24 11:00
2003.10.16
Использование БД по локалке только для чтения


3-51131
vil
2003-09-25 07:43
2003.10.16
Время обновления таблицы.


3-51137
dtm
2003-09-23 17:51
2003.10.16
Тут пролетал запрос, возвращающий





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский