【问题标题】:update statement is not working in instead of trigger oracle11g更新语句不起作用而不是触发 oracle11g
【发布时间】:2015-05-07 20:57:18
【问题描述】:
CREATE TABLE STUDENTMARK
(
    STUD_ROLLNO NUMBER(10),
    CLASS_NAME VARCHAR2(10),
    MARK1 NUMBER(5),
    MARK2 NUMBER(5),
    TOTAL NUMBER(5)
);

A) 编写一个 PL/SQL 触发器来更新“studentMark”表中的总数 当插入发生在同一个表中时。 查询:

CREATE VIEW STUDENTMARK_VIEW
AS SELECT * FROM STUDENTMARK;

CREATE OR REPLACE TRIGGER TOTAL_TRIG INSTEAD OF INSERT ON STUDENTMARK_VIEW
FOR EACH ROW
BEGIN
INSERT INTO STUDENTMARK (STUD_ROLLNO,CLASS_NAME,MARK1,MARK2)
  VALUES (:NEW.STUD_ROLLNO,:NEW.CLASS_NAME,:NEW.MARK1,:NEW.MARK2);
UPDATE STUDENTMARK SET TOTAL = :new.mark1+:new.mark2
  WHERE stud_rollno = :new.STUD_ROLLNO;
END;
/

truncate table studentmark;
INSERT INTO STUDENTMARK (STUD_ROLLNO,CLASS_NAME,MARK1,MARK2) 
  VALUES (1,'CSE_B',100,100);
SELECT * FROM STUDENTMARK;

我试过很多次。它正在插入 mark1 和 mark2 的值,但不更新总数 - 有什么错误?

【问题讨论】:

  • 您的触发器在 STUDENTMARK_VIEW 上!如果您希望在 STUDENTMARK 表中插入记录时调用触发器,则必须在 STUDENTMARK 表中定义触发器!

标签: sql database triggers oracle11g


【解决方案1】:

您插入的是表格,而不是视图,因此不会发生触发事件。如果您插入到视图中,它会执行您所期望的操作:

INSERT INTO STUDENTMARK_VIEW (STUD_ROLLNO,CLASS_NAME,MARK1,MARK2) 
  VALUES (1,'CSE_B',100,100);

SELECT * FROM STUDENTMARK;

STUD_ROLLNO CLASS_NAME      MARK1      MARK2      TOTAL
----------- ---------- ---------- ---------- ----------
          1 CSE_B             100        100        200 

触发器中不需要单独的insert和update语句,可以在insert期间计算总数:

INSERT INTO STUDENTMARK (STUD_ROLLNO,CLASS_NAME,MARK1,MARK2,TOTAL)
  VALUES (:NEW.STUD_ROLLNO,:NEW.CLASS_NAME,:NEW.MARK1,:NEW.MARK2,
    :NEW.MARK1+:NEW.MARK2);

视图似乎有点毫无意义,因为它与表格完全匹配。正如您所看到的,没有什么可以阻止直接插入表中并跳过计算。如果您计划通过适当的授予权限允许其他人插入视图而不是表中,这将是一些有意义的,但所有者仍然可以始终直接插入到表中

如果您想计算总数,您可以将该列从基表中删除并在视图中计算:

CREATE TABLE STUDENTMARK
(
    STUD_ROLLNO NUMBER(10),
    CLASS_NAME VARCHAR2(10),
    MARK1 NUMBER(5),
    MARK2 NUMBER(5)
);

CREATE VIEW STUDENTMARK_VIEW AS
SELECT STUD_ROLLNO, CLASS_NAME, MARK1, MARK2, MARK1 + MARK2 AS TOTAL
FROM STUDENTMARK;

INSERT INTO STUDENTMARK (STUD_ROLLNO,CLASS_NAME,MARK1,MARK2) 
  VALUES (1,'CSE_B',100,100);

SELECT * FROM STUDENTMARK;

STUD_ROLLNO CLASS_NAME      MARK1      MARK2
----------- ---------- ---------- ----------
          1 CSE_B             100        100 

SELECT * FROM STUDENTMARK_VIEW;

STUD_ROLLNO CLASS_NAME      MARK1      MARK2      TOTAL
----------- ---------- ---------- ---------- ----------
          1 CSE_B             100        100        200 

或者在基表上使用虚拟列:

CREATE TABLE STUDENTMARK
(
    STUD_ROLLNO NUMBER(10),
    CLASS_NAME VARCHAR2(10),
    MARK1 NUMBER(5),
    MARK2 NUMBER(5),
    TOTAL NUMBER(5) GENERATED ALWAYS AS (MARK1 + MARK2)
);

INSERT INTO STUDENTMARK (STUD_ROLLNO,CLASS_NAME,MARK1,MARK2) 
  VALUES (1,'CSE_B',100,100);

SELECT * FROM STUDENTMARK;

STUD_ROLLNO CLASS_NAME      MARK1      MARK2      TOTAL
----------- ---------- ---------- ---------- ----------
          1 CSE_B             100        100        200 

或者保留物理列并在执行计算的表上设置触发器;但是在 11g 上,使用虚拟列更简单、更安全。

【讨论】:

    猜你喜欢
    • 2013-09-08
    • 1970-01-01
    • 2016-05-22
    • 2013-06-19
    • 1970-01-01
    • 2015-07-16
    • 2017-09-27
    • 1970-01-01
    相关资源
    最近更新 更多