在迁移系统/数据库之后,我们修改了一个用于与15个不同系统连接的中央表。我们使用此迁移来添加和删除此表中的一些字段。
为了保持与接口系统的直接兼容性(即只需要更改数据库链接),已创建一个视图,该视图显示与旧表具有完全相同的列。但是,其中一些列只是模拟的,因此视图包含如下构造:
(...)
CREATE OR REPLACE VIEW STAFF_DATA_COMPAT AS
SELECT
NVL(knownas_surname,surname) as surname,
first_name
middle_name as mid-name
NULL as ni,
NULL as home_tel_no,
(...)
显然,这种观点本身不可更新。
我明白,您需要所有DML(插入,更新,删除)语句的INSTEAD OF触发器。 我可以看到,INSTEAD OF INSERT触发器应该非常简单(只需将NEW.field插入到真实表中,在适当的地方,忽略其他表)。
但实际问题:如何编写INSTEAD OF UPDATE / DELETE触发器?例如,如何接管原始DELETE语句的“WHERE”子句?还有什么我应该担心的,使用这些触发器时的任何副作用吗?
顺便说一下。这是Oracle 11g。
答案 0 :(得分:7)
INSTEAD OF触发器看起来像这样(我假设你有一个主键列id
):
SQL> CREATE OR REPLACE TRIGGER trg_staff_data_cpt_instead_upd
2 INSTEAD OF UPDATE ON staff_data_compat
3 FOR EACH ROW
4 BEGIN
5 UPDATE staff_data_compat_t
6 SET knownas_surname = :new.surname,
7 first_name = :new.first_name,
8 middle_name = :new.mid_name
9 WHERE id = :new.id
10 END;
11 /
Trigger created
请注意,某些列实际上可能在原始视图中是可更新的。查询all_updatable_columns
视图(在创建触发器之前)以查找:
SQL> CREATE TABLE staff_data_compat_t AS
2 SELECT object_name knownas_surname,
3 owner surname,
4 object_type first_name,
5 subobject_name middle_name
6 FROM all_objects;
Table created
SQL> CREATE OR REPLACE VIEW staff_data_compat AS
2 SELECT
3 NVL(knownas_surname,surname) as surname,
4 first_name,
5 middle_name mid_name,
6 NULL as ni,
7 NULL as home_tel_no
8 FROM staff_data_compat_t;
查看已创建的
SQL> SELECT * FROM all_updatable_columns WHERE table_name = 'STAFF_DATA_COMPAT';
OWNER TABLE_NAME COLUMN_NAME UPDATABLE INSERTABLE DELETABLE
------ ------------------ ------------ --------- ---------- ---------
VNZ STAFF_DATA_COMPAT SURNAME NO NO NO
VNZ STAFF_DATA_COMPAT FIRST_NAME YES YES YES
VNZ STAFF_DATA_COMPAT MID_NAME YES YES YES
VNZ STAFF_DATA_COMPAT NI NO NO NO
VNZ STAFF_DATA_COMPAT HOME_TEL_NO NO NO NO
如果您只需要插入/更新这些列,则不需要INSTEAD OF触发器。
答案 1 :(得分:5)
INSTEAD OF触发器是隐含的“FOR EACH ROW”,所以你不必找到WHERE子句,你只需要这样做:
begin
delete base_table
where pk = :old.pk;
end;
这也显示了INSTEAD OF触发器的一个缺点:它们逐行地工作而不是集合。