Sql Oracle触发器-更新行而不是删除
如何编写Oracle触发器,而不是当用户删除某个记录时,删除实际上不会发生,而是对这些行执行更新,并将记录的状态设置为“D” 我试过:Sql Oracle触发器-更新行而不是删除,sql,oracle,triggers,Sql,Oracle,Triggers,如何编写Oracle触发器,而不是当用户删除某个记录时,删除实际上不会发生,而是对这些行执行更新,并将记录的状态设置为“D” 我试过: create or replace trigger DELFOUR.T4M_ITEM_ONDELETE before delete on M_ITEM_H FOR EACH ROW BEGIN UPDATE M_ITEM_H SET ITEM_STAT = 'D' WHERE CUST_CODE = 'TEST' AN
create or replace
trigger DELFOUR.T4M_ITEM_ONDELETE
before delete on M_ITEM_H
FOR EACH ROW
BEGIN
UPDATE
M_ITEM_H
SET
ITEM_STAT = 'D'
WHERE
CUST_CODE = 'TEST'
AND ITEM_CODE = 'GDAY'
;
raise_application_error(-20000,'Cannot delete item');
END;
但我得到了变异表错误。这可能吗?首先,您编写的触发器将抛出一个变异表错误。技术上,你所要求的是不可能的,即删除不会删除,而是更新,除非你在中间引发异常,这可能是一个丑陋的做法。我认为用户使用某种应用程序前端,可以使用delete按钮
delete
数据,因此您可以在那里使用update语句,而不是delete
语句
另一个选项是创建一个日志表,您可以在从实际表中删除记录之前插入该记录,然后将日志表与实际表连接以检索已删除的记录。差不多-
CRETAE TABLE M_ITEM_H_DEL_LOG as SELECT * FROM M_ITEM_H WHERE 1=2;
然后
create or replace
trigger DELFOUR.T4M_ITEM_ONDELETE
before delete on M_ITEM_H
FOR EACH ROW
BEGIN
INSERT INTO
M_ITEM_H_DEL_LOG
VALUES (:old.col1, :old.col2,.....) --col1, col2...are columns in M_ITEM_H
;
END;
如果确实需要触发器,更合理的方法是创建一个视图,在视图上创建一个
INSEAD OF DELETE
触发器,并强制应用程序对视图而不是基表执行删除操作
CREATE VIEW vw_m_item_h
AS
SELECT *
FROM m_item_h;
CREATE OR REPLACE TRIGGER t4m_item_ondelete
INSTEAD OF DELETE ON vw_m_item_h
FOR EACH ROW
AS
BEGIN
UPDATE m_item_h
SET item_stat = 'D'
WHERE <<primary key>> = :old.<<primary key>>;
END;
创建视图vw\u m\u项目
作为
挑选*
从m_项目h;
创建或替换触发器t4m_项删除
而不是删除vw\u m\u项目
每行
作为
开始
更新m_项目
设置项_stat='D'
WHERE=:old。;
结束;
更好的是,您可以省去触发器,创建一个delete\u item
过程,应用程序将调用该过程,而不是发出delete
,该过程只需更新行以设置item\u stat
列,而不是删除行
如果您真的,真的,真的想要一个解决方案,其中包括表本身的触发器,那么您可以
m_item_h
表中数据的记录集合:old.
和所有其他:old
值插入集合item_stat
列这将比使用
而不是触发器
需要更多的工作,因为您必须删除行,然后重新插入行,这将涉及更多的移动片段,因此它将不那么优雅。但它会起作用。谢谢你的建议!我没有访问该应用程序的权限。基本上,它是一个仓库管理系统,如果该产品没有任何移动,它将删除一个项目代码。如果有,它只是停用该项目。我希望它总是停用该项目。该界面使用的是Oracle Forms,因此它非常难看,因此我不担心用户是否看到Oracle错误,因为当前的应用程序与它们分散在一起。如果您可以更改Oracle Forms代码以更改“删除”按钮功能,您就可以做到这一点。或者,在raise_应用程序_错误中,代替“无法删除项目”消息,显示类似“项目已删除/停用”的内容。不幸的是,我无法访问该应用程序,因此无法更改this@Lock-您是说这是一个第三方打包应用程序?如果是这样的话,为什么首先要通过添加触发器来修改它呢?因为我有sysdba访问database@Lock-如果这是第三方打包的应用程序,供应商通常不允许您首先向系统添加触发器。从技术上讲,您可以访问系统以添加触发器。但这样做会违反你的支持合同。如果您不介意违反支持合同,我会继续创建一个视图。您可以重命名该表,使用该表的名称创建视图,并在视图上创建而不是触发器。这通常对应用程序是透明的。