Jump to content


Photo

Trigger auditoria


  • Please log in to reply
13 replies to this topic

#1 fjcg02

fjcg02

    Newbie

  • Miembros
  • Pip
  • 4 posts

Posted 15 March 2010 - 10:52 AM

Hola a todos,
estoy intentando hacer un trigger 'generico' que me permita almacenar en una tabla los campos que se han modificado de cada tabla.
El problema que tengo es que no consigo acceder a los valores  old.campo y new.campo desde un execute statement.
Os pego algo de lo que he realizado, aunque he intentado un sinfín de variedades.
La idea sería hacerlo sólo para modificaciones de registros.

Agradecería cualquier ayuda.

Gracias



sql
  1. AS
  2. DECLARE variable WCAMPO VARCHAR(50);
  3. DECLARE variable sentencia VARCHAR(500);
  4. BEGIN
  5.   /* Trigger text */
  6.  
  7.   FOR SELECT RF.RDB$Field_Name CAMPO  /* Nombre del campo */
  8.       FROM RDB$Relation_Fields RF
  9.       WHERE RF.RDB$Relation_Name = 'TABLA' /* Aqui la tabla del trigger */
  10.       INTO :WCAMPO
  11.   DO
  12.     BEGIN
  13.       WCAMPO= TRIM(WCAMPO);
  14.       sentencia =  'IF (new.'||:WCAMPO ||'IS NOT NULL) THEN '||
  15.       'BEGIN '||
  16.         'IF (OLD.'||:WCAMPO||' <> NEW.'||:WCAMPO||' ) THEN ' ||
  17.           'INSERT INTO AUDITORIA (IDAUDITORIA, FECHA, USUARIO, IDREGISTRO,'||
  18.                                   'TABLA, CAMPO, VALORVIEJO,VALORNUEVO) '||
  19.             'VALUES (GEN_ID(AUDITORIA,1), '||'''NOW'''||', NEW.USUARIOMODIF, NEW.IDPOLIZA,'||
  20.                                 '''POLIZA'','''||:WCAMPO||''', CAST(OLD.'||:WCAMPO||' AS VARCHAR(50)),CAST( NEW.'||:WCAMPO||' AS VARCHAR(50)) ); '||
  21.       'END' ;
  22.     END
  23.     EXECUTE statement sentencia;
  24.  
  25. END




Otra variante que he intentado



sql
  1. AS
  2. DECLARE variable WCAMPO VARCHAR(50);
  3. DECLARE variable woldvalor VARCHAR(100);
  4. DECLARE variable wNEWvalor VARCHAR(100);
  5. DECLARE variable sentencia VARCHAR(500);
  6. BEGIN
  7.   /* Trigger text */
  8.  
  9.   FOR SELECT RF.RDB$Field_Name CAMPO  /* Nombre del campo */
  10.       FROM RDB$Relation_Fields RF
  11.       WHERE RF.RDB$Relation_Name = 'POLIZA' /* Aqui la tabla del trigger */
  12.       INTO :WCAMPO
  13.   DO
  14.     BEGIN
  15.       WCAMPO= TRIM(WCAMPO);
  16.       EXECUTE STATEMENT 'NEW.'||:WCAMPO INTO WNEWVALOR;
  17.       IF (WNEWVALOR IS NOT NULL) THEN
  18.       BEGIN
  19.         EXECUTE STATEMENT 'SELECT OLD.'||:WCAMPO || ' FROM RDB$DATABASE' INTO WOLDVALOR;
  20.         IF (WOLDVALOR <> WNEWVALOR ) THEN
  21.         BEGIN
  22.         SENTENCIA = 'INSERT INTO AUDITORIA (IDAUDITORIA, FECHA, USUARIO, IDREGISTRO,'||
  23.                                   'TABLA, CAMPO, VALORVIEJO,VALORNUEVO) '||
  24.             'VALUES (GEN_ID(AUDITORIA,1), '||'''NOW'''||', NEW.USUARIOMODIF, NEW.IDPOLIZA,'||
  25.                                 '''POLIZA'','''||:WCAMPO||''', CAST(OLD.'||:WCAMPO||' AS VARCHAR(50)),CAST( NEW.'||:WCAMPO||' AS VARCHAR(50)) ); ';
  26.         END
  27.         EXECUTE statement sentencia;
  28.       END
  29.   END
  30. END


  • 0

#2 pcicom

pcicom

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 267 posts
  • LocationMéxico

Posted 15 March 2010 - 11:34 AM

No te convendria y seria mas FACIL clonar tu TABLA(S) obviamante las mas importantes y grabar todo el REGISTRO en la tabla historial de cambios con los datos del USUARIO

Por ejemplo.

Tabla CLIENTES ----  tendria una tabla llamada HClientes  <-- que seria la del hostorial

Cuando hagas un UPDATE disparas un trigger INSERTANDO en la tabla HISTORIAL todo el REGISTRO..

SUPONIENDO..  lo pondrias en el TRIGGER de la tabla al hacer el UPDATE...



sql
  1.       INSERT INTO HClientes (numero,nombre,direccion,usuario,fecha...)
  2.                           VALUES (OLD.numero,OLD.nombre,OLD.direccion,[b]NEW.usuario,NEW.fecha[/b]...)



Es mas simple y no se te escapa nada...


SALUDOS..





  • 0

#3 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2092 posts
  • LocationRepública Dominicana

Posted 15 March 2010 - 12:12 PM

Saludos.

¿Puedes indicarnos que error te muestra?, ¿Has probado con poner directo los campos?

Con esta ultima pregunta me refiero a escribir 'OLD.CAMPO1' en vez de concatenaciones simplemente para ver si el EXECUTE se ejecuta correctamente.


  • 0

#4 HSEGURAC1976

HSEGURAC1976

    Newbie

  • Miembros
  • Pip
  • 2 posts

Posted 24 November 2011 - 06:15 PM

Un saludo cordial a todos los que nos ayudan, muchas gracias de antemano y quisiera saber si alguno ya pudo hacer esto de la auditoria, es que un cliente me exige que guarde el usuarop que hizo la midificacion , szobre que campo se hizo dicha modificacion, ademas del valor antes de modificarlo y despues de modificarlo, es intentado hacer lo de la clonacion pero es muy engorroso debido a la gran cantidad de tablas y de campos que constantemente se estan creando, muchas gracias no se si seria posible algun ejemplo
  • 0

#5 felipe

felipe

    Advanced Member

  • Administrador
  • 3283 posts
  • LocationColombia

Posted 24 November 2011 - 10:50 PM

Un saludo cordial a todos los que nos ayudan, muchas gracias de antemano y quisiera saber si alguno ya pudo hacer esto de la auditoria, es que un cliente me exige que guarde el usuarop que hizo la midificacion , szobre que campo se hizo dicha modificacion, ademas del valor antes de modificarlo y despues de modificarlo, es intentado hacer lo de la clonacion pero es muy engorroso debido a la gran cantidad de tablas y de campos que constantemente se estan creando, muchas gracias no se si seria posible algun ejemplo


Hola y bienvenido,
te recomendaría que hicieras un nuevo tema y fueras más puntual en lo que buscas y lo que tienes, para partir de allí a buscar una idea apropiada.


Saludos!
  • 0

#6 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 posts
  • LocationEspaña

Posted 25 November 2011 - 01:51 AM

Buenas,

Si no voy equivocado, desde un SP no vas a poder acceder al OLD y NEW de los campos, eso sólo está disponible en los triggers

Nos leemos

  • 0

#7 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1092 posts
  • LocationMurcia, España

Posted 25 November 2011 - 04:05 AM

Buenas,

Si no voy equivocado, desde un SP no vas a poder acceder al OLD y NEW de los campos, eso sólo está disponible en los triggers

Nos leemos


Cierto, old. y new. solo tiene sentido en un trigger de modificacion de la tabla, y si desde ese trigger llamas a un procedure generico, este no vera mas que uno de los dos valores.

Hacer esto desde triggers y en plan generico lo veo muy complicado sino imposible.

En nuestras aplicaciones hacemos esto mismo, anotando en una tabla el usurio, fecha y hora, tabla y cambos modificados con el antes y el despues, todo en modo texto, pero no utilizamos nada de la base de datos, lo hacemos desde delphi.

Nuestro caso es que tenemos un TFichaBase del que heredan todas las fichas de edicion de fichas, asi que en esa unit es donde hacmeos todo el tabajo de auditoria, en el evento BeforePost, asi una vez programado, la "feature" se activa en todas nuestras fichas de forma automatica.

En el AfterEdit almacenamos los valores iniciales de todos los campos en una lista, y en el afterpost, los repasamos de nuevo y anotamos los cambios, al estilo "Direccion pasa de valer "C/ Primera" a "Calle Segunda", simple y efectivo.
  • 0

#8 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1484 posts
  • LocationMallorca

Posted 25 November 2011 - 04:20 AM

Hola.

Como dicen Sergio y Xavi, no vas a poder acceder a los campos OLD y NEW, ni desde un SP ni desde un EXECUTE STATEMENT donde construyas sentencias sobre la marcha.

Pero no creo que te deba ser necesario. ¿ Para que quieres guardar los valores OLD ?, puedes guardar solamente los valores NEW, es decir, los valores actuales de la tabla.

Si más adelante necesitas consultar una operación, y saber los valores antiguos de los campos en ese momento, además de los nuevos, solo tienes que localizar la operación inmediatamente anterior sobre el mismo registro, y los valores que tuvo en ese momento son los valores OLD para la operación actual.

Saludos.


  • 0

#9 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1092 posts
  • LocationMurcia, España

Posted 25 November 2011 - 05:31 AM

Hola.

Como dicen Sergio y Xavi, no vas a poder acceder a los campos OLD y NEW, ni desde un SP ni desde un EXECUTE STATEMENT donde construyas sentencias sobre la marcha.

Pero no creo que te deba ser necesario. ¿ Para que quieres guardar los valores OLD ?, puedes guardar solamente los valores NEW, es decir, los valores actuales de la tabla.

Si más adelante necesitas consultar una operación, y saber los valores antiguos de los campos en ese momento, además de los nuevos, solo tienes que localizar la operación inmediatamente anterior sobre el mismo registro, y los valores que tuvo en ese momento son los valores OLD para la operación actual.

Saludos.


Hola Marc, el problema de no "ver" los old es que has de grabar los cambios en todos los campos, y eso puede ser mucho texto para buscar, aparte, mirando solo un aviso no puedes saber lo que se ha modificado, y aun mirando el anterior y comparando, cosa dificil de automatizar, si te borraron ese último registro verás el pre-anterior y le echas la culpa de cambios que hizo otro.

El uso de una "fichabase" y herencia visual lo hace muy sencillo, solo recorres los TFileds y te guardas los valores .AsString, al slair comparas y listo, guardas solo los cambiados incluyendo el valor anterior. Peor sin usar herencia visual desde el inicio de tu proyecto, lo veo muy compicado, la verdad.

Otra opcion es un "generador de triggers" automatico: Te repasas las tablas, en cada una le añades un trigger de modificaciones, y el texto lo pone tu generador, comparando uno a uno todos los fields que tenga esa tabla. Es un poco lio, y cada vez que modifques la estructuras has de recrear los triggers, pero es una opcion.

Para nosotros es inviable porque no tenemos acceso a las bases de datos, y de hacerse, deberia "automatizarse" en la aplicacion para que regenere tras actualizar la base de datos.. asi seria posible, pero vuelves a tener otro problema: El usuario de tu aplicacion no lo sabe el trigger, solo el de la base de datos, y aqui usamos SYSDBA siempre... asi que no es una buena opcion en nuestro caso.

Otra ventaja de nuestro sistema: Podemos indicar que en tal tabla, para poder guardar cambios, este usuario tiene que escribir un texto explicativo: En el beforepost, si vemos cambios, abrimos la ventana  y reguntamos por el motivo del cambio (si cancelan o no escriben nada, no guardamos sus cambios) y ese texto tambien lo almacenamos

Es MUY flexible y queda muy sencillito de mantener, bueno, casi que no tiene ningún mantenimiento.

  • 0

#10 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2137 posts

Posted 25 November 2011 - 06:29 AM

Yo utilizo esta función para averiguar que campos han sido modificados:



delphi
  1. uses
  2. Variants
  3. //...
  4. function Modificado(D: TDataSet; const FieldList: string): Boolean;
  5. var
  6.   k: Integer;
  7. begin
  8.   k := 1;
  9.   while k < Length(FieldList) do
  10.     if not VarIsEmpty(D.FieldByName(ExtractFieldName(FieldList, k)).NewValue) then
  11.     begin
  12.       Result := True;
  13.       Exit;
  14.     end;
  15.   Result := False;
  16. end;



Sirve para averiguar si uno, varios o todos los campos han sido modificados, basta separar con "puntoycoma"
el nombre de los campos en el segundo parámetro:



delphi
  1. if Modificado (TuDataset, 'CampoQueQuieresEvaluar') then
  2. //hacer algo
  3.  
  4. //o también así
  5.  
  6. if Modificado (TuDataset, 'Campo1;Campo2;CampoN') then
  7. //hacer algo



Para el caso de la auditoría es muy fácil usarla, en mi caso  con bdExpress lo hago en el evento
OnAfterUpdateRecord del TDatasetProvider, trataré de adaptarla en este momento para cualquier dataset.



delphi
  1. function Cambios(Dataset: TDataset): string;
  2. var
  3.   h: integer;
  4. begin
  5.   result := '';
  6.   for h := 0 to Dataset.FieldCount - 1 do
  7.     if Modificado(Dataset, Dataset.Fields[h].FieldName) then
  8.       result := result + 'Modificó ' + Dataset.Fields[h].DisplayLabel + ': ' +
  9.         VarToStr(Dataset.Fields[h].OldValue) +
  10.         ' por ' VarToStr(Dataset.Fields[h].NewValue);
  11. end;



Con la anterior función (que podrías usarla en el evento OnAfterPost del dataset
obtienes una cadena con los cambios de los campos modificados, y ya  podrías usarla como parámetro
para agregarla a tu tabla de auditorías, en mi caso en la tabla de auditrias guardo la clave principal del registro en cuestión, el
nombre de la tabla, la fecha y hora, los cambios y el usuario.

Espero les sirva de guía.

Saludos

PD: La función Cambios se puede optimizar para borrados, agregar saltos de línea y lo que se les ocurra.
  • 0

#11 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1484 posts
  • LocationMallorca

Posted 25 November 2011 - 06:31 AM

Hola Sergio.

En realidad tu sistema me parece muy adecuado (a veces he pensado en añadir algo parecido a mis formularios base, ahora registro con triggers la actividad en las tablas pero no registro sus campos modificados), utilizar herencia visual tiene muchas ventajas. NOTA: creo que nuestras aplicaciones se deben parecer mucho :).

Hacer la auditoría en la misma base de datos, a nivel de trigger tiene la ventaja de que es más exhaustivo, y también registra los cambios en tablas relacionadas, cambios propagados desde triggers y procedimientos almacenados, etc. ...

Pero llevas razón en que programar la auditoría en la ficha base de la herencia visual, tiene muchas ventajas, como dices, es tan flexible como necesites y no te ocasiona ningún mantenimiento. NOTA: Por cierto, ¿ tu auditoría automatizada en la herencia visual solo registra los datos de la tabla principal asociada al formulario, o también reconoce las relaciones maestro-detalle y es capaz de auditar las tablas relacionadas ?. En muchas ocasiones (ventas, albaranes, facturas, ...) resultará imprescindible que se auditen también las tablas relacionadas.

Pero comentemos tus observaciones sobre la auditoría con triggers :

a) Problemas guardando solo los valores NEW :

1) Dices que viendo solo los campos NEW, hay que grabar todos los campos. Creo que no es necesario, el trigger de auditoría puede consultar el último valor que tiene registrado de un campo (con los índices adecuados, eso es bastante rápido), compararlo con su valor actual (es decir, NEW), y decidir si ha cambiado y por tanto es necesario volver a registrarlo.

2) Dices que es un problema que haya que consultar varios avisos para saber las modificaciones. Personalmente no me parece un problema, no le veo diferencia a una consulta que devuelve un registro o bien una consulta que devuelve la unión de varios registros (esta unión no es difícil de automatizar). Aunque sí que llevas razón en que si te eliminan un registro de la auditoría, entonces te harás una idea equivocada de lo ocurrido y puedes culpar de un problema a un inocente. Pero es que realmente no se deberían poder modificar/eliminar registros de la auditoría, y si desaparecen registros de la auditoría siempre vas a tener problemas para determinar lo ocurrido, esté toda la información de un evento en un único registro, o en una unión de registros.

b) Comentas la opción del generador automático de Triggers :

Esta opción es muy interesante, puesto que une flexibilidad y sencillez de mantenimiento. Lo puedes implementar en forma de un único procedimiento almacenado (que ejecute una serie de EXECUTE STATEMENTS construidos sobre la marcha), de forma que cada vez que hagas cambios en la base de datos, no tengas más que llamar a ese procedimiento almacenado para regenerar todos los triggers de auditoría.

Paso 1 : Mediante las tablas de sistema recorremos la lista de todos los triggers existentes, y todos los que empiecen por AUDIT_xxxxxxx los eliminamos mediante un DROP TRIGGER lanzado por un EXECUTE STATEMENT dentro del SP.

Paso 2: Recorremos la lista de las tablas a auditar (mediante las tablas de sistema que nos indicarán todas las tablas en la base e datos, o mediante una tabla propia donde indicamos las tablas a auditar). Para cada una de ellas generamos los CREATE TRIGGER AUDIT_xxxxxx que una vez ejecutados por el EXECUTE STATEMENT, te crean el trigger de auditoría correspondiente.

Paso 3 : El cuerpo del trigger a crear lo tenemos que construir recorriendo las tablas de sistema, para identificar todos los campos que tiene actualmente la tabla para la que hacemos el trigger. Para cada campo en la base de datos, añadimos la correspondiente línea del cuerpo del trigger : IF NEW.CAMPO <> OLD.CAMPO THEN xxxx

Dices que para vosotros es inviable porqué no tenéis acceso a la base de datos. Este es también mi caso, pero para mi no me parece que me representaría ningún problema. Simplemente en los scripts que distribuyo de actualización de base de datos, tendría que añadir al final de cada uno, la llamada al SP de regeneración de triggers de auditoría. O bien, en lugar de añadirlo a cada script, podría forzar una única llamada a ese SP al final del proceso de actualización de la base de datos, sin necesidad de añadirlo a los scripts (tengo una aplicación de actualización que verifica la versión de la base de datos, determina los scripts de actualización que hay que pasarle y los ejecuta, no me costaría nada añadir al final la llamada a la regeneración de la auditoría).

Saludos.
  • 0

#12 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1484 posts
  • LocationMallorca

Posted 25 November 2011 - 06:52 AM

Por cierto, Sergio, comentas que el Trigger no sabe el usuario de la aplicación (ya que todos se conectan mediante SYSDBA) y por tanto no puede registrar quienes hacen los cambios.

Yo también utilizo solo el usuario SYSDBA, pero esto no representa ningún problema. Puesto que también registro las conexiones de usuarios al sistema (usuario de la aplicación, hora de conexión, ip de conexión y nº de sesión). Consultando esta información, los triggers de auditoría no tienen ningún problema en identificar el usuario de la aplicación involucrado en la modificación.

Saludos.
  • 0

#13 HSEGURAC1976

HSEGURAC1976

    Newbie

  • Miembros
  • Pip
  • 2 posts

Posted 25 November 2011 - 08:23 PM

hola a todos y muchas gracias, la verdad es que lo que pretendia era en una tabla de auditoria poder guardar el usuario, fecha, registro , campo, tabla, valor nuevoy el valor que estaba antes de actualizar los datos por ahora lo que hice fue hacer un trigger en cada tabla y validar campo por campo debido a la prioridad de la entrega, no se si fue lo mas optimo pero esto fue lo que hice

SET TERM ^ ;
create trigger trg_CLIENTES_AU for CLIENTES AFTER UPDATE
AS
begin
        IF (new.cli_salario <> old.cli_salario) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA,    AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_SALARIO', CAST(OLD.cli_salario AS VARCHAR(500)),CAST( NEW.cli_salario AS VARCHAR(500)) );
        END
        IF (new.CAR_CODIGO <> old.CAR_CODIGO) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CAR_CODIGO', CAST(OLD.CAR_CODIGO AS VARCHAR(500)),CAST( NEW.CAR_CODIGO AS VARCHAR(500)) );
        END
        IF (new.COS_CODIGO <> old.COS_CODIGO) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','COS_CODIGO', CAST(OLD.COS_CODIGO AS VARCHAR(500)),CAST( NEW.COS_CODIGO AS VARCHAR(500)) );
        END
        IF (new.PRO_CODIGO <> old.PRO_CODIGO) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','PRO_CODIGO', CAST(OLD.PRO_CODIGO AS VARCHAR(500)),CAST( NEW.PRO_CODIGO AS VARCHAR(500)) );
        END
        IF (new.CTR_CODIGO <> old.CTR_CODIGO) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CTR_CODIGO', CAST(OLD.CTR_CODIGO AS VARCHAR(500)),CAST( NEW.CTR_CODIGO AS VARCHAR(500)) );
        END
        IF (new.SUC_CODIGO <> old.SUC_CODIGO) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','SUC_CODIGO', CAST(OLD.SUC_CODIGO AS VARCHAR(500)),CAST( NEW.SUC_CODIGO AS VARCHAR(500)) );
        END
        IF (new.EMP_CODIGO <> old.EMP_CODIGO) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','EMP_CODIGO', CAST(OLD.EMP_CODIGO AS VARCHAR(500)),CAST( NEW.EMP_CODIGO AS VARCHAR(500)) );
        END
        IF (new.CLI_CODNOM <> old.CLI_CODNOM) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_CODNOM', CAST(OLD.CLI_CODNOM AS VARCHAR(500)),CAST( NEW.CLI_CODNOM AS VARCHAR(500)) );
        END
        IF (new.CLI_FCHAFILIACION <> old.CLI_FCHAFILIACION) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_FCHAFILIACION', CAST(OLD.CLI_FCHAFILIACION AS VARCHAR(500)),CAST( NEW.CLI_FCHAFILIACION AS VARCHAR(500)) );
        END
        IF (new.CLI_ESTADO <> old.CLI_ESTADO) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_ESTADO', CAST(OLD.CLI_ESTADO AS VARCHAR(500)),CAST( NEW.CLI_ESTADO AS VARCHAR(500)) );
        END
        IF (new.CLI_FCHRETIRO <> old.CLI_FCHRETIRO) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_FCHRETIRO', CAST(OLD.CLI_FCHRETIRO AS VARCHAR(500)),CAST( NEW.CLI_FCHRETIRO AS VARCHAR(500)) );
        END
        IF (new.CLI_FCHINGRESOCIA <> old.CLI_FCHINGRESOCIA) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_FCHINGRESOCIA', CAST(OLD.CLI_FCHINGRESOCIA AS VARCHAR(500)),CAST( NEW.CLI_FCHINGRESOCIA AS VARCHAR(500)) );
        END
        IF (new.CLI_SOCIO_S_N <> old.CLI_SOCIO_S_N) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_SOCIO_S_N', CAST(OLD.CLI_SOCIO_S_N AS VARCHAR(500)),CAST( NEW.CLI_SOCIO_S_N AS VARCHAR(500)) );
        END
        IF (new.CLI_MENSAJE <> old.CLI_MENSAJE) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_MENSAJE', CAST(OLD.CLI_MENSAJE AS VARCHAR(500)),CAST( NEW.CLI_MENSAJE AS VARCHAR(500)) );
        END
        IF (new.DIV_CODIGO <> old.DIV_CODIGO) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','DIV_CODIGO', CAST(OLD.DIV_CODIGO AS VARCHAR(500)),CAST( NEW.DIV_CODIGO AS VARCHAR(500)) );
        END
        IF (new.CLI_FCHINIVAC <> old.CLI_FCHINIVAC) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_FCHINIVAC', CAST(OLD.CLI_FCHINIVAC AS VARCHAR(500)),CAST( NEW.CLI_FCHINIVAC AS VARCHAR(500)) );
        END
        IF (new.NIVESCO_CODIGO <> old.NIVESCO_CODIGO) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','NIVESCO_CODIGO', CAST(OLD.NIVESCO_CODIGO AS VARCHAR(500)),CAST( NEW.NIVESCO_CODIGO AS VARCHAR(500)) );
        END
        IF (new.CLI_ESTRATO <> old.CLI_ESTRATO) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_ESTRATO', CAST(OLD.CLI_ESTRATO AS VARCHAR(500)),CAST( NEW.CLI_ESTRATO AS VARCHAR(500)) );
        END
        IF (new.CLI_CABFAM <> old.CLI_CABFAM) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_CABFAM', CAST(OLD.CLI_CABFAM AS VARCHAR(500)),CAST( NEW.CLI_CABFAM AS VARCHAR(500)) );
        END
        IF (new.CLI_MUJCABFAM <> old.CLI_MUJCABFAM) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_MUJCABFAM', CAST(OLD.CLI_MUJCABFAM AS VARCHAR(500)),CAST( NEW.CLI_MUJCABFAM AS VARCHAR(500)) );
        END
        IF (new.CLI_JORNLAB <> old.CLI_JORNLAB) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_JORNLAB', CAST(OLD.CLI_JORNLAB AS VARCHAR(500)),CAST( NEW.CLI_JORNLAB AS VARCHAR(500)) );
        END
        IF (new.OCU_CODIGO <> old.OCU_CODIGO) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','OCU_CODIGO', CAST(OLD.OCU_CODIGO AS VARCHAR(500)),CAST( NEW.OCU_CODIGO AS VARCHAR(500)) );
        END
        IF (new.CLI_CENTRI <> old.CLI_CENTRI) THEN
        BEGIN
            INSERT INTO AUDITORIA (AUDIT_CCN, AUDIT_FECHA, AUDIT_USUARIO, TER_CCN, AUDIT_TABLA, AUDIT_CAMPO, AUDIT_VALORVIEJO,AUDIT_VALORNUEVO)
            VALUES (GEN_ID(AUDITORIA_GEN,1), NEW.CLI_FCHACTUALIZACION, NEW.CLI_USUACTUAL, OLD.TER_CCN ,'CLIENTES','CLI_CENTRI', CAST(OLD.CLI_CENTRI AS VARCHAR(500)),CAST( NEW.CLI_CENTRI AS VARCHAR(500)) );
        END


end
^

  • 0

#14 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1092 posts
  • LocationMurcia, España

Posted 28 November 2011 - 04:24 PM

Dices que para vosotros es inviable porqué no tenéis acceso a la base de datos. Este es también mi caso, pero para mi no me parece que me representaría ningún problema. Simplemente en los scripts que distribuyo de actualización de base de datos, tendría que añadir al final de cada uno, la llamada al SP de regeneración de triggers de auditoría. O bien, en lugar de añadirlo a cada script, podría forzar una única llamada a ese SP al final del proceso de actualización de la base de datos, sin necesidad de añadirlo a los scripts (tengo una aplicación de actualización que verifica la versión de la base de datos, determina los scripts de actualización que hay que pasarle y los ejecuta, no me costaría nada añadir al final la llamada a la regeneración de la auditoría).


Marc, nuestras aplicaciones parecen que comparten diseño y forma de pensar sobre todo!

El sistema de actualizar la base de datos es identica a la nuestra, nosotros distribuimos ficheros Actualiza123.sql que incluyen el numero de version que actualizan, el 123 la actualiza dejandola en la V1.24. Tenemos la precaucion de encriptarlos por seguridad, que un manual de sql es facil de encontrar hoy dia.

En nuestras fichas complejas tipo factura con lineas de factura, estas lineas se abren en subfichas, con su propio mecanismo heredado de auditoria. Las dos comparten transaccion, esto es importante: Por ejemplo, entras a una factura, cambias la fecha, entras a cambiar una subficha -un precio de un articulo- y guardas la subficha. En este ejemplo, el primer grabado genera su log del cambio de precio indicando la factura a la que pertenece, ya que se lo tenemos marcado en la ficha hija que es un dato identificativo del record cambiado.

Si ahora guardas los cambios en la factura, se generan al final 2 entradas, la segunda seria la de la fecha de factura, pero si cancelas la grabacion de la factura, al ser la misma transaccion, ni se graba el cambio de precio, ni su log, ni el cambio de fecha, ni su log. Va todo "empaquetado" como dos cambios puntuales y diferentes, que lo son, pero o se graban los dos o ninguno.

Esto permite registrar el caso en que cambies 20 lineas de factura y la fecha con la misma simpleza que grabar solo los cambios de una ficha, y permite tener permisos diferentes para las dos operaciones: igual puedes modificar fechas pero no precios.
  • 0




IP.Board spam blocked by CleanTalk.