О генерации уникальных первичных ключей
Еще
одним серьезным
недостатком подобной
информационной системы
является необходимость
ввода пользователем
значений первичных ключей,
что в данном примере
особенно критично для
списка пациентов и списка
посещений. В этом случае
весьма высока возможность
ошибки, связанной с вводом
значения, уже имеющегося в
базе данных. Причиной
может быть как ошибка
самого оператора, так и попытка
одновременного ввода
одного и того же значения с
разных рабочих станций
сети.
Проблема
подобного рода может быть
решена с помощью генерации
уникальных первичных
ключей как в клиентском
приложении, так и на
сервере. В приложении
генерация первичного
ключа осуществляется,
например, путем создания
длинной случайной
символьной строки с
помощью какого-либо
генератора, использующего
в качестве параметров
время с точностью до долей
секунды и какие-либо
уникальные характеристики
рабочей станции так, чтобы вероятность
повторов была чрезвычайно
мала. Этот способ обычно
используется с теми СУБД,
которые сами не
поддерживают возможность
генерации таких ключей
(например, dBase). Он неудобен,
так как при наличии
нескольких различных
приложений, использующих
одну и ту же
базу данных, требуется в
каждом из них повторить
код, отвечающий за
генерацию первичных
ключей.
Более
предпочтительным способом
является использование
возможностей генерации
первичных ключей,
содержащихся в самой СУБД.
Эту возможность
поддерживает большинство
серверных СУБД, а также
некоторые настольные СУБД
(например, Paradox,
позволяющий создавать в
таблицах автоинкрементные
поля).
В
качестве примера
рассмотрим, как можно
использовать возможности
генерации первичных
ключей, предоставляемые
Oracle, для автоматического
заполнения поля TAG таблицы
VISIT. С этой целью
воспользуемся генератором
последовательностей Oracle,
создающим
последовательности
уникальных целых чисел,
используемых клиентскими
приложениями в качестве
значений первичных ключей.
Создадим такую
последовательность с
помощью следующего набора
операторов (исполнить их
можно с помощью SQL Plus или с
помощью утилиты Database Explorer):
create sequence seqtag
start with 200
increment by 1
nominvalue
nomaxvalue
nocycle
nocache
На
главной форме приложения
заменим компонент TDBEdit, в
который ранее вводилось
значение поля TAG,
компонентом TDBText, чтобы
исключить возможность
ввода этого значения
пользователем. В модуль
данных нашего клиентского
приложения поместим
компонент TUpdateSQL, выберем его имя в
качестве значения
свойства UpdateObject
компонента TTable, с помощью
которого вводятся данные в
таблицу VISIT, сгенерируем
операторы SQL для вставки,
удаления и модификации
записи и изменим оператор
SQL для вставки следующим
образом:
Insert into VISIT
(TAG, STAT_ID, DIAG_ID, PURP_ID, PAT_ID, DOCT_ID, DATE_VIZ)
values
(seqtag.NEXTVAL, :STAT_ID, :DIAG_ID, :PURP_ID, :PAT_ID, :DOCT_ID, :DATE_VIZ)
Далее
изменим свойство CachedUpdates
этого компонента TTable на true
и обеспечим возможность
сохранять в базе данных
изменения, накопленные в
кэше, переопределив
реакцию на нажатие кнопок
компонента TDBNavigator либо
введя для этой цели либо
дополнительные
интерфейсные элементы
(например, кнопку):
void __fastcall TMAINFORM::Button1Click(TObject *Sender)
{
DataModule2->Table1->ApplyUpdates();
DataModule2->Table1->CommitUpdates();
}
Метод
ApplyUpdates() нужен для
сохранения изменений в
базе данных, а метод
CommitUpdates() - для очистки кэша.
Скомпилировав
и выполнив приложение,
можно убедиться в том, что
первичные ключи в базе
данных генерируются
автоматически (например, с
помощью Database Explorer).
Окончательный вид
приложения представлен на
рис.11.
Рис. 11.
Окончательный вид главной
формы АРМ медстатистика.
Этот
способ создания первичных
ключей в любом случае
намного более удобен, чем
использование ручного
ввода их значений. Однако и
этот способ является не
самым эффективным, так как
операторы SQL для вставки
записи содержатся в
клиентском приложении.
Другой
способ генерации ключей с
использованием
последовательности
реализуется путем
создания триггера,
выполняющегося перед
вставкой записи в таблицу,
примерно следующего вида:
CREATE TRIGGER MEDIC1.VI_INS BEFORE INSERT
ON MEDIC1.VISIT
FOR EACH ROW
BEGIN
UPDATE VISIT SET TAG=seqtag.nextval where TAG=10;
END;
Триггер
можно создать, например, с
помощью утилиты SQL Plus, и с
помощью SQL Explorer можно
просматривать его текст
(рис.12):
Рис.12.
Просмотр текста
созданного триггера с
помощью SQL Explorer.
В
этом случае компонент
TUpdateSQL уже не требуется, но
при этом нужно добавить в
приложение код,
присваивающий значение
полю TAG, так как в противном
случае клиентское
приложение не допустит
отправки запроса на
сервер:
void __fastcall TDataModule2::Table1BeforeInsert(TDataSet *DataSet)
{
Table1TAG->Value=10;
}
Назад | Содержание | Вперед