为视图创建一个触发器,在视图所基于的表中的数据第一次更改(UPDATE、DELETE、INSERT、MERGE)时,将使用视图中的信息将 USER 和 TIME 列添加到正在修改的表中正在修改的有关用户和更改时间的行。在后续访问已创建列的表时,触发器必须更正 USER 和 TIME 列中的信息。你只需要创建一个触发器
这是我的解决方案,但是当我在表上使用 UPDATE、DELETE、INSERT 时,不会添加新列。根据任务,需要为视图创建触发器,并操作表
CREATE OR REPLACE TRIGGER audit_changes_trg INSTEAD OF INSERT OR UPDATE OR DELETE ON EMP_VIEWDOP5 DECLARE PRAGMA AUTONOMOUS_TRANSACTION; v_column_exists NUMBER; BEGIN
SELECT COUNT(*)
INTO v_column_exists
FROM user_tab_columns
WHERE table_name = 'EMPLOYEESDOP5'
AND column_name = 'USERAUDIT';
IF v_column_exists = 0 THEN
EXECUTE IMMEDIATE 'ALTER TABLE EMPLOYEESDOP5 ADD (
USERaudit VARCHAR2(30),
TIMEaudit TIMESTAMP)';
END IF;
IF INSERTING THEN
EXECUTE IMMEDIATE
'INSERT INTO EMPLOYEESDOP5 (EMP_ID, EMP_NAME, EMP_SALARY, DEPT_ID, USERaudit, TIMEaudit)
VALUES (:1, :2, :3, :4, :5, :6)'
USING :NEW.EMP_ID, :NEW.EMP_NAME, :NEW.EMP_SALARY, :NEW.DEPT_ID, USER, SYSTIMESTAMP;
END IF;
IF UPDATING THEN
EXECUTE IMMEDIATE
'UPDATE EMPLOYEESDOP5
SET EMP_NAME = :1,
EMP_SALARY = :2,
DEPT_ID = :3,
USERaudit = :4,
TIMEaudit = :5
WHERE EMP_ID = :6'
USING :NEW.EMP_NAME, :NEW.EMP_SALARY, :NEW.DEPT_ID, USER, SYSTIMESTAMP, :OLD.EMP_ID;
END IF;
IF DELETING THEN
EXECUTE IMMEDIATE
'DELETE FROM EMPLOYEESDOP5 WHERE EMP_ID = :1'
USING :OLD.EMP_ID;
END IF;
END;
...当我在表上使用 UPDATE、DELETE、INSERT 时,没有添加新列。
你没有解释这是什么意思。添加到哪里?如果您检查了视图,当然不会添加它们,因为视图定义是在触发器第一次运行之前设置的。但是,如果您检查了该表,审核表应该存在。 这是一个基于 Scott 示例架构的演示,其
emp
表。
测试台:SQL> CREATE TABLE emp_test
2 AS
3 SELECT empno,
4 ename,
5 job,
6 sal
7 FROM emp
8 WHERE deptno = 10;
Table created.
基于该表的视图:
SQL> CREATE OR REPLACE VIEW v_emp_test
2 AS
3 SELECT * FROM emp_test;
View created.
触发;请注意,它最后需要
commit
,因为它是一个自治事务:
SQL> CREATE OR REPLACE TRIGGER audit_changes_trg
2 INSTEAD OF INSERT OR UPDATE OR DELETE
3 ON v_emp_test
4 DECLARE
5 PRAGMA AUTONOMOUS_TRANSACTION;
6 v_column_exists NUMBER;
7 BEGIN
8 SELECT COUNT (*)
9 INTO v_column_exists
10 FROM user_Tab_columns
11 WHERE table_name = 'EMP_TEST'
12 AND column_name = 'USERAUDIT';
13
14 IF v_column_exists = 0
15 THEN
16 EXECUTE IMMEDIATE 'alter table emp_test add (useraudit varchar2(30), timeaudit date)';
17 END IF;
18
19 IF INSERTING
20 THEN
21 EXECUTE IMMEDIATE 'insert into emp_test (empno, ename, job, sal, useraudit, timeaudit)
22 values (:1, :2, :3, :4, :5, :6)'
23 USING :new.empno,
24 :new.ename,
25 :new.job,
26 :new.sal,
27 USER,
28 SYSDATE;
29 ELSIF UPDATING
30 THEN
31 EXECUTE IMMEDIATE 'update emp_test set
32 ename = :1, job = :2, sal = :3, useraudit = :4, timeaudit = :5
33 where empno = :6'
34 USING :new.ename,
35 :new.job,
36 :new.sal,
37 USER,
38 SYSDATE,
39 :new.empno;
40 ELSIF DELETING
41 THEN
42 EXECUTE IMMEDIATE 'delete from emp_test where empno = :1'
43 USING :old.empno;
44 END IF;
45
46 COMMIT;
47 END;
48 /
Trigger created.
测试:表格内容:
SQL> SELECT * FROM emp_test;
EMPNO ENAME JOB SAL
---------- ---------- --------- ----------
7782 CLARK MANAGER 2450
7839 KING PRESIDENT 5000
7934 MILLER CLERK 1300
查看内容:
SQL> SELECT * FROM v_emp_test;
EMPNO ENAME JOB SAL
---------- ---------- --------- ----------
7782 CLARK MANAGER 2450
7839 KING PRESIDENT 5000
7934 MILLER CLERK 1300
让我们更新一下视图;触发器应该触发并将审核列添加到表(而不是视图!):
SQL> UPDATE v_emp_test
2 SET sal = 2000
3 WHERE job = 'CLERK';
1 row updated.
SQL> SELECT * FROM emp_test;
EMPNO ENAME JOB SAL USERAUDIT TIMEAUDIT
---------- ---------- --------- ---------- ------------------------------ -------------------
7782 CLARK MANAGER 2450
7839 KING PRESIDENT 5000
7934 MILLER CLERK 2000 SCOTT 09.10.2024 08:16:31
风景怎么样?什么都没有(除了反映工资变化的事实之外):
SQL> SELECT * FROM v_emp_test;
EMPNO ENAME JOB SAL
---------- ---------- --------- ----------
7782 CLARK MANAGER 2450
7839 KING PRESIDENT 5000
7934 MILLER CLERK 2000
如果您还想向视图添加新列,则必须
重新创建视图:
SQL> CREATE OR REPLACE VIEW v_emp_Test
2 AS
3 SELECT * FROM emp_test;
View created.
SQL> SELECT * FROM v_emp_test;
EMPNO ENAME JOB SAL USERAUDIT TIMEAUDIT
---------- ---------- --------- ---------- ------------------------------ -------------------
7782 CLARK MANAGER 2450
7839 KING PRESIDENT 5000
7934 MILLER CLERK 2000 SCOTT 09.10.2024 08:16:31
SQL>