Firebird中是否可以通过触发器执行UPDATE而不是DELETE?
这在Microsoft SQL Server中可以通过将触发器声明为“ INSTEAD”来实现。
问题是,我们有一个使用Firebird数据库的应用程序,我们希望防止记录的删除,然后将其标记为“已删除”(新字段),但不会向用户显示任何错误,并且“作弊” ”的应用程序。
答案 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触发器解决了我的问题。