![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как реализовать неперекрываемость данных?
Riko © (2003-08-05 11:01:00)
При создании записи в многопользовательском режиме работы есть вероятность что два пользователя получат один и тот-же номер вносимого документа....В результате возникнет перекрытие данных одного юсера другим, более поздним.
Ну например:
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;
Но если в момент заполнения документа другой , более шустрый юсер , получит номер таким-же способом, то его номер будет идентичен предыдущему.....КАК БОРОТЬСЯ? Заранее спасибо.
Riko (2003-08-13 09:21:00) [1]
Огромное спасибо, пробую....
Zacho (2003-08-12 10:22:00) [2]
> Riko © (12.08.03 10:10)
Если ты выбрал этот способ, то на всякий случай еще раз (и немного подробнее) повторю:
Получение номера и вставку документа нужно делать в отдельной и как можно более короткой транзакции с блокированием всей таблицы, т.е. параметры транзакции должны быть типа:
write
consistency
wait
lock_write=имя_таблицы
exclusive
Riko (2003-08-12 10:10:00) [3]
ID и номер дока и так на разных полях, за табличные беспокойств нет.
ID генератор и так стоит, вопрос идет о неперекрываемости номера документов, к примеру накладной.... Если заполнять дырочки впоследствии, то нумерация документов будет запутанной, то -есть более поздний документ может быть с меньшим номером и т.п. Наиболее безопасным мне кажется генерация номера документа при Commit (совет Zacho ©), а на печать не посылать без проведения транзакции...
Всем спасибо...
HSolo (2003-08-06 15:23:00) [4]
Тогда уж, может, 3 поля?
№ документа (Int)
префикс (varchar)
служебное (int или char(1))
И ничего отсекать не надо
MsGuns (2003-08-06 12:44:00) [5]Дополнение к 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 выполнять на клиенте или вообще на сервере с возвращением одного поля как реального №
Практика говорит о том, что такая система нумерации в делопроизводстве удовлетворяет даже самых изобретательных бухгалтеров или секретарш ;))
Ann (2003-08-06 11:13:00) [6]
:) нет, мне это не надо :))
Sir Alex (2003-08-06 11:10:00) [7]
ОЙ, чё-т я не посмотрел, кто запостил жту тему, подумал, что это все надо Ann... 8)
Sir Alex (2003-08-06 11:07:00) [8]Тогда нет проблем:
В БД создать генератор:
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 есть возможность в дизайнере указать генератор и ключевое поле, тогда вообще не надо беспокоиться о кодах.
Успехов...
Ann (2003-08-06 10:25:00) [9]
> MsGuns © (05.08.03 13:06)
> >Ann © (05.08.03 11:02)
> >бороться с этим лучше использованием генераторов.
> К тому же что делать 1 января, когда нумерация должна сбрасываться
> ?
я не говорила про нумерацию документов, я говорила про ID...
а нумеровать документы можно или в другом поле или просто в вычисляемом поле (смотря что требуется...)
Sergey13 (2003-08-06 10:09:00) [10]
Еще могу посоветовать разнести понятие Id и Номер документа по разным полям.
Riko (2003-08-06 10:01:00) [11]
Спасибо всем огромное, более или менее картинка ясна...
Zacho (2003-08-05 14:07:00) [12]
> 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
> Да и вообще не советовал бы никому завязываться на уникальность
> номеров в делопроизводстве - могут, еще как могут встречаться
> документы с одинаковым номером !
Полностью согласен ;-)
MsGuns (2003-08-05 13:46:00) [13]
>Zacho © (05.08.03 13:19)
Совет хороший, но не панацейный. В частности не решает проблем заполненности "дырок" (когда документ был удален, а на его место надо добавить новый с тем же номером) Да и вообще не советовал бы никому завязываться на уникальность номеров в делопроизводстве - могут, еще как могут встречаться документы с одинаковым номером ! (Например, выписаны 2 варианта накладных покупателю, один из которых впоследствии будет удален)
Zacho (2003-08-05 13:19:00) [14]
> MsGuns © (05.08.03 13:06)
> Но постятся записи последовательно, поэтому в проге должен
> быть предусмотрена ситуация возврата "опоздавшим" узерам
> незаписанного в БД документа с соотв.сообщением. Либо формировать
> этот номер автоматически в цикле, модифицируя № каждый раз
> пока не запостится.
Imho, самый "правильный" способ "бездырочной" нумерации - получать новый номер после окончания создания документа непосредственно перед вставкой записей в БД с помощью SELECT MAX(..)+1 .. ,все это в отдельной короткой транзакции SNAPSHOT TABLE STABILITY WAIT с явным резервированием таблицы. Тогда не будет ни каких конфликтов, и никакие циклы не нужны.
АлексейК (2003-08-05 13:10:00) [15]
А какая база данных то?
MsGuns (2003-08-05 13:06:00) [16]
Трабла от недостатка опыта. Во-первых, в промежуток времени один
и тот же № действительно могут ввести хоть 100 человек (что в реале, весьма маловероятно - максимум 2-3), тем более, что в некоторых программых он предоставляется узеру автоматически.
Но постятся записи последовательно, поэтому в проге должен быть предусмотрена ситуация возврата "опоздавшим" узерам незаписанного в БД документа с соотв.сообщением. Либо формировать этот номер автоматически в цикле, модифицируя № каждый раз пока не запостится.
>Ann © (05.08.03 11:02)
>бороться с этим лучше использованием генераторов.
Для нумерации "живых" документов совет рискованный. Получать "рваные" последовательности номеров физических документов - это не каждому рук-лю или главбуху придется по душе.
К тому же что делать 1 января, когда нумерация должна сбрасываться ?
Zacho (2003-08-05 11:12:00) [17]
Еще совет: почитай статьи на http://wwww.ibase.ru/develop.htm, особенно касающиеся транзакций и генераторов.
Ну и, естественно, что-нибудь про первичные ключи и уникальные индексы.
Соловьев (2003-08-05 11:06:00) [18]
и блокировкой записи - это уже настройка уровня изоляции транзакции.
Ann (2003-08-05 11:02:00) [19]
бороться с этим лучше использованием генераторов.