Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Como saber si la tabla cambio al editarla? (https://www.clubdelphi.com/foros/showthread.php?t=70801)

El_Raso 11-11-2010 17:33:15

Como saber si la tabla cambio al editarla?
 
Que tal a todos...

Tengo una tabla que tiene unos 100 campos de una encuesta, y quiero saber si al editar la tabla algunos de ellos sufrio algun cambio para mandar a grabar el usuario que realizo dicho cambio.

Se que uno a uno con un triguer se podria usando el OLD y NEW, pero quiero saber si existe algun truco de la tabla completa para no tirar tantos codigos.

O si con los componentes que uso lo puedo conseguir.

Uso Delphi 2010 con FIBPlus 6.9.9 y Firebird 2.5.

Un saludo desde el caribe...

Gallosuarez 12-11-2010 01:09:38

Sugerencia...
 
El_Raso:

Mira, en mi caso hice una pequeña consulta que me genera el código que después inserto en mi procedimiento almacenado. Básicamente lo que hace esta consulta es utilizar las tablas del sistema para obtener TODOS los campos de la tabla especificada en la clausula WHERE y generar el código que se necesita para cada campo involucrado en dicha tabla.
Código SQL [-]
SELECT 'IF (NEW.' || TRIM(RDB$FIELD_NAME) || ' IS DISTINCT FROM OLD.' ||
  TRIM(RDB$FIELD_NAME) || ') THEN REG_CHANGES;'
FROM RDB$RELATION_FIELDS
WHERE RDB$RELATION_NAME = 'NOMBRE_TABLA'

Adecua la a tus necesidades, ignoro si existe algún otro truco que nos facilite este trabajo.

Saludos
Gerardo Suárez Trejo

P.D. Estaremos atentos a ver si alguien mas ha hecho algo al respecto.

Al González 12-11-2010 06:44:38

Hola El_Raso.

Si utilizas componentes TClientDataSet con dbExpress tendrás la ventaja de que al servidor no llegará ninguna sentencia SQL Update "inútil", es decir, solamente que el registro haya sufrido alguna modificación real se enviarán al servidor los cambios.

Eso te facilitaría mucho las cosas del lado del servidor, porque en la base de datos podrás usar un sencillo disparador (trigger) Before / After Update con la seguridad de que el registro realmente cambió.

En tu caso implicaría que cambies los componentes de acceso a datos que utilizas (además de asegurar un buen controlador DBX para Firebird 2.5 si tu edición de Delphi 2010 no es la Enterprise). Así que es algo que deberás considerar, junto con el tamaño de tu aplicación y el tiempo que dispongas para hacer el cambio de componentes. :)

Como dato interesante, decir que TClientDataSet maneja de una manera eficiente el registro de cambios. El usuario puede modificar un registro en memoria y su propiedad ChangeCount aumentará en 1, y si luego lo modifica nuevamente para dejarlo como estaba al principio, ChangeCount disminuirá en 1, aunque antes de hacer este segundo cambio se haya movido de registro o hecho más cambios en otros.

Saludos.

Al González. :)

roman 12-11-2010 16:44:52

Cita:

Empezado por El_Raso (Mensaje 382076)
quiero saber si al editar la tabla algunos de ellos sufrio algun cambio para mandar a grabar el usuario que realizo dicho cambio.

No trabajo con Firebird, pero en MySQL, luego de una sentencia update, insert o delete, es posible saber cuántos registros fueron realmente afectados. Es decir, si un UPDATE abarca 100 registros pero sólo dos de ellos realmente cambiaron, el motor indica que cambiaron dos registros.

Entonces, si lo único que interesa es saber si realmente hubo un cambio y así poder acreditarlo al usuario, podrías ver si Firebird cuenta con algo similar y así te evitas triggers y demás.

// Saludos

ecfisa 12-11-2010 17:16:08

Hola El_Raso.

Cuando leí tu post, interpreté que deseabas averiguar solamente si un campo determinado de un registro había sido modificado. Y como no conozco nada al respecto, mejor hice silencio.

Ahora si como dice roman, te alcanza con saber si hubo un cambio en el/los registros, podes utilizar POST_EVENT en un trigger AFTER UPDATE y capturar el evento.

Saludos. :)

guillotmarc 12-11-2010 17:50:41

Hola.

Cita:

Empezado por Gallosuarez (Mensaje 382119)
El_Raso:

Mira, en mi caso hice una pequeña consulta que me genera el código que después inserto en mi procedimiento almacenado. Básicamente lo que hace esta consulta es utilizar las tablas del sistema para obtener TODOS los campos de la tabla especificada en la clausula WHERE y generar el código que se necesita para cada campo involucrado en dicha tabla.
Código SQL [-]SELECT 'IF (NEW.' || TRIM(RDB$FIELD_NAME) || ' IS DISTINCT FROM OLD.' || TRIM(RDB$FIELD_NAME) || ') THEN REG_CHANGES;' FROM RDB$RELATION_FIELDS WHERE RDB$RELATION_NAME = 'NOMBRE_TABLA'


Adecua la a tus necesidades, ignoro si existe algún otro truco que nos facilite este trabajo.

Saludos
Gerardo Suárez Trejo

P.D. Estaremos atentos a ver si alguien mas ha hecho algo al respecto.

¿ Esto te funciona ?.

Yo lo he intentado varias veces, pero al ejecutar ese comando con un EXECUTE STATEMENT, se hace en un contexto distinto y las variables NEW.XXX y OLD.XXX no se reconocen (incluso aunque el comando se ejecute en el mismo trigger).

¿ Puedes poner un poco más de código para ver como lo haces ?. Me interesa mucho.

Saludos.

Gallosuarez 12-11-2010 19:17:29

Explicación...
 
Guillotmarc:

Mira, como explico en mi primera participación, esa sentencia la utilizo solo para generar el código que después inserto en el procedimiento almacenado (posteriormente tengo que compilar ese procedimiento almacenado), es decir, ejecuto la sentencia en IBExpert y esta me va a devolver las sentencias ya listas de los todos los campos involucrados. Lo hago principalmente para todas aquellas tablas que tienen muchos campos y quiero evitarme la fatiga de escribir todas las sentencias por cada campo (interpreté así la pregunta de El_Raso que es lo que él precisamente quiere evitarse, ¿o estoy equivocado?).

Creo que Guillotmarc, quiere lograr lo que yo en un principió también intenté hacer (poner este código dentro del disparador y posteriormente hacer un EXECUTE STAMENT. :eek: No, no funciona de esta manera (para desgracia de todos nosotros). Pero tengo otro código donde logré grabar la sentencia (UPDATE, DELETE o INSERT), tal como se la envió la capa de datos de nuestro FRONT END, sin importar que sea DELPHI, PHP, JAVA, IBExpert, etc. El problema que me falta resolver (ignoro si se pueda hacer), es cuando en una sola transacción hay varias sentencias (solo logro grabar una de ellas). Sin embargo, déjenme rescatar ese código, y lo publico. A lo mejor hay al guíen en este foro que se le ocurra como hacerlo. ¿Les parece la idea?.

Saludos,
Gerardo Suárez Trejo

guillotmarc 12-11-2010 21:04:00

Gracias Gerardo.

Ahora lo entiendo. La verdad es que supone mucho mantenimiento, hay que estar siempre pendiente de que cada vez que modificas algún campo tendrás que regenerar el trigger.

Pero está claro que siempre es mejor utilizar esto que te da el cuerpo del trigger automáticamente, que no tener que escribirlo manualmente.

NOTA: Gracias por ofrecerte a buscar el código para recuperar la sentencia que actualizó el registro. Pero por mi no te molestes, no lo utilizaría.

Saludos.

rastafarey 19-11-2010 03:34:45

Resp
 
Si mas no recuerdo hay algo asi como rowafect o algo por el estilo. Lee un poco hacerca de esto. Ahora no recuerdo desde que version de firebird esta disponible.

Delphius 19-11-2010 04:02:45

Tengo entendido que desde Firebird 2.0 (aunque creo que también estaba disponible desde 1.5) se puede hacer uso de ROW_COUNT para saber la cantidad de registros afectados por una instrucción UPDATE.

Saludos,


La franja horaria es GMT +2. Ahora son las 09:36:00.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi