2012-05-08 52 views
0

我有以下表格:Oracle觸發器錯誤ORA-01427:錯誤ORA-04091

師資隊伍表

CREATE TABLE "FACULTY" 
    ( "FACULTY_ID" NUMBER(3,0), 
    "FACULTY_NAME" VARCHAR2(30), 
    "FACULTY_DEAN" VARCHAR2(30), 
    CONSTRAINT "FACULTY_PK" PRIMARY KEY ("FACULTY_ID") ENABLE 
    ) 

課程表

CREATE TABLE "COURSE" 
    ( "COURSE_ID" NUMBER(5,0), 
    "COURSE_NAME" VARCHAR2(50), 
    "COURSE_LEVEL" NUMBER, 
    "FACULTY" NUMBER, 
    CONSTRAINT "COURSE_PK" PRIMARY KEY ("COURSE_ID") ENABLE 
    ) 

所以現在我想實現兩件事

(1)在教員表上更新faculty_id時。觸發器將觸發並用新的faculty_id更新課程表中的相應行。它還會存儲舊的faculty_id值,課程名稱以及在course_log表中執行操作的日期。

下面是我得到

create or replace trigger update_faculty 
after update on faculty 
for each row 
begin 
    insert into course_log 
    values (:old.faculty_id, 
      (select course_name 
       from course 
       where faculty=:old.faculty_id), 
      sysdate); 
    update course 
     set faculty=:new.faculty_id 
    where faculty=:old.faculty_id; 
end; 

,但我得到了下面的錯誤。

錯誤ORA-01427:單行子查詢返回多個行ORA-06512:在 「SYSTEM.UPDATE_FACULTY」,第2行ORA-04088:錯誤觸發的執行期間 'SYSTEM.UPDATE_FACULTY'

關於如何解決它的任何想法? (2)編寫一個觸發器,當嘗試更改課程表中的course_id屬性時,它會檢查該值是否已經存在於課程表中,如果它是新值,則會成功更新。如果該值已存在於任何行中,則該觸發器將引發應用程序錯誤,指出「course_id已存在!更新不成功」。

下面

是我的查詢

CREATE OR REPLACE TRIGGER "UPDATE_COURSE_ID" 
after update on course 
for each row 
declare 
    error number; 
begin 
    select count(*) 
     into error 
    from course 
    where course_id=:new.course_id; 

    if error > 0 then 
     raise_application_error (-20000,'The course_id already found! Update not success'); 
    end if; 
    if error = 0 then 
     update course set course_id=:new.course_id where course_id=:old.course_id; 
    end if; 
end; 

但我得到這個錯誤

錯誤ORA-04091:表SYSTEM.COURSE都在變異,觸發/功能可能沒看出來ORA-06512:在「SYSTEM.UPDATE_COURSE_ID」,第5行ORA-04088:執行觸發期間出錯'SYSTEM.UPDATE_COURSE_ID'

+0

這功課嗎? –

+0

這是我用觸發器練習的一些練習。你能幫忙嗎? – user1382242

回答

0

對於第一個問題,由於您可能想要插入多行進入course_log表,你需要做這樣

create or replace trigger update_faculty 
    after update on faculty 
    for each row 
begin 
    -- I'm guessing about the definition of the course_log table 
    insert into course_log(faculty_id, course_name, log_date) 
    select :old.faculty_id, course_name, sysdate 
     from course 
     where faculty=:old.faculty_id; 

    update course 
     set faculty=:new.faculty_id 
    where faculty=:old.faculty_id; 
end; 

東西對於第二個問題,它沒有任何意義使用觸發器。你想要使用一個約束。並且您已經有course_id中的主鍵約束course已阻止重複course_id值。

用觸發器強制執行這種事情是一個非常糟糕的主意。由於course上的行級別觸發器無法查詢course表(除了插入語句始終爲單行表單INSERT ... VALUES或使用自治事務的觸發器的行級插入觸發器之外,這兩者在此均不適用) 。所以如果你真的想用觸發器做到這一點,你需要創建一個包含course_id值集合的包,一個用於初始化集合的before語句觸發器,一個將:new.course_id添加到集合的行級觸發器,以及遍歷集合的after語句觸發器並查找重複的值course_id。這是很多對象做的事情,不應該首先使用觸發器完成,並且已經由您的約束完成。如果你剛剛瞭解觸發器,我猜你還沒有被教過關於軟件包或集合的東西,這使得解決方案更加不合適。