¿Por qué no puedo ACTUALIZAR una tabla de Postgresql donde tengo definido un DISPARADOR (TRIGGER) con ANTES DE ACTUALIZAR?
En PostgreSQL, tengo una tabla con un disparador definido que llama a una función definida en PostgreSQL. El disparador es “BEFORE UPDATE”. Con el disparador definido, no puedo realizar actualizaciones en la tabla en cuestión. Si redefino el disparador como “AFTER UPDATE”, todo funciona correctamente. ¿Alguna idea de por qué?
La tabla es similar a la siguiente:
create table user (
id bigserial constraint pk_user primary key,
username varchar,
hasreadinstructions smallint,
hasstarted smallint,
hasendeddataentry smallint,
hasviewedresults smallint,
email varchar,
firstname varchar,
lastname varchar,
registrationdate timestamp);
Y la función es:
create function perform_notify() returns trigger
language plpgsql
as
$$
BEGIN
PERFORM pg_notify(‘has_read_instructions’, ‘foo’);
RETURN NULL;
END;
$$;
El disparador es:
CREATE TRIGGER has_read_instructions BEFORE UPDATE
ON user FOR EACH ROW EXECUTE PROCEDURE
perform_notify();
Si defino el disparador con BEFORE UPDATE, como se muestra, las actualizaciones en la tabla no funcionan, por ejemplo:
update user set hasreadinstructions = 1 where id = 1;
El resultado es UPDATE 0 y el valor no cambia.
Si cambio el disparador a “AFTER UPDATE”, todo parece funcionar correctamente y mi actualización en la tabla se realiza con el resultado UPDATE 1 y el valor se cambia.
En este caso, no me importa particularmente si uso BEFORE o AFTER, pero estoy perdido en cuanto a por qué; cualquier ayuda para entender esto será apreciada.
davy.ai
El motivo del problema se debe al hecho de que el desencadenador
BEFORE UPDATE
se dispara antes de que se realice la actualización real. En este caso, se llama a la funciónperform_notify()
antes de que se realice la actualización, notificando así a las partes necesarias que el usuario ha leído las instrucciones. Sin embargo, como la actualización aún no se ha realizado, la columnahasreadinstructions
aún está configurada en su valor original de 0, y tratar de actualizarla a 1 con la instrucciónUPDATE
no produce cambios.Por otro lado, si el desencadenador se define como
AFTER UPDATE
, la funciónperform_notify()
se llama después de que se haya realizado la actualización, permitiendo así que la columna se actualice al valor deseado de 1 antes de que se envíe la notificación.Por lo tanto, la elección de utilizar
BEFORE
oAFTER
depende del comportamiento deseado del desencadenador y si debe ejecutarse antes o después de que se realice la actualización.