是否可以使用触发器将删除更改为更新?

时间:2018-10-02 19:11:28

标签: sql triggers firebird

Firebird中是否可以通过触发器执行UPDATE而不是DELETE?

这在Microsoft SQL Server中可以通过将触发器声明为“ INSTEAD”来实现。

问题是,我们有一个使用Firebird数据库的应用程序,我们希望防止记录的删除,然后将其标记为“已删除”(新字段),但不会向用户显示任何错误,并且“作弊” ”的应用程序。

2 个答案:

答案 0 :(得分:1)

您不能对表执行此操作,但是可以对视图执行此操作。视图可以具有用于插入,更新和删除的触发器,这些触发器可以修改基础表。另请参阅《 Firebird 2.5语言参考》中的Updatable Views

简而言之,为数据创建一个表,添加一个视图,将通过视图插入/更新/删除的触发器添加到基础表。然后,用户可以像使用表一样使用该视图。

一个例子

我正在使用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报告生成的ID。

更新触发器

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,并且外键的行为将略有偏离。基表中的记录将继续存在,因此外键不会阻止删除。如果这是必需的,则需要模拟约束行为(这可能很棘手)。

答案 1 :(得分:0)

是的!可以在VIEW上进行。 我就是这样解决的。 如果View有一个触发器,则该触发器负责对基础表进行真正的更新或删除。...所以...一个对表进行UPDATE的DELETE触发器解决了我的问题。