2016-05-23 7 views
0

Ich habe um diesen Auslöser gearbeitet und wenn ich das Skript ausführe, sagt es mir die vorherige Fehlermeldung. Ich kann nicht herausfinden, warum es nicht richtig kompilieren wird, jedes pl/sql Trigger-Tutorial scheint die Struktur zu haben, die mein Auslöser hat. Code ist folgende:ORA-24344: Erfolg mit Kompilierungsfehler - Auslöser APEX

create 
    or replace trigger new_artist before insert 
     on 
     Artist referencing new as nvartist declare counter number; 

begin select 
    count(*) into 
     counter 
    from 
     Performer 
    where 
     Stage_name = nvartist.Stage_name; 

if counter > 0 then signal sqlstate '45000'; 
else insert 
    into 
     Artist 
    values(
     nvartist.Stage_name, 
     nvartist.Name 
    ); 

insert 
    into 
     Performer 
    values(nvartist.Stage_name); 
end if; 
end; 

Es wird überprüft, ob der neue Künstler bereits in seinem Supertyp (Performer) liegt vor, wenn es existiert es einen Fehler gibt, wenn er es nicht fügt beide in Künstler (Stage_name varchar2, Namens- varchar2) und Performer (Stage_name). Ein weiterer Subtyp von Performer (und Geschwister zu Artist) ist Band (Stage_name), der wiederum eine Beziehung zu Artist hat. Warum schreit der Compiler mich wegen dieses Triggers an?

Vielen Dank im Voraus

+0

Es sollte trotzdem in Runtime aufgrund muting Triggerfehler fehlschlagen, während Sie versuchen, Daten in der gleichen zugrundeliegenden Tabelle einzufügen. –

+0

Ich lese darüber, ich habe verstanden, dass der Trigger fehlschlagen sollte, wenn es mit der Zeile, die eingefügt wurde/aktualisiert, wenn es direkt oder indirekt diese Zeile innerhalb des Triggers gelöscht, scheint es nicht der Fall zu sein. Mein Ziel ist es, zu überprüfen, ob Stage_name bereits in Performer vorhanden ist, bevor Sie ihn in Artist einfügen. Wenn es existiert (da es sich bei der Beziehung um eine disjunkte isa (Performer ISA Artist/Band) handelt, gibt es einen Fehler, aber wenn es nicht existiert, fügt es sowohl in Artist als auch in Performer ein. Ich dachte, das würde das erreichen. – Punk

+0

In Oracle gibt es keinen SIGNAL-Befehl. Das ist MySql. Dieser Trigger wird nicht kompiliert. Verwenden Sie anstelle von Signal raise_application_error. Sie können nicht in dieselbe Tabelle einfügen und müssen dies nicht tun. Löschen Sie den Befehl "In Artist einfügen". Dies wird automatisch durchgeführt. – Mottor

Antwort

0

Möglicherweise möchten Sie diese Variante, um zu versuchen (I Namen Ihrer Tabellen leicht modifiziert). Erstellen von Tabellen mit Beispieldaten:

CREATE table test_artist(
    stage_name varchar2(100) 
, name varchar2(100) 
); 

create table test_performer(
    stage_name varchar2(100) 
); 

/*inserting test performer on which trigger will rise an error*/ 
insert into test_performer 
select 'performer_1' from dual; 

Erstellen von Trigger:

create or replace trigger new_artist 
    before insert 
    on TEST_ARTIST 
    referencing new as nvartist 
    for each row 

declare 
    counter number; 
begin 
    select count(*) 
    into counter 
    from test_performer 
    where Stage_name = :nvartist.Stage_name; 

    if counter > 0 then 
     --signal sqlstate '45000' ; 
     raise_application_error(-20001, 'No insertion with existing Performer'); 
    else 
     /*you cant update the same table, in other case you'll get 
     ora-04091 table mutating error.  
     But nevertheless this values will be inserted by sql triggered this trigger.*/ 
     --insert into test_artist values(:nvartist.Stage_name, :nvartist.Name);  
     insert into test_performer values(:nvartist.Stage_name); 
    end if; 
end new_artist; 

Danach dieser Einsatz funktioniert, führen die keine 'performer_2' in 'test_performer' Tabelle:

insert into test_artist 
select 'performer_2', 'name_2' from dual; 

Und dies wird fehlschlagen:

insert into test_artist 
select 'performer_1', 'name_1' from dual; 
+0

Danke für die eingehende Antwort. Ich hatte den Verdacht, dass der Tisch mutierte, aber ich war mir nicht sicher, ob die Einfügung in den Künstler immer noch passieren würde. Ist 'nicht für jede Reihe' hier überflüssig? Da der Zähler mit einer Zählungsabfrage gefüllt wird, muss ich trotzdem jede Zeile überprüfen? – Punk

+0

Hallo, @Punk! "Die Option FÜR JEDE ZEILE bestimmt, ob der Trigger ein Zeilentrigger oder ein Anweisungstrigger ist." Sie können viele Zeilen pro Anweisung in die 'Artist'-Tabelle einfügen. Es scheint also, dass Sie für jede einzelne Zeile eine Performer-Existenzprüfung durchführen müssen. Und der andere: NEUE oder alte Referenzen sind in Triggern auf Tabellenebene nicht erlaubt. –