Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Zählen (*) funktioniert nicht richtig

Ein paar Punkte. Erstens missbrauchen Sie das Pragma der autonomen Transaktion. Es ist für separate Transaktionen gedacht, die Sie unabhängig von der Haupttransaktion festschreiben oder rückgängig machen müssen. Sie verwenden es, um die Haupttransaktion rückgängig zu machen – und Sie führen niemals ein Commit durch, wenn kein Fehler vorliegt.

Und diese "unvorhergesehenen Folgen", die jemand erwähnt hat? Einer davon ist, dass Ihre Zählung immer 0 zurückgibt. Entfernen Sie also das Pragma, weil es missbraucht wird und die Zählung einen korrekten Wert zurückgibt.

Eine andere Sache ist, dass innerhalb von Triggern keine Commits oder Rollbacks vorhanden sind. Lösen Sie einen Fehler aus und lassen Sie den steuernden Code tun, was er tun muss. Ich weiß, dass die Rollbacks wegen des Pragmas waren. Vergessen Sie nur nicht, sie zu entfernen, wenn Sie das Pragma entfernen.

Der folgende Trigger funktioniert bei mir:

CREATE OR REPLACE TRIGGER trg_mytable_biu 
BEFORE INSERT OR UPDATE ON mytable 
FOR EACH ROW 
WHEN (NEW.TYPEB = 'Bert') -- Don't even execute unless this is Bert
DECLARE
    L_COUNT NUMBER;
BEGIN
    SELECT  COUNT(*) INTO L_COUNT
    FROM    MYTABLE 
    WHERE   ARTICLE = :NEW.ARTICLE
        AND TYPEB = :NEW.TYPEB;

    IF L_COUNT > 0  THEN
        RAISE_APPLICATION_ERROR( -20001, 'Bert already exists!' );
    ELSIF :NEW.STOCK_COUNT > 1 THEN
        RAISE_APPLICATION_ERROR( -20001, 'Can''t insert more than one Bert!' );
    END IF;
END;

Es ist jedoch keine gute Idee, dass ein Trigger für eine Tabelle separat auf diese Tabelle zugreift. Normalerweise lässt das System dies nicht einmal zu – dieser Trigger wird überhaupt nicht ausgeführt, wenn er auf „after“ geändert wird. Wenn es ausgeführt werden darf, kann man sich der erzielten Ergebnisse nie sicher sein – wie Sie bereits herausgefunden haben. Eigentlich bin ich ein wenig überrascht, dass der Trigger oben funktioniert. Ich würde mich unwohl fühlen, wenn ich es in einer echten Datenbank verwende.

Die beste Option, wenn ein Auslöser muss Der Zugriff auf die Zieltabelle besteht darin, die Tabelle hinter einer Ansicht zu verstecken und einen "statt"-Trigger auf die Ansicht zu schreiben. Das Trigger kann auf die Tabelle zugreifen, wie er will.