2013-12-17 42 views
0

我試圖讓這個代碼排序,而且它編譯,但是當我通過刪除一條記錄測試,如果給出了: 無效的IDOracle觸發器不起作用

該錯誤可能是在:老部分,但我無法弄清楚。

這是我的代碼。

create or replace trigger t_OnDeleteCategory 
create or replace trigger t_OnDeleteCategory 
before delete on Categorie 
for each row 
declare 
v_textMail varchar2(2000); 
v_emailAdres MailAbonnee.emailAdres%type; 
v_Voornaam MailAbonnee.voornaam%type; 
v_Achternaam MailAbonnee.Achternaam%type; 
c_cursor SYS_REFCURSOR; 
v_sql varchar2(2000); 
v_categorienaam categorie.naam%type; 
begin 
v_categorienaam := :old.naam; 
--1) mailbericht verzenden 
v_sql := 'select voornaam, achternaam, emailAdres from MailAbonnee where id in (select mailAbonneeID from CategorieAbonnement where categorieNaam = v_categorienaam)'; 
open c_cursor for v_sql; 
loop 
    fetch c_cursor into v_Voornaam, v_Achternaam, v_emailAdres; 
    exit when c_cursor%notfound; 
    v_textMail := 'Beste ' || v_Voornaam || ' ' || v_Achternaam || ', uw abonnement is opgeheven voor Categorie '|| v_categorienaam || '.'; 
    sendMailAbonnee(v_textMail, v_emailadres); 
end loop; 
--2) verwijder alle abonnementen 
delete from CategorieAbonnement where categorieNaam = v_categorienaam; 
--3) pas alle nieuwsberichten aan 
update Nieuwsbericht set categorieNaam = '' where categorieNaam = v_categorienaam; 
end; 
+1

是否有原因需要在觸發器中使用動態SQL?在這裏似乎沒有必要。但是也許你已經簡化了這個問題以便在這裏發佈,並且在你的實際代碼中有一些原因需要動態SQL。 –

+0

你能向我們展示'Categorie'和'MailAbonnee'的表結構嗎? – Drumbeg

+0

你有'創建或替換觸發器t_OnDeleteCategory'兩次在開始 –

回答

2

像@JustinCave建議,你的動態SQL有問題。 v_categorienaam是一個變量,它在你的SQL的字符串中。刪除動態SQL,你的問題就會消失。

此外,還可以通過使用遊標循環簡化代碼很多,像:

create or replace trigger t_OnDeleteCategory 
before delete on Categorie 
for each row 
declare 
    v_textMail varchar2(2000); 
begin 
    --1) mailbericht verzenden 
    for c in (
    select voornaam, achternaam, emailAdres 
    from MailAbonnee 
    where id in (
     select mailAbonneeID from CategorieAbonnement where categorieNaam = :old.naam 
    ) 
) loop 
    v_textMail := 'Beste ' || c.voornaam || ' ' || c.achternaam || ', uw abonnement is opgeheven voor Categorie '|| c.naam || '.'; 
    sendMailAbonnee(v_textMail, c.emailadres); 
    end loop; 
    --2) verwijder alle abonnementen 
    delete from CategorieAbonnement where categorieNaam = :old.naam; 
    --3) pas alle nieuwsberichten aan 
    update Nieuwsbericht set categorieNaam = '' where categorieNaam = :old.naam; 
end; 
+0

此外,您可以通過使您的數據庫外鍵'刪除級聯'和'刪除集空'分別刪除步驟2和3。 –

1

在這一行:

v_sql := 'select voornaam, achternaam, emailAdres from MailAbonnee where id in (select mailAbonneeID from CategorieAbonnement where categorieNaam = v_categorienaam)'; 

....你指到v_categorienaam,但這不是執行動態SQL時的範圍內的變量。您應該使用綁定變量:

v_sql := 'select voornaam, achternaam, emailAdres from MailAbonnee where id in (select mailAbonneeID from CategorieAbonnement where categorieNaam = :v_categorienaam)'; 

然後

open c_cursor for v_sql using v_categorienaam; 

但似乎沒有任何理由爲這是動態的,在所有的,因爲其他人已經指出。你可以擺脫v_sql,只是做:

open c_cursor for 
    select voornaam, achternaam, emailAdres 
    from MailAbonnee 
    where id in (
    select mailAbonneeID 
    from CategorieAbonnement 
    where categorieNaam = v_categorienaam; 

哪個更容易格式化和讀取,並可在解析/編譯時進行驗證,而不是讓你在運行時的任何潛在錯誤。科林的版本更簡單;你沒有從顯式獲取中獲得任何東西。