Форум: "Базы";
Текущий архив: 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.009 c