在迁移系统/数据库之后,我们修改了一个用于与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,
(...)
Run Code Online (Sandbox Code Playgroud)
显然,这种观点本身并不是可更新的.
我明白,你需要所有DML(插入,更新,删除)语句的INSTEAD OF触发器.我可以看到,INSTEAD OF INSERT触发器应该非常简单(只需将NEW.field插入到真实表中,在适当的地方,忽略其他表).
但实际问题:如何编写INSTEAD OF UPDATE/DELETE触发器?例如,如何接管原始DELETE语句的"WHERE"子句?还有什么我应该担心,使用这些触发器时的任何副作用?
顺便说一句.它是Oracle 11g.
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
Run Code Online (Sandbox Code Playgroud)
请注意,某些列实际上可能在原始视图中是可更新的.查询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;
Run Code Online (Sandbox Code Playgroud)
查看已创建
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
Run Code Online (Sandbox Code Playgroud)
如果您只需要插入/更新这些列,则不需要INSTEAD OF触发器.
INSTEAD OF触发器是隐式"FOR EACH ROW",所以你不必找到WHERE子句,你只需要这样做:
begin
delete base_table
where pk = :old.pk;
end;
Run Code Online (Sandbox Code Playgroud)
这也显示了INSTEAD OF触发器的一个缺点:它们逐行而不是成组.