Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.09.04;
Скачать: CL | DM;

Вниз

Как реализовать неперекрываемость данных?   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.021 c
3-10634
Avreliy
2003-08-12 18:13
2003.09.04
Левое внешнее объединение 2х хранимых процедур


8-10844
dronas555
2003-05-06 12:08
2003.09.04
Формат BMP


1-10819
BlackTiger
2003-08-21 13:05
2003.09.04
Помогите побороть Automation-сервер! Очень нужно!


7-11012
AdMiRaL
2003-06-22 20:54
2003.09.04
Faili


1-10801
Zheks
2003-08-22 09:43
2003.09.04
После экзэшника