Trigger – Disparadores en PosgreSQL

Un disparador o Trigger es una función con ciertas características, de ellas la mas relevante es que es invocada(llamada) automáticamente al suceder cierta acción sobre una tabla.

Este es el motivo de su nombre ya que son funciones que serán disparadas al suceder cierto evento, insertar un registro, borrar, editar, etc., ademas también podemos definir si este disparador ocurra antes o después de dicho evento.

Nota: para que una función sea denotada como trigger deberá ser declarada como una función que no reciba argumentos y deberá devolver un tipo trigger.

Imaginemos que tenemos el siguiente esquema de la tabla emp(empleados):

CREATE TABLE emp (
    empname text,
    salary integer,
    last_date timestamp,
    last_user text
);

Ahora para este ejemplo lo que pretendemos hacer es que validar los datos antes de ser intertados o actualizados en el registro de emp, para esto declaramos un disparador el cual deberá revisar los datos nuevos a insertar o actualizar, para esto PL/pgSQL nos brinda un objeto denominado NEW el cual tiene como miembro a los nuevos valores por insertar por ejemplo NEW.empname accede al valor de empname que introdujo el usuario al realizar la consulta update o insert. Veamos mejor el ejemplo.

CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
    BEGIN
        -- Revisando que el campo empname No este vacio
        IF NEW.empname IS NULL THEN
            RAISE EXCEPTION ’empname no puede ser null’;
        END IF;
	-- Revisando que el campo salary No este vacio
        IF NEW.salary IS NULL THEN
            RAISE EXCEPTION ’% salary no puede ser null’, NEW.empname;
        END IF;
        -- Salary tampoco puede llegar a ser negavito
        IF NEW.salary < 0 THEN
            RAISE EXCEPTION ’% no puede haber un salario negativo!’, NEW.empname;
        END IF;
        -- Generando los datos para la bitacola
        NEW.last_date := current_timestamp;
        NEW.last_user := current_user;
        RETURN NEW;
    END;
$emp_stamp$ LANGUAGE plpgsql;

De igual forma p.e. En el caso del UPDATE si quisiéramos comparar el valor anterior del campo empname podríamos acceder con desde el objeto OLD en este caso seria OLD.empname, por ultimo solo nos falta instanciar el Trigger a la tabla y eventos correspondientes.

CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp
    FOR EACH ROW EXECUTE PROCEDURE emp_stamp();

Para esto instanciamos el Trigger (CREATE TRIGGER) emp_stamp a la tabla(ON) emp para que sea ejecutado antes (BEFORE) una inserción u una actualización (INSERT OR UPDATE).

Conclusiones:

Como podemos ver un Trigger es una función que es ejecutada automáticamente por el motor de BD al generarse una acción, así también vimos un ejemplo claro de su uso común en la validación de los datos, ya que como podemos ver estas funciones las definimos en el estema de nuestra BD y con esto tenemos la seguridad que nuestras tablas se comportaran de la forma como la definimos, p.e. Si tenemos una aplicación de escritorio programada en Java y otra aplicación distribuida en PHP y ambas hacen uso de la tabla emp, con esto tendremos la certeza que la tabla emp nunca tendrá un campo con el valor salary negativo, sin importar la mala programación en Java o PHP.

Fuente Documentación oficial PosgreSQL 8.4.1 US:

http://www.postgresql.org/files/documentation/pdf/8.4/postgresql-8.4.1-US.pdf

La información fue extraída y traducida de:

  • 9.25. Trigger Functions – paginas 322-323
  • 12.4.3. Triggers for Automatic Updates – paginas 360-362
  • 38.9. Trigger Procedures – paginas 925-931

PostgreSQL 8.4.1 Documentation  by The PostgreSQL Global Development Group  Copyright ©

Anuncios

5 thoughts on “Trigger – Disparadores en PosgreSQL

  1. Pingback: Trigger – Disparadores en PosgreSQL - DbRunas

  2. Hola Fitorec espero que estes bien!! Tengo un problemita espero me puedas ayudar
    Estoy haciendo un trigger para update con la finalidad de que cada vez que se realice un cambio en cierta tabla (origen p ej.) me lo registre en otra (destino p ej.), ahora bien todo iba perfecto hasta que me encontré con campos vacíos en la tabla origen ya que el mismo no registra en la tabla destino cuando se modifican esos campos vacios, es decir, es necesario llenar toda la tabla para que me pueda hacer el registro en destino, probe con hacer if (a_old.dicho_campo is not null) then
    begin
    if (a_new.dicho_campo a_old.dicho_campo) then
    resultado := resultado ||’dicho_campo:’ ||a_old.dicho_campo||’=>’||a_new.adicho_campo||;
    end if;
    end;
    else
    resultado := resultado ||’dicho_campo:’||’=>’||a_new.adicho_campo||;
    end if;
    corre correctamente mas no hace nada 😦
    esto es en postgresql 8.3
    de antemano gracias por la ayuda estare pendiente de tu respuesta gracias..

    • Tal vez la cadena no es nula si no vacia prueba haciendo case con if (a_old.dicho_campo IS NOT ” ) then …

      Creo que es eso lo que te esta pasando, pero probar y si no le hayas por aquí andamos :¬)

      • Hola gracias por la respuesta pero si ya probé con todo eso, la verdad estoy cambiando la metodología estoy tratando de otras maneras xq la que conseguí es muy larga y tediosa, ahora estoy probando pasándole los parámetros de la tabla en cuestión es decir estoy buscando la manera de que me pase los valores old concatenando el nombre del campo para cada tabla. en este momento estoy buscando el análogo de TG_TABLE_NAME pero para obtener el nombre de los campos no se si me explique 😦 :S

      • Prueba con definir tus campos valores por defectos en tu esquema de BD a estos campos que te generan conflicos(p.e. `campo` VARCHAR(50) DEFAULT 'valor-por-defecto').

        ¿Como tienes definido tu esquema y que quieres hacer?.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s