Форум: "Базы";
Текущий архив: 2003.09.04;
Скачать: [xml.tar.bz2];
ВнизКак реализовать неперекрываемость данных? Найти похожие ветки
← →
Riko (2003-08-05 11:01) [0]При создании записи в многопользовательском режиме работы есть вероятность что два пользователя получат один и тот-же номер вносимого документа....В результате возникнет перекрытие данных одного юсера другим, более поздним.
Ну например:
function TFNewNakl.GetLasNumProd:Integer;
begin
IBQuery1.Active:=false;
IBQuery1.SQL.Clear;
IBQuery1.SQL.Add(" SELECT DISTINCT MAX( TABLE.NUM )");
IBQuery1.SQL.Add(" MAX_NUM FROM TABLE");
IBQuery1.Active:=true;
Result:=IBQuery1.Fields[0].AsInteger+1;//присвоили новый номер
end;
После чего заполняется документ и по окончании:
IBTransaction1.Commit;
Но если в момент заполнения документа другой , более шустрый юсер , получит номер таким-же способом, то его номер будет идентичен предыдущему.....КАК БОРОТЬСЯ? Заранее спасибо.
← →
Ann (2003-08-05 11:02) [1]бороться с этим лучше использованием генераторов.
← →
Соловьев (2003-08-05 11:06) [2]и блокировкой записи - это уже настройка уровня изоляции транзакции.
← →
Zacho (2003-08-05 11:12) [3]Еще совет: почитай статьи на http://wwww.ibase.ru/develop.htm , особенно касающиеся транзакций и генераторов.
Ну и, естественно, что-нибудь про первичные ключи и уникальные индексы.
← →
MsGuns (2003-08-05 13:06) [4]Трабла от недостатка опыта. Во-первых, в промежуток времени один
и тот же № действительно могут ввести хоть 100 человек (что в реале, весьма маловероятно - максимум 2-3), тем более, что в некоторых программых он предоставляется узеру автоматически.
Но постятся записи последовательно, поэтому в проге должен быть предусмотрена ситуация возврата "опоздавшим" узерам незаписанного в БД документа с соотв.сообщением. Либо формировать этот номер автоматически в цикле, модифицируя № каждый раз пока не запостится.
>Ann © (05.08.03 11:02)
>бороться с этим лучше использованием генераторов.
Для нумерации "живых" документов совет рискованный. Получать "рваные" последовательности номеров физических документов - это не каждому рук-лю или главбуху придется по душе.
К тому же что делать 1 января, когда нумерация должна сбрасываться ?
← →
АлексейК (2003-08-05 13:10) [5]А какая база данных то?
← →
Zacho (2003-08-05 13:19) [6]
> MsGuns © (05.08.03 13:06)
> Но постятся записи последовательно, поэтому в проге должен
> быть предусмотрена ситуация возврата "опоздавшим" узерам
> незаписанного в БД документа с соотв.сообщением. Либо формировать
> этот номер автоматически в цикле, модифицируя № каждый раз
> пока не запостится.
Imho, самый "правильный" способ "бездырочной" нумерации - получать новый номер после окончания создания документа непосредственно перед вставкой записей в БД с помощью SELECT MAX(..)+1 .. ,все это в отдельной короткой транзакции SNAPSHOT TABLE STABILITY WAIT с явным резервированием таблицы. Тогда не будет ни каких конфликтов, и никакие циклы не нужны.
← →
MsGuns (2003-08-05 13:46) [7]>Zacho © (05.08.03 13:19)
Совет хороший, но не панацейный. В частности не решает проблем заполненности "дырок" (когда документ был удален, а на его место надо добавить новый с тем же номером) Да и вообще не советовал бы никому завязываться на уникальность номеров в делопроизводстве - могут, еще как могут встречаться документы с одинаковым номером ! (Например, выписаны 2 варианта накладных покупателю, один из которых впоследствии будет удален)
← →
Zacho (2003-08-05 14:07) [8]
> MsGuns © (05.08.03 13:46)
> Совет хороший, но не панацейный. В частности не решает проблем
> заполненности "дырок" (когда документ был удален, а на его
> место надо добавить новый с тем же номером)
Эта проблема тоже вполне решаема - вместо SELECT MAX(doc_num)+1 ... делаем
SELECT MIN(T.doc_num)+1
FROM TABLE T
LEFT JOIN TABLE T1 ON T1.DOC_NUM=T.DOC_NUM+1
WHERE T1.DOC_NUM IS NULL
> Да и вообще не советовал бы никому завязываться на уникальность
> номеров в делопроизводстве - могут, еще как могут встречаться
> документы с одинаковым номером !
Полностью согласен ;-)
← →
Riko (2003-08-06 10:01) [9]Спасибо всем огромное, более или менее картинка ясна...
← →
Sergey13 (2003-08-06 10:09) [10]Еще могу посоветовать разнести понятие Id и Номер документа по разным полям.
← →
Ann (2003-08-06 10:25) [11]
> MsGuns © (05.08.03 13:06)
> >Ann © (05.08.03 11:02)
> >бороться с этим лучше использованием генераторов.
> К тому же что делать 1 января, когда нумерация должна сбрасываться
> ?
я не говорила про нумерацию документов, я говорила про ID...
а нумеровать документы можно или в другом поле или просто в вычисляемом поле (смотря что требуется...)
← →
Sir Alex (2003-08-06 11:07) [12]Тогда нет проблем:
В БД создать генератор:
CREATE GENERATOR GEN_TABLE_ID;
function TFNewNakl.GetLasNumProd:Integer;
begin
IBQuery1.Active:=false;
IBQuery1.SQL.Clear;
IBQuery1.SQL.Add(" SELECT GEN_ID(GEN_TABLE_ID,1) FROM RDB$DATABASE");
IBQuery1.Active:=true;
Result:=IBQuery1.Fields[0].AsInteger;//присвоили новый номер
end;
Если используются компоненты FIBPlus, можно еще проще:
function TFNewNakl.GetLasNumProd:Integer;
begin
( "GEN_TABLE_ID",1)Тогда нет проблем:
В БД создать генератор:
CREATE GENERATOR GEN_TABLE_ID;
function TFNewNakl.GetLasNumProd:Integer;
begin
IBQuery1.Active:=false;
IBQuery1.SQL.Clear;
IBQuery1.SQL.Add(" SELECT GEN_ID(GEN_TABLE_ID,1) FROM RDB$DATABASE");
IBQuery1.Active:=true;
Result:=IBQuery1.Fields[0].AsInteger;//присвоили новый номер
end;
Если используются компоненты FIBPlus, можно еще проще:
function TFNewNakl.GetLasNumProd:Integer;
begin
Result:=FIBDatabase.Gen_ID ("GEN_TABLE_ID",1)
end;
P.S. И еще у FIBDataSet есть возможность в дизайнере указать генератор и ключевое поле, тогда вообще не надо беспокоиться о кодах.
Успехов...
← →
Sir Alex (2003-08-06 11:10) [13]ОЙ, чё-т я не посмотрел, кто запостил жту тему, подумал, что это все надо Ann... 8)
← →
Ann (2003-08-06 11:13) [14]:) нет, мне это не надо :))
← →
MsGuns (2003-08-06 12:44) [15]Дополнение к Sergey13 © (06.08.03 10:09):
Советовал бы добавить еще одно поле дополнительно к № документа (которое Int), которое я назвал префикс документа и обозначить его VARCHAR c длиной, допустим, 24, причем первый символ-всегда "служебный". Для чего ?
Например, накладные
Реальный Поля таблицы БД
№ NUMBER(LongInt) ( 24) Дополнение к Sergey13 © (06.08.03 10:09):
Советовал бы добавить еще одно поле дополнительно к № документа (которое Int), которое я назвал префикс документа и обозначить его VARCHAR c длиной, допустим, 24, причем первый символ-всегда "служебный". Для чего ?
Например, накладные
Реальный Поля таблицы БД
№ NUMBER(LongInt) NUMNDX VARCHAR(24)
-------------------------------------------------------
13786Возврат 13786 tВозврат
Возврат13786 13786 lВозврат
Анализ и отсекание упр.символа l/t выполнять на клиенте или вообще на сервере с возвращением одного поля как реального №
Практика говорит о том, что такая система нумерации в делопроизводстве удовлетворяет даже самых изобретательных бухгалтеров или секретарш ;))
← →
HSolo (2003-08-06 15:23) [16]Тогда уж, может, 3 поля?
№ документа (Int)
префикс (varchar)
служебное (int или char(1))
И ничего отсекать не надо
← →
Riko (2003-08-12 10:10) [17]ID и номер дока и так на разных полях, за табличные беспокойств нет.
ID генератор и так стоит, вопрос идет о неперекрываемости номера документов, к примеру накладной.... Если заполнять дырочки впоследствии, то нумерация документов будет запутанной, то -есть более поздний документ может быть с меньшим номером и т.п. Наиболее безопасным мне кажется генерация номера документа при Commit (совет Zacho ©), а на печать не посылать без проведения транзакции...
Всем спасибо...
← →
Zacho (2003-08-12 10:22) [18]
> Riko © (12.08.03 10:10)
Если ты выбрал этот способ, то на всякий случай еще раз (и немного подробнее) повторю:
Получение номера и вставку документа нужно делать в отдельной и как можно более короткой транзакции с блокированием всей таблицы, т.е. параметры транзакции должны быть типа:
write
consistency
wait
lock_write=имя_таблицы
exclusive
← →
Riko (2003-08-13 09:21) [19]Огромное спасибо, пробую....
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2003.09.04;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.01 c