sql >> Base de Datos >  >> RDS >> Oracle

Count(*) no funciona correctamente

Un par de puntos. Primero, está haciendo un mal uso del pragma de transacción autónomo. Está destinado a transacciones separadas que necesita confirmar o revertir independientemente de la transacción principal. Lo está utilizando para deshacer la transacción principal, y nunca se compromete si no hay ningún error.

¿Y esas "consecuencias imprevistas" que alguien mencionó? Una de ellas es que su conteo siempre devuelve 0. Así que elimine el pragma porque se está utilizando incorrectamente y para que el conteo devuelva un valor adecuado.

Otra cosa es no tener compromisos o reversiones dentro de los disparadores. Genere un error y deje que el código de control haga lo que debe hacer. Sé que los retrocesos se debieron al pragma. Simplemente no olvide eliminarlos cuando elimine el pragma.

El siguiente disparador funciona para mí:

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;

Sin embargo, no es una buena idea que un disparador en una tabla acceda por separado a esa tabla. Por lo general, el sistema ni siquiera lo permitirá; este activador no se ejecutará en absoluto si se cambia a "después". Si se permite su ejecución, uno nunca puede estar seguro de los resultados obtenidos, como ya descubrió. En realidad, estoy un poco sorprendido de que el disparador anterior funcione. Me sentiría incómodo usándolo en una base de datos real.

La mejor opción cuando un disparador debe acceder a la tabla de destino es ocultar la tabla detrás de una vista y escribir un disparador "en lugar de" en la vista. Eso trigger puede acceder a la tabla todo lo que quiera.