Логин: Пароль:    Регистрация Всеми возможностями сайта можно пользоваться
только после авторизации.
   Забыли пароль?

Поиск
L



Статистика
u
Пользователи онлайн: нет
Гостей онлайн: 2
Всего онлайн: 2
Зарегистрировано юзеров: 6362
Комментариев на сайте: 645
Новый юзер: Pseulairrerve



Последние комментарии
c
Aqel прокомментировал "Урок 71 - Работа с сжатыми файлами":
GZip псевдоархив, на мой вопрос тоже не отвечают, как распаковать отдельные файлы/папки...
Pingitrus прокомментировал "Урок 71 - Работа с сжатыми файлами":
Есть еще кто нибудь живой на этом сайте, кто сможет помочь? Так то все работает, zip и rar распаковывает, но у меня есть файл dat который сжат GZip, почему то его не удается распаковать или так не получится так как этот файл не является архивом или является?)) пишет ошибку что неверная функция



Мы в соцсетях
c
Delphi
Создание генераторов и триггеров в InterBase

В данной статье я опишу реализацию небольшой утилиты для InterBase, которая создает генераторы, автоматически вызываемые из триггеров. На создание такой утилиты меня подвигло то, что я не нашел никакого средства для этого, а создавать генераторы руками мне неудобно, да и слишком много времени это отнимает.

Общая информация
Вообще, считается хорошим стилем создание первичного ключа в виде уникального числа. Мало того, это наиболее удобный способ для связи таблиц. Такой первичный ключ часто называют "айдишкой" (от слова "ID", идентификатор) таблицы.

Значения такого поля могут задаваться и вручную, но тогда придется вручную же контролировать их уникальность, что практически невозможно при многопользовательском режиме использования БД. Для этого в InterBase был включен механизм "генераторов", аналогичный механизму "последовательностей" в Oracle. Единственная цель генератора - дать уникальное (в его контексте) числовое значение при вызове.

Сами по себе генераторы практически не имеют смысла, так как они никак не связаны с таблицами БД. Для запроса значения генератора применяются триггеры, автоматически вызываемые СУБД при возникновении определенных событий. В основном, триггер, использующий генератор, вызывается по событию "BeforeInsert", то есть перед непосредственной вставкой данных.

Текст создания классического генератора и триггера для него, в общем случае, выглядит следующим образом:

CREATE GENERATOR GEN_%TBL_NAME%;
CREATE TRIGGER NEW_%TBL_NAME% FOR %TBL_NAME%
ACTIVE BEFORE INSERT POSITION 0
AS
begin
  if (NEW.%ID_FIELD% is NULL) then NEW.%ID_FIELD% = gen_id(GEN_%TBL_NAME%,1);
end
Здесь %TBL_NAME% - имя таблицы, для которой создается триггер и генератор, а %ID_FIELD% - имя поля, являющегося первичным ключом.

Реализация
Итак, для реализации утилиты нам необходимо для начала найти список таблиц базы данных, а также их первичных ключей. Для этого мы сделаем запросы к словарю данных базы (словарь данных еще называется метаданными), который содержится в системных таблицах, имена которых начинаются с последовательности "rdb$".

Список таблиц можно получить следующим образом:
select rdb$relation_name from rdb$relations
where (rdb$system_flag=0) and (rdb$view_source is null)
order by rdb$relation_name asc;
Список первичных ключей получаем так:
select i.rdb$field_name from rdb$relation_constraints r, rdb$index_segments i
where r.rdb$relation_name=:TBL_NAME and r.rdb$constraint_type='PRIMARY KEY'
and r.rdb$index_name=i.rdb$index_name order by i.rdb$field_position
Теперь все необходимое для дальнейшей работы получено и мы можем создавать генераторы с триггерами.

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

В поле списка опций (большое белое поле) у нас будут имена таблиц, а надписи на кнопках говорят сами за себя. Как вы видите, ничего сложного. Код обработки нажатия на кнопку "Create generators..." таков:
procedure TForm2.btnCreateClick(Sender: TObject);
var i: integer;
begin
  with dm do for i := 0 to pred(lbTables.Count) do
  begin
    if lbTables.Checked[i] then
      if not HasTrigger(lbTables.Items[i]) then
      begin
        if not tm.InTransaction then tm.StartTransaction;
        try CreateTriggeredGenerator(lbTables.Items[i]);
        except
          tm.Rollback;
          showmessage('Unable to create objects for the table '+lbTables.Items[i]+'.');
        end;
        if tm.InTransaction then
        begin
          tm.Commit;
          showmessage('Objects for the table '+lbTables.Items[i]+' is successfully created.');
        end;
      end;
  end;
end;
Здесь для каждой выбранной в списке таблицы проверяется, существует ли уже триггер с генератором для этой таблицы. Если нет, то они создаются.

Проверка существования триггера выглядит вот таким образом:
function TForm2.HasTrigger(const TableName: string): boolean;
var s: string;
    i: integer;
begin
  Result := false;
  if (Gens.Count < 1) then exit;
  with dm do
  begin
    qHasTrigger.ParamByName('TBL_NAME').Value := TableName;
    qHasTrigger.Open;
    while not qHasTrigger.Eof do
    begin
      s := qHasTrigger.FieldByName('rdb$trigger_source').AsString;
      if (length(s) > 0) then
        for i := 0 to pred(Gens.Count) do
          if pos(UpperCase(Gens[i]),UpperCase(s)) > 0 then Result := true;
      qHasTrigger.Next;
    end;
    qHasTrigger.Close;
  end;
end;


Вот и всё, Удачи!

Источник: www.thedelphi.ru
Автор: Савельев Александр
Опубликовано: 14 Июня 2015
Просмотров:


Зарегистрируйтесь или авторизуйтесь, чтобы добавлять комментарии.