Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2003.01.27;
Скачать: [xml.tar.bz2];

Вниз

Генераторы   Найти похожие ветки 

 
Вованчик   (2003-01-08 08:52) [0]

Всем здравствуйте. Возникла такая проблемка: для нумерации счетов в программе использую значения генератора. И в начале вроде все было в порядке, но потом изредка значения генератора стали проскакивать. В любой другой программе это мне было бы безразлично (разные и разные), а здесь каждый номер нужен. Хотелось бы знать это глюк генератора InterBase или чего ещё?


 
Alexandr   (2003-01-08 08:57) [1]

это глюк у тебя в голове.
Генераторы ну никак не предназначены для нумерации счетов без пропусков.
1) Значения не откатываются при отмене транзакции
2) Значения не вернуть назад, не заделать дырки без сложных выкрутасов.


 
Sergey Masloff   (2003-01-08 09:02) [2]

Я когда-то для нумерации без пробелов делал так: номер действительно генератор создавал, но при откате транзакции я записывал его (номер) в хранилище для последующего использования. И при необходимости нового номера сначала смотрел в "хранилище" нет ли там свободных. Сам механизм был чуть сложнее, но в общем именно так. Думаю, реализовать это не составит труда


 
Johnmen   (2003-01-08 09:04) [3]

...
2) И со сложными не заделаешь однозначно...
...


 
Вованчик   (2003-01-08 09:04) [4]

Спасибо и всех с праздниками !!!


 
AlienB   (2003-01-08 09:29) [5]

Есть конечно еще вариантик, незнаю может и медленне, но...
Сортируем по AccountNumber и берем последний номер... просто до нельзя...


 
Wolf   (2003-01-08 09:52) [6]

2 AlienB

Только при двух запущенных клиентах можно получить одинаковый номер.

2 Вованчик

Ты номер присваивай по проведению документа, только когда он уже сохранится.


 
Alexander Vasjuk   (2003-01-08 18:26) [7]

ни фига
их еще удаляют


 
Мышь   (2003-01-08 21:07) [8]

Номер по проведению - хорошая идея. А то, что документы удаляют - это жизнь. Если под каким-то номером был какой-то документ, то, видимо, не стоит использовать этот номер для другого документа, особенно, если этот документ напечатан на бумажке.


 
MsGuns   (2003-01-08 21:10) [9]

Делал почти как >Sergey Masloff (08.01.03 09:02)
Идея такова:

1. При добавлении новой записи смотрим "стек", файл любого формата, (у меня был простой ini-подобный). Если пустой, то определяем номер как Max+1. Если не пустой, берем самый первый свободный, одновременно удаляя его из "стека".
2. При откате - отмене - удалении номер записи дописываем в "стек".
3. Делаем попытку добавления. При повторе ключа возврат к п.1

Единственная трабла - это обеспечение нормальной обработки "стека" на сети, когда юзеров несколько, - но я просто ставил защищенный блок, в цикле повторяя чтение-запись. Все работало хорошо и быстро, пока количество записей стека не становилось слишком велико (больше 1000). Тогда ручками при остановленном сервере просто выкидывал все, оставляя не более сотни первых. "Дырки" получались, конечно. Раз в два-три месяца приходилось запускать спец.прожку, которая просто определяла все "дырки" и писала их в стек. Генератор использовать в этом случае весьма затруднительно.


 
Jeer   (2003-01-08 21:30) [10]

Вставлять - после утверждения.
Делаю и так.

{Get max available ID}
function quGetMaxID_(tbName,FName: String): LongInt;
begin
with TQuery.Create(nil) do
try
DatabaseName := DBname;
SQL.Add("SELECT MAX("+FName+") FROM " + QuotedStr(tbName));
Prepare;
Open;
result := Fields[0].AsInteger + 1;
finally
Close;
Free;
end;
end;

{ Insert record for integer ID}
function quInsertKeySQL_(tbName, KeyField: string; KeyValue: Longint): boolean;
var
i: integer;
str: string;
begin
Result := False;
str := "INSERT INTO "+tbName+" ("+ KeyField + ")"+ " VALUES ("+IntToStr(KeyValue)+")";
for i:=1 to gRptAccess do begin
Result := quExecuteSQL_(str);
if Result then Break;
end;
end;

{ Insert blank record with next value of Key field }
function quInsertBlankSQL_(tbName,fName: string; var id: Longint): boolean;
var
i: integer;
begin
Result := False;
for i:=1 to gRptAccess do begin
id := quGetMaxID_(tbName,fName);
Result := quInsertKeySQL_(tbName,fName,id);
if Result then Break;
end;
end;


 
Sergey Masloff   (2003-01-08 22:52) [11]

Jeer ©
SELECT MAX() - это гарантированные траблы с одинаковыми номерами при многопользовательской работе.



 
Jeer   (2003-01-08 23:00) [12]

Нет - вы не поняли или не вникли в src.

Работа на коллизиях - это вообще один из методов гарантированной работоспособности системы в сложных, малопредсказуемых условиях.
Все мы работаем в Ethernet, где это сплошь и рядом имеет место быть.


 
Sergey Masloff   (2003-01-09 09:50) [13]



да, я код сразу не глядел ;-) Все равно ж практика порочная с этим MAX... ;-)

а зачем у вас цикл в function quInsertKeySQL_()? N попыток пропихнуть в базу то, что не лезет?

а когда вы поняли что такая запись уже есть и надо менять ID - его теперь нужно поменять и у пары сотен Detail-записей которые на этот ID завязаны? Это если последовательное значение - Primary Key. А если нет - по оно скорее всего не Integer а что-то типа KL-12345/02-99 в котором SELECT MAX() вообще неэффективно.

Впрочем, ваш вариант для приведенного примера работает.


 
Jeer   (2003-01-09 19:14) [14]

>Все равно ж практика порочная с этим MAX... ;-)
Иногда просто нет другого выбора (autoinc еще более порочен, генераторов нет и пр)

>а зачем у вас цикл в function quInsertKeySQL_()?
Создается поток N попыток вставки на случай блокировок строки другими такими же потоками (замечу, что речь не о блокировке строки пользователем идет, а о блокировке строки в процессе( порожденным пользователем) изменения строки).

> а когда вы поняли что такая запись уже есть и надо менять ID - его теперь нужно поменять и у пары сотен Detail-

Ничего и нигде менять не надо. Поскольку ID только еще создается и нет ссылок на чего-либо.:))
ID - это и есть primary key исключительно int(word,byte,..)
Так, что select max() весьма эффективно.

Кстати, давным давно решил для себя вопрос о ключах исключительно в пользу искусственных. И ни разу не пожалел:)

Когда-то (много лет назад) проводил тестирование этой технологии на разных СУБД (зачем ? Люблю все измерять - еще Ломоносов сказал: "Наука начинается там, где начинаются измерения").
InterBase, DBF, Paradox (BDE), Access, MySQL, DBISAM, MSDE..

Выяснил, что летает по ней MySQL.

По данной технологии работают до десятка разных многопользовательских программ в диапазоне до 4 лет.
Ни одного сбоя.


 
Sergey Masloff   (2003-01-09 21:52) [15]

Jeer ©
>По данной технологии работают до десятка разных многопользовательских программ в диапазоне до 4 лет.
Ни одного сбоя.

вот это действительно хороший ответ!



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2003.01.27;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.01 c
1-86907
cult
2003-01-16 14:25
2003.01.27
Адрес окна по его хэндлу


14-87045
polizei
2003-01-11 08:40
2003.01.27
У К А ЗА ТЕ Л И !


1-86900
Uncle Archi
2003-01-14 22:33
2003.01.27
BIOS


14-87126
Дмитрий К.К.
2002-12-30 06:03
2003.01.27
Именинники 30 декабря


1-86784
БД
2003-01-18 08:25
2003.01.27
Plese help me now!





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