Можно ли изменить удаление на обновление с помощью триггеров? - PullRequest
0 голосов
/ 02 октября 2018

Есть ли в Firebird способ выполнить ОБНОВЛЕНИЕ вместо УДАЛЕНИЯ через триггер?

Это возможно в Microsoft SQL Server, объявив триггеры как "INSTEAD".

Проблемав том, что у нас есть приложение, которое использует базу данных Firebird, и мы хотим предотвратить удаление записей и пометить их как «удаленные» (новое поле), но без отображения какой-либо ошибки пользователю и «обмана» приложения.

Ответы [ 2 ]

0 голосов
/ 05 октября 2018

Вы не можете сделать это с таблицами, но вы можете сделать это с представлениями.Представления могут иметь триггеры при вставке, обновлении и удалении, которые изменяют базовые таблицы.См. Также Обновляемые представления в справочнике по языку Firebird 2.5.

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

Пример

Я использую Firebird 3, но это будет работать с небольшими изменениями в Firebird 2.5 и более ранних версиях.

Таблица example_base:

create table example_base (
  id bigint generated by default as identity constraint pk_example_base primary key,
  value1 varchar(100),
  deleted boolean not null default false
)

Представление example:

create view example (id, value1) 
  as 
  select id, value1 
  from example_base 
  where not deleted;

Не создавайте представление с with check option, так как это запретит вставки какОтсутствие столбца deleted в представлении не позволит Firebird проверить инвариант.

Затем добавьте триггер вставки:

create trigger tr_example_insert before insert on example
as
begin
  if (new.id is not null) then
    -- Don't use identity
    insert into example_base(id, value1) values (new.id, new.value1);
  else
    -- Use identity
    -- mapping generated id to new context 
    -- this way it is available for clients using insert .. returning
    insert into example_base(value1) values (new.value1) 
      returning id into :new.id;
end

Приведенный выше триггер обеспечивает «по умолчанию как идентификатор»Первичный ключ базовой таблицы сохраняется и позволяет insert into example .. returning сообщать о сгенерированном идентификаторе.

Триггер обновления

create trigger tr_example_update before update on example
as
begin
  -- Consider ignoring modification of the id (or raise an exception)
  update example_base 
    set id = new.id, value1 = new.value1 
    where id = old.id;
end

Приведенный выше триггер позволяет изменять первичный ключ;Вы можете захотеть просто игнорировать такую ​​модификацию или даже вызвать исключение.

И, наконец, триггер удаления:

create trigger tr_example_delete before delete on example
as
begin
  update example_base 
    set deleted = true
    where id = old.id;
end

Этот триггер пометит запись в базовой таблице как удаленную.

Чтобы использовать это, просто предоставьте своим пользователям право выбирать, вставлять и обновлять права доступа к представлению (а не к таблице).

Единственное замечание, о котором я знаю, это то, что определение внешних ключей будетнужно указывать на example_base, а не на example, и поведение внешних ключей будет слегка отключено.Запись в базовой таблице будет продолжать существовать, поэтому внешний ключ не будет блокировать удаление.Если это то, что необходимо, вам нужно будет эмулировать поведение ограничения (что может быть сложно).

0 голосов
/ 04 октября 2018

ДА!Это можно сделать на VIEWS.Вот так я и решил.Если у View есть триггер, то триггер отвечает за реальное обновление или удаление базовой таблицы .... Итак ... триггер DELETE, который делает UPDATE для таблицы, решил мою проблему.

...