更新语句不起作用而不是触发器oracle11g

时间:2015-03-06 09:20:46

标签: sql database triggers oracle11g

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

A)写一个PL / SQL触发器以更新学生标记'表 插入发生在同一个表中。 QUERY:

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的值但没有更新总数 - 错误是什么?

1 个答案:

答案 0 :(得分:2)

您正在插入表格而不是视图,因此触发事件不会发生。如果你插入视图,它会做你期望的事情:

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 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时更简单,更安全。