sql >> Database teknologi >  >> RDS >> Oracle

Antal(*) fungerer ikke korrekt

Et par punkter. For det første misbruger du pragmaen for autonome transaktioner. Det er beregnet til separate transaktioner, du skal forpligte eller rulle tilbage uafhængigt af hovedtransaktionen. Du bruger den til at rulle hovedtransaktionen tilbage -- og du forpligter dig aldrig, hvis der ikke er nogen fejl.

Og de "uforudsete konsekvenser", som nogen nævnte? En af dem er, at din optælling altid returnerer 0. Så fjern pragmaen, både fordi den bliver misbrugt, og så vil optællingen returnere en ordentlig værdi.

En anden ting er, at du ikke har commits eller rollbacks inden for triggere. Ret en fejl, og lad den kontrollerende kode gøre, hvad den skal gøre. Jeg ved, at tilbagefaldene var på grund af pragmaen. Bare glem ikke at fjerne dem, når du fjerner pragmaen.

Følgende trigger virker for mig:

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;

Det er dog ikke en god idé for en trigger på et bord at få adgang til den tabel separat. Normalt vil systemet ikke engang tillade det -- denne trigger vil slet ikke udføres, hvis den ændres til "efter". Hvis den får lov til at udføre, kan man aldrig være sikker på de opnåede resultater - som du allerede har fundet ud af. Faktisk er jeg lidt overrasket over, at udløseren ovenfor virker. Jeg ville føle mig utryg ved at bruge den i en rigtig database.

Den bedste mulighed, når en trigger skal adgang til måltabellen er at skjule tabellen bag en visning og skrive en "i stedet for" trigger på visningen. Det trigger kan få adgang til tabellen alt, hvad den vil.



  1. Django ORM lækker forbindelser, når du bruger ThreadPoolExecutor

  2. NO_DATA_FOUND undtagelse blev ikke kastet, når den bruges i SELECT INTO

  3. mysqld-tjenesten stopper en gang om dagen på ec2-serveren

  4. sql server, kaskade sletning og overordnet/underordnet tabel