Re: Multi Doc Numeration
Oleg LOA wrote: В данном случае можно создать генератор номеров у которго будет своя таблица. Я когда-то даже придумал такой, http://konstb.newmail.ru/interbase/gennum.htm а все тут спросили: ну и зачем? :-)
Re: Multi Doc Numeration
Константин [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] А если серьёзно, кто что думает по этому поводу ? Предлагаю подумать на следующие темы самостоятельно; 1) Сериализация доступа к механизму создания новых номеров 2) Параметрытранзакции lock_writе и wait
Re: Multi Doc Numeration
Тебе нужна сериализация. При генерации нового документа запускаешь транзакцию с параметрами wait lock_write=имя_некой_таблицы protected Такие транзакции будут сериализованы. Внутри вычисляешь номер нового документа обычными sql операторами. -- --- Home Page http://ok.novgorod.net/ap ---
Re: Multi Doc Numeration
Константин wrote: Вопрос: когда я, с таким подходом, напорюсь на грабли ? И на какие ? CREATE PROCEDURE DOC_PROVODKA ( doc_id bigint) as declare variable i bigint; declare variable tid bigint; declare variable ftid bigint; begin // Stop - семафор, // sleep - UDF наподобие Application.ProcessMessages в Delphi while (gen_id(stop, 0) 0)) do sleep(100); i = gen_id(stop, 1); Здесь. Запросто можешь получить в i не 1, как ты думаешь, а 2,3...N select TYPE_ID, to_id from vw_doc where id = :doc_id into :tid, :ftid; select max(num) from doc where TYPE_ID = :tid into :i; Здесь. Либо лишний индекс либо будешь курить бамбук. update doc set num = z(:i) + 1 where id = :doc_id; select max(UserNUM) from doc where TYPE_ID = :tid and to_id = :ftid into :i; Здесь. Либо лишний индекс либо будешь курить бамбук. update vw_doc set UserNUM = z(:i) + 1 where id = :doc_id; i = gen_id(stop, -1); Здесь. Запросто можешь получить в i не 0, как ты думаешь, а 1,2,3...N end А если серьёзно, кто что думает по этому поводу ? Очередной лисапет с до боли знакомыми квадратными колёсами. Если можно, подскажите варианты решения ... желательно опробованные на практике ... Раз уж тебе приспичило создавать бутылочные горлышки в системе и выстраивать всех в очередь, заведи табличку Номера Тип документа not null PK Следующий номер int и получай номер как-нибудь так: Starttransaction Repeat Try Update Номера Set Следующий номер = Следующий номер +1 Where Тип документа = Чаво нада; Select Следующий номер From Номера Where Тип документа = Чаво нада; Получилося:=True; Except Do Получилося:=False; end; Until Получилося; Тыр-пыр-восемь дыр, ну там инсёрт или ещё чего нада для щастья Commit; Это для read_commited. А ващета про генерацию людских, а не искуственных номеров, подробные статейки есть, и вроде даже у ДК на сайте... -- Regards. Ded.
Re: Multi Doc Numeration
Alexey Popov wrote: Тебе нужна сериализация. При генерации нового документа запускаешь транзакцию с параметрами wait lock_write=имя_некой_таблицы protected Такие транзакции будут сериализованы. Внутри вычисляешь номер нового документа обычными sql операторами. Мля, на колу мочало, начинай сначала, 2001-й год вроде, учител Йода вернулся. Чтоб удержать одну запись, крайне необходимо блокировать таблицу целиком. МП, крутани ПНХ движок до отсечки, а? -- Regards. Ded.
Re: Multi Doc Numeration
Константин пишет: Hi, многоуважаемый All! Есть табличка шапок документов скажем CREATE TABLE DOC ( IDBIGINT, TYPE_ID BIGINT, DATE_DOC TIMESTAMP, NUM BIGINT, UserNUM BIGINT, From_ID BIGINT, TO_ID BIGINT, ... ); 1) Есть условие что нумерация (NUM) для каждого типа документов (type_id) должна быть уникальной 2) Есть условие что для каждого контрагента получателя (To_ID), в зависимости от типа документа (Type_id) идёт своя нумерация Привет! Заведи таблицу с номерами для разных получателей и типов документов: CREATE TABLE DOC_NUM( TO_ID BIGINT NOT NULL, TYPE_ID BIGINT NOT NULL, MAX_DOC_NUM INT NOT NULL); ALTER TABLE DOC_NUM ADD CONSTRAINT PK_DOC_NUM PRIMARY KEY (TO_ID, TYPE_ID); В триггере на BI что то типа: ... IF (EXISTS(SELECT 1 FROM DOC_NUM WHERE TO_ID = NEW.TO_ID AND TYPE_ID = NEW.TYPE.ID)) THEN UPDATE DOC_NUM SET MAX_DOC_NUM = MAX_DOC_NUM + 1 WHERE TO_ID = NEW.TO_ID AND TYPE_ID = NEW.TYPE.ID; ELSE INSERT INTO DOC_NUM(TO_ID, TYPE_ID, MAX_DOC_NUM) VALUES (NEW.TO_ID, NEW.TYPE_ID, 1); SELECT MAX_DOC_NUM FROM DOC_NUM WHERE TO_ID = NEW.TO_ID AND TYPE_ID = NEW.TYPE.ID INTO NEW.NOM; И пиши в коротких R/C транзакциях. В случае облома - sleep(100) и пробуй еще. -- Удачи! Shiliaev Ruslan
Re: Multi Doc Numeration
Ded wrote: Такие транзакции будут сериализованы. Внутри вычисляешь номер нового документа обычными sql операторами. Мля, на колу мочало, начинай сначала, 2001-й год вроде, учител Йода вернулся. Чтоб удержать одну запись, крайне необходимо блокировать таблицу целиком. МП, крутани ПНХ движок до отсечки, а? Если изменяющие транзакции быстрые и не висячие то никаких узких мест. Блокировать можно не основную таблицу, а вспомогательную. Тогда блокировка будет идти только при создании нового документа, но это если номера не редактируются. -- --- Home Page http://ok.novgorod.net/ap ---
Re: Multi Doc Numeration
Что если создавать для каждого нового типа документов свой генератор, по аналогии как в Firebird создаются домены RDB$X
Re: Multi Doc Numeration
Константин wrote: По типу документа ещё можно ... А по контрагенту ? Что скажут кодописатели насчёт ~5000 генераторов ? :) Я не знаю точно, но какое-то ограничение на к-во генераторов существует же ... Странный ты, ей-богу. Тыщу раз говорили ведь - при создании документов они не нумеруются человеческими номерами. Нумеруются при утверждении и как правило скопом, отдельной функцией. Потому что там, к бабке не ходи, упорядоченность по номерам должна соответствовать упорядоченности по датам. И если более ранним номера не присвоены, более поздние надо тоже придержать. А для связей держут искусственные ключи, на одном генераторе на всех. А пользователю его не показывают. Или показывают пока не присвоен человеческий номер, как нибудь типа 'Проект N '||ID. Ну и заведи ты для выходной нумерации табличку каталог типов, нужен составной ключ - m:n тип-контрагент, инсёрть туда на инсёрт-триггерах парентов с полем текущий номер 0, будет у тебя в ней хоть 5 000 000 псевдогенераторов, которые будешь лочить-инкать и читать в функции нумерации. Это всегда делается через захватываемый ресурс, а не внетранзакционный генератор. Даже если ограничений по дате нет. Двоечник на любое - Надо! отвечает - Зачем? Хреновый из тебя двоечник. Не думаешь - зачем. Пилить бросаешься. -- Regards. Ded.
Re: Multi Doc Numeration
Константин пишет: // Stop - семафор, // sleep - UDF наподобие Application.ProcessMessages в Delphi while (gen_id(stop, 0) 0)) do sleep(100); i = gen_id(stop, 1); Хм, sleep... Чего уж мелочиться, давай сразу CreateMutex/WaitForSingleObject/ReleaseMutex :) -- wbr, ps ps-at-azs-ru