Re: Variable NEW en una funcion para un trigger

From: "Fernando Moreno" <azazel(dot)7(at)gmail(dot)com>
To: "Juan Luis Echeverria" <juanluise(at)usa(dot)net>
Cc: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Variable NEW en una funcion para un trigger
Date: 2008-05-02 17:50:00
Message-ID: b1c45530805021050l45b55333gbe6b24edd9d0b476@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

No creo que EXECUTE te sirva para evaluar expresiones que no sean consultas.
He realizado algunas búsquedas, y veo que el acceso dinámico a variables
RECORD y la introspección sobre las mismas es un tema poco documentado y
complejo.

Pienso que un camino alternativo podría ser el siguiente: Si las columnas
con nombres cambiantes (por lo que veo son dos) sólo las usas para asignarle
valores que se insertarán/actualizarán, es decir, como valores "de lado
izquierdo" y nunca como "de lado derecho" (no consultas sus valores), puedes
crear una variable RECORD a la que asignes mediante un SELECT INTO, los
valores comunes desde NEW, y los reasignados, con las variables new_idsync y
new_sync. Regresando ese nuevo RECORD conseguirías el efecto deseado,
supongo :) .

2008/5/2 Juan Luis Echeverria <juanluise(at)usa(dot)net>:

> Hola:
> Solicito me aclaren una duda porfavor: Tengo un trigger BEFORE INSERT FOR
> EACH ROW y en la funcion (con PL/pgSQL Postgresql 8.1) que usa en una de
> sus
> lineas tiene la siguiente instrucción:
>
> NEW.idsync008 = new_sync;
>
> en donde idsync008 es un campo de la tabla afectada por el trigger. Esta
> instrucción funciona pero la quiero sustituir por esta otra
>
> EXECUTE 'NEW.' || trim(both '' from idsyncxxx) || ' = ' ||
> new_idsync || ';';
>
> En donde syncxxx es una variable que ser ercibe como argumento en la
> funcion
> y que contiene el valor 'idsync008'. Esta ultima instrucción no me
> funciona;
> al consultar el log, veo esta descripcion para el error
>
> 2008-05-01 23:19:54 ERROR: syntax error at or near "NEW" at character 1
> 2008-05-01 23:19:54 QUERY: NEW.idsync008 = 15;
> 2008-05-01 23:19:54 CONTEXT: PL/pgSQL function "sync_marj" line 35 at
> execute statement
>
> Mi pregunta es: realmente se puede usar la variable NEW de la forma en que
> lo quiero hacer? Y si no, hay alguna otra forma de hacer lo que necesito ?
> Lo quiero hacer asi debido a que esta funcion tienen que usarla mas o
> menos
> 100 tablas y pues, ya saben, me quiero evitar el tener que hacer 100
> funciones en donde lo unico que variara para cada una seran unos cuantos
> campos que bien se pudieran recibir como argumentos en dicha funcion. Por
> cierto, la variable TG_TABLE_NAME tampoco me funciona pero no me causa
> problema ya que puedo recibir el nombre de la tabla en los argumentos de
> la
> funcion.
> Gracias por su ayuda.
>
> Saludos.
>
>
> --------------------
> Juan Luis Echeverria
> juanluise(at)cresolt(dot)info
>
> PD.
> Si sirve de algo, esta es la funcion y el trigger que mencionaba arriba:
>
> CREATE OR REPLACE FUNCTION sync_marj() RETURNS TRIGGER AS $back$
> DECLARE
> --argumentos
> idsyncxxx character(9) = TG_ARGV[0];
> syncxxx character(7) = TG_ARGV[1];
> tabla_evaluada character(25) = TG_ARGV[2];
>
> --variables a usar dentro del bloque
> sync_on usparamweb.usanumrecibos%TYPE;
> last_idsync cxabonos.idsync008%TYPE = 0;
> new_idsync cxabonos.idsync008%TYPE = 0;
> new_sync cxabonos.sync008%TYPE = 0;
> new_codinst usinstituciones.codinst%TYPE;
> contador_registros bigint = 0;
> query1 varchar;
>
> BEGIN
>
> --Si el evento es un insert
> IF (TG_OP = 'INSERT') THEN
> --Determina si esta activa la sincronizacion en la empresa
> del registro a insertar
> new_codinst = NEW.codinst;
> SELECT usanumrecibos INTO sync_on FROM usparamweb where
> codinst = new_codinst;
> --indica que si esta activa la replicacion
> IF sync_on > 0 THEN
>
> --Trae el ultimo valor de IDSync para la tabla que
> se esta recorriendo
> query1 := 'SELECT ' || TG_ARGV[0] || ' FROM '||
> tabla_evaluada || ' WHERE codinst = ' || new_codinst || ' ORDER BY
> codinst,
> ' || TG_ARGV[0] || ' DESC LIMIT 1;';
> EXECUTE query1 INTO last_idsync;
>
> --Incremente en 1 el utimo valor encontrado de
> idsync008
> new_idsync = last_idsync + 1;
>
> --Actualiza los campos IDSync_ y Sync_ de la tabla
> que se esta afectando
> --NEW.idsync008 = new_idsync;
>
> EXECUTE 'NEW.' || trim(both '' from idsyncxxx) ||
> '
> = ' || new_idsync || ';';
>
> --NEW.sync008 = new_sync;
> EXECUTE 'NEW.' || trim(both '' from syncxxx) || ' =
> ' || new_sync || ';';
>
> --crea nuevo registro (si no existe) en
> USSyncTablas
> correspondiente a la tabla que aqui se esta evaluando
> --verifica si ya existe el registro correspondiente
> a la tabla evaluada
> SELECT count(*) INTO contador_registros FROM
> ussynctablas WHERE codinst = new_codinst AND tablasync = tabla_evaluada;
> --Si no existe el registro se hara un INSERT
> IF contador_registros = 0 THEN
>
> --nuevo registro que indica que la tabla
> evaluada debe ser sincronizada
> INSERT INTO ussynctablas
> VALUES(new_codinst,
> tabla_evaluada, now());
> END IF;
>
> END IF;
> END IF;
> RETURN NEW;
> END;
> $back$ LANGUAGE plpgsql;
>
> DROP TRIGGER trigger_test ON cxabonos;
>
> CREATE TRIGGER trigger_test BEFORE
> INSERT ON cxabonos
> --Los primeros 2 argumentos son los campos a modificar; el tercero es el
> nombre de la tabla a afectar.
> FOR EACH ROW EXECUTE PROCEDURE sync_marj('idsync008','sync008','cxabonos'
> );
>
>
>
>
> --
> TIP 9: visita nuestro canal de IRC #postgresql-es en irc.freenode.net
>

In response to

Responses

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Juan Luis Echeverria 2008-05-02 18:44:23 RE: Variable NEW en una funcion para un trigger
Previous Message Alvaro Herrera 2008-05-02 17:35:26 Re: Variable NEW en una funcion para un trigger