Вниз
Скачать: CL | DM;

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

← →
Вованчик   (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 вся ветка

Скачать: CL | DM;



Память: 0.49 MB
Время: 0.011 c
1-86776
Бук
2003-01-16 07:26
2003.01.27
Иконки для формы


3-86712
anton2v
2003-01-09 16:31
2003.01.27
Связанные таблицы


4-87226
Bukerman
2002-12-13 11:04
2003.01.27
Убивание процесса или как найти дочерние процессы


14-87058
Николай Быков
2003-01-08 04:41
2003.01.27
В сети что ли нет ресурсов с материалами по.....


7-87168
Эли
2002-11-15 18:21
2003.01.27
переключение языка клавиатуры




   Наверх