Модераторы: Akella

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Изменение значения генератора, FireBird+FIBPlus 
:(
    Опции темы
former
Дата 13.7.2009, 21:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



Master-detail.
В триггере BeforeInsert master-таблицы выполняется проверка данных и, в случае ошибки, вызывается исключение. 
Изначально генерацию первичного ключа выполнял в триггере после всех проверок, однако потребовалось получать id добавленной записи для detale-таблицы и обновлять только измененную запись. Стал использовать AutoUpdateOptions компонента FIBDataSet master-таблицы. Но в этом случае генератор изменяется до проверки исключений в триггере. Получается, что если несколько раз возникало исключение, то номер записи будет больше на число исключений. 
Как избежать многократного изменения значения генератора, но при этом сохранить возможность получения ключа для detail-таблицы и обновления добавленной записи?
Active - false/true не предлагать.


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
aryab
Дата 21.7.2009, 09:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 21.7.2009

Репутация: 1
Всего: 1



Для FireBird 2.0 и больше

Код

insert into Table (...) 
values(...)
RETURNING Id;


после Post  поле id добавленной записи будет заполнено значением заполненным в базе
PM MAIL WWW Jabber   Вверх
Deniz
Дата 8.9.2009, 07:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 22
Всего: 44



former, вопрос еще актуален?


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
former
Дата 8.9.2009, 08:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



Deniz, если есть еще вариатны, с удовольствием их выслушаю.


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
Akella
Дата 8.9.2009, 09:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 20
Всего: 329



former, я вообще не понимаю, зачем так делать, что вызов исключения влияет на срабатывание генератора?
Ты хоть бы код показал
PM MAIL   Вверх
former
Дата 8.9.2009, 09:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



Цитата(Akella @  8.9.2009,  09:20 Найти цитируемый пост)
former, я вообще не понимаю, зачем так делать, что вызов исключения влияет на срабатывание генератора?

Именно. В AutoUpdateOptions есть свойство WhenGetGenID, которое имеет wgNever (не используется), wgBeforePost (перед вызовом Post), wgOnNewRecord (при вызове Insert). 
У меня контроль данных осуществляется в триггерах с вызовом исключений. Получается следующее:
wgOnNewRecord
Вызываем Insert, генерируется значение ключа, вводим данные, вызываем Post, получаем исключение, а генератор уже изменен.
wgBeforePost
Вызываем Insert, вводим данные, вызываем Post (генерируется значение ключа), получаем исключение, а генератор уже изменен.
А для выполнения Refresh необходимо значение ключа добавленной записи.
Цитата(Akella @  8.9.2009,  09:20 Найти цитируемый пост)
Ты хоть бы код показал 

ИХМО:А код тут не причем.


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
Akella
Дата 8.9.2009, 10:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 20
Всего: 329



у компоненты базы данных (FibDataBase) есть метод получения кода генератора, его и используй. В этом случае триггер не будешь трогать.

Добавлено через 2 минуты и 33 секунды
Пример
Код

  table1.Insert;
  table1.FBN('ID') :=  dbScanFilter.Gen_Id('my_super_generator', 1, dbScanFilter.DefaultTransaction);
  table1.FBN('Akella') := 'CyberWolf';
  table1.post;


Добавлено через 4 минуты и 15 секунд
Цитата(former @  8.9.2009,  09:43 Найти цитируемый пост)
ИХМО:А код тут не причем. 

а ты поставь код получения значения генератора после кода вызова исключения smile 
тогда в случае исключения код получения значения генератора не будет срабатывать smile
PM MAIL   Вверх
former
Дата 8.9.2009, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



Цитата(Akella @  8.9.2009,  10:31 Найти цитируемый пост)
у компоненты базы данных (FibDataBase) есть метод получения кода генератора, его и используй. В этом случае триггер не будешь трогать.

В твоем коде, в случае возникновения исключения и повторного вызова метода Post, будет сгенерировано новое значение генератора. А если возникнет несколько исключений, то вместо 15-го мы запишем запись с ключем номер 25. Не очень хочется "транжирить" генератор.
Цитата(Akella @  8.9.2009,  10:31 Найти цитируемый пост)
а ты поставь код получения значения генератора после кода вызова исключения smile 
тогда в случае исключения код получения значения генератора не будет срабатывать smile 

Именно так я и делаю:
Код

CREATE OR ALTER TRIGGER COURSES_BI FOR COURSES
ACTIVE BEFORE INSERT POSITION 0
AS
begin
  if (new.coursename is null or  new.coursename = '') then exception courses_coursename_null;
  else if (new.hours is null or new.hours = '') then exception courses_hours_null;
  else if (exists(select * from courses where (coursename = new.coursename) and
           (hours = new.hours) and (departmentid = new.departmentid))) then
    exception courses_duplicate;
  else if (new.courseid is null) then
    new.courseid = gen_id(gen_courses_id,1);
end
^

Akella, для Refresh тогда откуда возьмется ключ записи? 

Это сообщение отредактировал(а) former - 8.9.2009, 10:51


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
Akella
Дата 8.9.2009, 11:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 20
Всего: 329



Цитата(former @  8.9.2009,  10:49 Найти цитируемый пост)
Akella, для Refresh тогда откуда возьмется ключ записи? 

А при чём здесь генератор?
PM MAIL   Вверх
former
Дата 8.9.2009, 11:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



Цитата(Akella @  8.9.2009,  11:17 Найти цитируемый пост)
А при чём здесь генератор? 

А вот причем:
Код

SELECT
    C.COURSEID,
    C.COURSENAME,
    C.HOURS,
    C.DEPARTMENTID,
    D.SDEPNAME,
    C.CSACTUALITY
FROM COURSES  AS C
    INNER JOIN DEPARTMENTS AS D
      ON D.DEPARTMENTID = C.DEPARTMENTID
WHERE C.COURSEID = :OLD_COURSEID

Обрати внимание на последнюю строку.


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
Akella
Дата 8.9.2009, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 20
Всего: 329



Refresh выполняется после чего? После Update!
абчём говорит эта строка?
Код

WHERE C.COURSEID = :OLD_COURSEID


Добавлено через 1 минуту и 1 секунду
Если речь идёт об insert, то нужн что делать? Правильно - pFibDataSet1.CloseOpen();
PM MAIL   Вверх
Deniz
Дата 8.9.2009, 13:04 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 22
Всего: 44



Цитата(former @  8.9.2009,  13:49 Найти цитируемый пост)
Не очень хочется "транжирить" генератор.
Вот с этого все и начинается  smile
Попробуй посчитать сколько примерно сотен лет нужно чтобы занять весь генератор при условии что 1 запись вставляется каждую секунду в режиме 24х7.
Далее, не совсем понятно почему часть бизнес логики (по обработке 1 записи) вынесена в триггер, а часть остается на клиенте.
Далее, такие проверки как в триггере, можно оформить как not null на поле, а на клиенте преобразовывать пустые в null (есть вроде такая опция в FIBPlus)
Далее, удивил код с 
Код
exception courses_duplicate;
это реальные грабли, причем получишь ими, когда люди начнут работать толпой, лучше пользуй уникальные индексы.
И наконец, если мне не изменяет память, то после исключения на POST, DataSet остается в режиме редактирования, и повторно onNewRecord не вызывается, если только ты сам не делаешь Cancel.


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
former
Дата 8.9.2009, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



Цитата(Deniz @  8.9.2009,  13:04 Найти цитируемый пост)
Попробуй посчитать сколько примерно сотен лет нужно чтобы занять весь генератор при условии что 1 запись вставляется каждую секунду в режиме 24х7.

Порядка 30 млн. записей в год. В некоторых случаях мне нужна четкая последовательность нумерации.
Цитата(Deniz @  8.9.2009,  13:04 Найти цитируемый пост)
Далее, не совсем понятно почему часть бизнес логики (по обработке 1 записи) вынесена в триггер, а часть остается на клиенте.
Далее, такие проверки как в триггере, можно оформить как not null на поле, а на клиенте преобразовывать пустые в null (есть вроде такая опция в FIBPlus)

Где такое написано, что преобразование идет на клиенте? Клиент только передает данные.
Цитата(Deniz @  8.9.2009,  13:04 Найти цитируемый пост)
это реальные грабли, причем получишь ими, когда люди начнут работать толпой, лучше пользуй уникальные индексы.
И наконец, если мне не изменяет память, то после исключения на POST, DataSet остается в режиме редактирования, и повторно onNewRecord не вызывается, если только ты сам не делаешь Cancel. 

Цитата(Deniz @  8.9.2009,  13:04 Найти цитируемый пост)
это реальные грабли, причем получишь ими, когда люди начнут работать толпой, лучше пользуй уникальные индексы.

Это если уникальность в одном поле. А когда уникальность по нескольким полям то как?
Какие грабли?
Цитата(Deniz @  8.9.2009,  13:04 Найти цитируемый пост)
И наконец, если мне не изменяет память, то после исключения на POST, DataSet остается в режиме редактирования, и повторно onNewRecord не вызывается, если только ты сам не делаешь Cancel. 

Да, именно если пользователь делает Cancel.

Это сообщение отредактировал(а) former - 8.9.2009, 14:04


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
former
Дата 8.9.2009, 14:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



Цитата(Akella @  8.9.2009,  12:50 Найти цитируемый пост)
Refresh выполняется после чего? После Update!
абчём говорит эта строка?

В опциях стоит RefreshAfterPost:=true. Если установлено свойство WhenGetGenID в wgBeforePost или wgOnNewRecord, Id для обновления берется из него.
А если wgNever, то можно подсунуть Refresh-у номер записи и он ее обновит.
Цитата(Akella @  8.9.2009,  12:50 Найти цитируемый пост)
Если речь идёт об insert, то нужн что делать? Правильно - pFibDataSet1.CloseOpen(); 

Если делать pFibDataSet1.CloseOpen(), то потом нужно будет искать добавленную запись. А так, сразу попадаем на нужную запись. Тем более весь набор данных заново открывать.

Это сообщение отредактировал(а) former - 8.9.2009, 14:22


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
Deniz
Дата 8.9.2009, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 22
Всего: 44



Цитата(former @  8.9.2009,  17:02 Найти цитируемый пост)
Порядка 30 млн. записей в год.
это твой реальный прирост?

Цитата(former @  8.9.2009,  17:02 Найти цитируемый пост)
В некоторых случаях мне нужна четкая последовательность нумерации.
зачем? Поподробнее можно? Обычно id кроме разработчиков никто не видит.

Цитата(former @  8.9.2009,  17:02 Найти цитируемый пост)
Это если уникальность в одном поле. А когда уникальность по нескольким полям то как?
а что уникальные составные ключи отменили? Из Firebird-2.0-LangRef:
Код
CREATE [UNIQUE] [ASC[ENDING] | [DESC[ENDING]] INDEX indexname
ON tablename
{ (colname [, colname ...]) | COMPUTED BY (expression) }


Цитата(former @  8.9.2009,  17:02 Найти цитируемый пост)
Какие грабли?
Запрос 
Код
if (exists(select * from courses ...) then exception courses_duplicate;
работает в контексте транзакции, т.е. на момент запроса в базе уже может быть такая запись, в неподтвержденной транзакции, и твой запрос ее не увидит, а потом транзакция подтвердится и ты получишь 2 одинаковые записи.

Если уж так необходимо гарантировано соблюсти последовательность, то оформить insert into в хранимку с предварительной проверкой и последующей вставкой. Результат храминки или ID или код ошибки (например отрицательный).



--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
Akella
Дата 8.9.2009, 15:13 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 20
Всего: 329



Цитата(former @  8.9.2009,  14:02 Найти цитируемый пост)
В некоторых случаях мне нужна четкая последовательность нумерации.

нельзя так с генераторами

Цитата(former @  8.9.2009,  14:02 Найти цитируемый пост)
А когда уникальность по нескольким полям то как?

индексы, индексы...


Цитата(former @  8.9.2009,  14:18 Найти цитируемый пост)
Если делать pFibDataSet1.CloseOpen(), то потом нужно будет искать добавленную запись. А так, сразу попадаем на нужную запись. Тем более весь набор данных заново открывать.

Ты хочешь сказать, что после добавления, если выполнить refresh, то в наборе данных ты увидишь запись? Хм...



Цитата(Deniz @  8.9.2009,  14:39 Найти цитируемый пост)
зачем? Поподробнее можно? Обычно id кроме разработчиков никто не видит.

И не должен видеть, можно показывать в редких случаях.


Ты этот код понимаешь? Для чего он?
Код
WHERE C.COURSEID = :OLD_COURSEID


Почитай про OLD_, NEW_ и MAS_ в докементации к фибам.


И ты вообще знаешь для чего рефреш?

Ты не увидишь новой записи в НД, пока не переоткроешь его.

Добавлено через 1 минуту и 11 секунд
Цитата(former @  8.9.2009,  14:18 Найти цитируемый пост)
Если делать pFibDataSet1.CloseOpen(), то потом нужно будет искать добавленную запись.

Опять же, посмотри, что за параметр можно вставить в скобки CloseOpen()
PM MAIL   Вверх
former
Дата 9.9.2009, 21:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



Цитата(Deniz @  8.9.2009,  14:39 Найти цитируемый пост)
а что уникальные составные ключи отменили?

Цитата(Akella @  8.9.2009,  15:13 Найти цитируемый пост)
индексы, индексы...

Согласен.
Цитата(Deniz @  8.9.2009,  14:39 Найти цитируемый пост)
работает в контексте транзакции, т.е. на момент запроса в базе уже может быть такая запись, в неподтвержденной транзакции, и твой запрос ее не увидит, а потом транзакция подтвердится и ты получишь 2 одинаковые записи.

А как же область видимости транзакции? При возникновении исключения у меня выполняется Cancel в соответствующих событиях DataSet. Кроме того, открываем Хелен Борри (2-е издание) на стр. 700 и читаем, читаем...
Цитата(Akella @  8.9.2009,  15:13 Найти цитируемый пост)
нельзя так с генераторами

Цитата(Akella @  8.9.2009,  15:13 Найти цитируемый пост)
И не должен видеть, можно показывать в редких случаях.

Почему? Ведь если в качестве ключа использовать другие уникальные данные, показывать их можно, так почему номер нельзя?
Я же объяснил, что требуется четкая последовательность регистрационных карт. Есть определенная процедура (в смысле регламент) исключения и удаления регистрационной карты.
Цитата(Akella @  8.9.2009,  15:13 Найти цитируемый пост)
Ты хочешь сказать, что после добавления, если выполнить refresh, то в наборе данных ты увидишь запись? Хм...

Если использовать генерацию в AutoUpdate Oprions или этот вариант, то после добавления/обновления записи (если установлено в Options RefreshAfterPost->true или принудительно обновлять в соответсвующем событии DataSet) запись появится в наборе данных и гриде и окажется в фокусе. Проверено.
Цитата(Akella @  8.9.2009,  15:13 Найти цитируемый пост)
Почитай про OLD_, NEW_ и MAS_ в докементации к фибам.

Читал.
Цитата(Akella @  8.9.2009,  15:13 Найти цитируемый пост)
Ты не увидишь новой записи в НД, пока не переоткроешь его.

Еще раз повторю, что увижу.

Это сообщение отредактировал(а) former - 9.9.2009, 21:59


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
Deniz
Дата 10.9.2009, 06:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 22
Всего: 44



Цитата(former @  10.9.2009,  00:53 Найти цитируемый пост)
А как же область видимости транзакции? При возникновении исключения у меня выполняется Cancel в соответствующих событиях DataSet. Кроме того, открываем Хелен Борри (2-е издание) на стр. 700 и читаем, читаем...

Так я про это и говорю. Пример:
Условие 1 все транзакции read commited
Условие 2 триггер на проверку наличия типа 
Код
...
if exist(select 1 from table where id = :new.id) then exception ...

1. Старт транзакции 1
2. Старт транзакции 2
3. Транз№1 Insert into table (id) values (1);
4. Транз№2 Insert into table (id) values (1);
5. Транз№1 Commit
6. Транз№2 Commit
Как думаешь сколько записей с id=1 будет в БД?
И вызовется ли исключение?


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
Akella
Дата 10.9.2009, 09:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 20
Всего: 329



Цитата(former @  9.9.2009,  21:53 Найти цитируемый пост)
Почему? Ведь если в качестве ключа использовать другие уникальные данные, показывать их можно, так почему номер нельзя?

Потому что пользователи ныть начинают... типа: "А я хочу по порядку...." и т.д. и т.п.
А тут уже даже программист хочет по порядку  smile  


Цитата(former @  9.9.2009,  21:53 Найти цитируемый пост)
Цитата(Akella @  8.9.2009,  15:13 Найти цитируемый пост)
Ты не увидишь новой записи в НД, пока не переоткроешь его.

Еще раз повторю, что увижу.

Стормозил, ты не увидишь данных, которые были добавлены другими транзакциями.
PM MAIL   Вверх
former
Дата 10.9.2009, 10:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



Цитата(Deniz @  10.9.2009,  06:00 Найти цитируемый пост)
1. Старт транзакции 1
2. Старт транзакции 2
3. Транз№1 Insert into table (id) values (1);
4. Транз№2 Insert into table (id) values (1);
5. Транз№1 Commit
6. Транз№2 Commit
Как думаешь сколько записей с id=1 будет в БД?
И вызовется ли исключение? 

Сегодня проведу эксперимент.
Цитата(Akella @  10.9.2009,  09:08 Найти цитируемый пост)
Потому что пользователи ныть начинают... типа: "А я хочу по порядку...." и т.д. и т.п.
А тут уже даже программист хочет по порядку  smile  

Два поста подряд пытаюсь донести суть.
Строгая нумерация не моя прихоть. Яркий пример бухгалтерия, где номера договоров, счетов, инвентарных номеров и прочих документов идет в строгой последовательности. Что прикажешь делать? Как им присваивать номера?
Цитата(Akella @  10.9.2009,  09:08 Найти цитируемый пост)
Стормозил, ты не увидишь данных, которые были добавлены другими транзакциями. 

Для этого используется отдельная кнопка, которая переоткрывает DataSet, т.е. делает полный Refresh. А то получится, что пользователь добавил запись и должен заново выполнять поиск, фильтрацию и т.д., что бы продолжить с ней работать. Согласись, что нажать на одну кнопку он всегда успеет, чем искать каждый раз нужную запись. Кроме того, каждый раз ворочить большин набором данных не очень-то экономично, по отношению к ресурсам и нагрузки на сеть и сервер, особенно, если пользователей много.


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
Deniz
Дата 10.9.2009, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 22
Всего: 44



Цитата(former @  10.9.2009,  13:54 Найти цитируемый пост)
Строгая нумерация не моя прихоть. Яркий пример бухгалтерия, где номера договоров, счетов, инвентарных номеров и прочих документов идет в строгой последовательности. Что прикажешь делать? Как им присваивать номера?
Не надо путать искусственный ключ с номером договора.
А если с нового года/пятилетки/и т.д. нужно начать нумерацию с начала? Что будешь делать?
Обычно делают так:
1. ID никто, кроме программиста, не видит.
2. Под № договора выделяют отдельное поле или несколько полей.
3. Строится уникальный индекс по полям "№ договора" + Год, может еще какие поля можно добавить.
4. ID получают в начале редактирования.
5. К этому ID привязывают detail таблицы.
6. Итоговый номер договора генерируется после того, как сделаны все проверки и данные договора добавлены.


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
former
Дата 10.9.2009, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



Deniz, индексы это хорошо, а вот что тогда с исключениями делать? Какого формата сообщение увидит пользователь в результате исключения?
Цитата(Deniz @  10.9.2009,  12:39 Найти цитируемый пост)
6. Итоговый номер договора генерируется после того, как сделаны все проверки и данные договора добавлены. 

Т.е. для номера договора должен использоваться отдельный генератор?

Это сообщение отредактировал(а) former - 10.9.2009, 14:56


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
Akella
Дата 10.9.2009, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 20
Всего: 329



Цитата(former @  10.9.2009,  10:54 Найти цитируемый пост)
Строгая нумерация не моя прихоть. Яркий пример бухгалтерия, где номера договоров, счетов, инвентарных номеров и прочих документов идет в строгой последовательности. Что прикажешь делать? Как им присваивать номера?

Так создай им отдельное поле № договора!!!

Добавлено через 35 секунд
А если прийдётся изменить значение? Ты дашь пользователю редактировать значение поля первичного ключа? Ну ну smile

Добавлено через 1 минуту и 28 секунд
Создай ещё один генератор для номера договора и/или сам на клиенте атоматом подставляй.

Добавлено через 10 минут и 55 секунд
ааа, Deniz уже написал smile

Добавлено через 12 минут и 21 секунду
Цитата(former @  10.9.2009,  14:51 Найти цитируемый пост)
Т.е. для номера договора должен использоваться отдельный генератор?

да!!! Можно делать и 
Код

Select MAX(N_dogovor) from table1

PM MAIL   Вверх
former
Дата 10.9.2009, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



Deniz, с транзакция ми действительно прав. Но как тогда быть с сообщениями исключений, если использовать индексы? Ведь они должны быть понятны пользователю.
Цитата(Akella @  10.9.2009,  16:08 Найти цитируемый пост)
А если прийдётся изменить значение? Ты дашь пользователю редактировать значение поля первичного ключа? Ну ну

Нет, пользователь ничего не редактирует. Номер карты присваивается генератором.
Цитата(Akella @  10.9.2009,  16:08 Найти цитируемый пост)
ааа, Deniz уже написал

 smile  smile 
Цитата(Akella @  10.9.2009,  16:08 Найти цитируемый пост)
Можно делать и 
Выделить всёкод SQL
1:Select MAX(N_dogovor) from table1

Ну это только при условии, что номер состоит из одних цифр.

Akella, так что с Refresh-ом? smile 

Это сообщение отредактировал(а) former - 10.9.2009, 18:37


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
former
Дата 10.9.2009, 18:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



DenizAkella, спасибо за помощь!
С исключениями я разобрался, используя репозиторий.
А вот с номером договора так и не понятно, в какой момент его нужно генерировать и где?



--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
Akella
Дата 10.9.2009, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 20
Всего: 329



Цитата(former @  10.9.2009,  17:00 Найти цитируемый пост)
Нет, пользователь ничего не редактирует. Номер карты присваивается генератором.

Но всё равно когда-нибудь понадобится изменять номер карты, корректировать, мало ли. Если будет отдельное поле - без проблем, а если ковырять первичный ключ.... smile 

Цитата(former @  10.9.2009,  17:00 Найти цитируемый пост)

Select MAX(N_dogovor) from table1

Ну это только при условии, что номер состоит из одних цифр.

 smile 
а так?
Код
select max(a.LCD) from apart a


При условии, что поле LCD типа Timestamp  smile 

Это сообщение отредактировал(а) Akella - 10.9.2009, 19:09
PM MAIL   Вверх
former
Дата 10.9.2009, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



Цитата(Akella @  10.9.2009,  19:05 Найти цитируемый пост)
а так?

Я имел виду, как быть с текстовым вариантом?


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
Deniz
Дата 11.9.2009, 06:01 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 22
Всего: 44



Цитата(former @  10.9.2009,  21:34 Найти цитируемый пост)
С исключениями я разобрался, используя репозиторий.
вот и славненько  smile 
Цитата(former @  10.9.2009,  21:34 Найти цитируемый пост)
А вот с номером договора так и не понятно, в какой момент его нужно генерировать и где?
Здесь есть куча вопросов:
Как выглядит этот номер? Как он должен генерироваться? Кто отвечает за генерацию?
По своему опыту могу сказать, что в таких номерах (договор, вх. документ и т.д.) обычно присутствуют разные буквы и метасимволы, причем автоматизировать процесс генерации бывает достаточно сложно.
Иногда лучше назначить одного ответственного, кто будет вбивать № договора во внесенный в БД документ, чем попытаться определить след. номер от "458-П/2009/В-32".


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
former
Дата 11.9.2009, 09:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 1
Всего: 17



Цитата(Deniz @  11.9.2009,  06:01 Найти цитируемый пост)
Как выглядит этот номер? Как он должен генерироваться? Кто отвечает за генерацию?

Ручной ввод - самое простое, что можно придумать.  Но человеческий фактор.... smile 
Я уже кое-что сам вчера придумал. Можно использовать префиксы для каждого типа договора. Создать для них отдельную таблицу.
Например, для 458-П/2009/В-32:
Префикс - -П/2009/В- (для каждого типа договора свой)
Изменяемые части - 458 и 32. Для них генераторы. Значения получать в процессе редактирования, в зависимости от условий договора.
Что-то вроде регулярных выражений.

Безусловно, такой подход имеет свои недостатки.

Это сообщение отредактировал(а) former - 11.9.2009, 09:06


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
Deniz
Дата 11.9.2009, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 22
Всего: 44



former, не все так просто, все зависит от того, какой на Вашем предприятии принят алгоритм формирования номеров.
Поскольку официально-декларирующего алгоритма нет, то каждый извращается как хочет, например (458-П/2009/В-32):
458 - порядковый номер
П - тип договора
2009 - год заключения
В-32 - дополнительные параметры по договору
Может быть два одинаковых порядковых номера но с разными типами 458-П и 458-С.

Цитата(former @  11.9.2009,  12:05 Найти цитируемый пост)
Ручной ввод - самое простое, что можно придумать.  Но человеческий фактор.... 
если будет один назначенный ответственный с одного компа (с проверкой на уникальность), проблем будет меньше, а если еще пару раз сделать показательное наказание за ошибки ...
В общем удачи.


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Interbase"
Alex

Обязательно указание:

1. Версию InterBase (Firebird, Yaffil)

2. Способа доступа (ADO, BDE, IBX и т.д.)

  • КАК ПРАВИЛЬНО ОФОРМИТЬ КОД - ЗДЕСЬ
  • КАК ПРАВИЛЬНО УКАЗАТЬ ТЕКСТ ОШИБКИ - ЗДЕСЬ
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • FAQ раздела лежит здесь!

Если Вам понравилась атмосфера форума, заходите к нам чаще! С Уважением, Akella.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Firebird, Interbase | Следующая тема »


 




[ Время генерации скрипта: 0.1327 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.