Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Identificar origen de un trigger

734 views
Skip to first unread message

Jorge V

unread,
May 9, 2002, 7:34:24 AM5/9/02
to
Hola.

Estoy haciendo un log las operaciones que se realizan en una tabla mediante
triggers, y tengo dos dudas:
¿ se puede saber el texto de la sentencia Sql que ha provocado el disparo
del trigger.?
Si creo un único trigger genérico 'for insert,update,delete', ¿puedo saber
qué tipo de evento lo ha disparado (insert o update o delete)?

Un saludo
Jorge


Carlos Sacristán

unread,
May 9, 2002, 8:02:52 AM5/9/02
to
Pues la verdad es que son dos preguntas que nunca me había planteado
porque no le veo excesivas ventajas, pero bueno, vamos a ver:

La sentencia SQL que ha lanzado el trigger no creo que puedas saberla, o
al menos yo no conozco una función que te lo facilite, aunque por otro lado,
¿qué es lo que necesitas exactamente? o, mejor dicho, ¿para qué lo
necesitas?

En cuanto a la otra pregunta, seguramente exista un método más sencillo,
pero podrías saberlo por las tablas virtuales que existen según el trigger
lanzado, aunque tampoco podría ser fiable. Sacado de los BOL:

*************************************************
La tabla deleted almacena copias de las filas afectadas por las
instrucciones DELETE y UPDATE. Durante la ejecución de una instrucción
DELETE o UPDATE, las filas se eliminan de la tabla del desencadenador y se
transfieren a la tabla deleted. La tabla deleted y la tabla del
desencadenador no suelen tener filas en común.

La tabla inserted almacena copias de las filas afectadas por las
instrucciones INSERT y UPDATE. Durante una transacción INSERT o UPDATE, se
agregan nuevas filas a la tabla inserted y a la tabla del desencadenador.
Las filas de la tabla inserted son copias de las nuevas filas de la tabla
del desencadenador.

Una transacción UPDATE es como una eliminación seguida de una inserción:
primero, se copian las filas antiguas en la tabla deleted y, a continuación,
se copian las filas nuevas en la tabla del desencadenador y en la tabla
inserted.

Cuando establezca condiciones para el desencadenador, utilice las tablas
inserted y deleted según la acción que activara el desencadenador. Aunque no
se produce ningún error si se hace referencia a deleted cuando se comprueba
INSERT, o a inserted cuando se comprueba DELETE, estas tablas de prueba del
desencadenador no contendrán filas en estos casos.

*************************************************

En cualquier caso, creo que lo mejor es que crees tres trigger por
separado, puesto que el mantenimiento será más sencillo. Al menos es como lo
haría yo.

Un saludo
--
--
----------------------------------------------
"Sólo una cosa vuelve un sueño imposible: el miedo a fracasar (P.Coelho)"

"Jorge V" <jorg...@jazzfree.com> escribió en el mensaje
news:#suur009BHA.1692@tkmsftngp05...

Jorge V

unread,
May 9, 2002, 10:23:23 AM5/9/02
to
Hola.

La idea es tener un método genérico para llevar registro de todas las
operaciones que se realizan en las tablas de una bd, tanto por motivos de
log como complemento de las copias de seguridad.
La tabla de log es:
CREATE TABLE [dbo].[TLOG] (
[ID_LOG] [int] IDENTITY (1, 1) NOT NULL ,
[FECHA] [datetime] NOT NULL ,
[TIPO] [nvarchar] (50) COLLATE Modern_Spanish_CI_AS NOT NULL ,
[TABLA] [nvarchar] (50) COLLATE Modern_Spanish_CI_AS NOT NULL ,
[VALORES] [nvarchar] (1000) COLLATE Modern_Spanish_CI_AS NULL
) ON [PRIMARY]
GO
En el campo Valores guardo los campos como texto con separadores, y el Tipo
guardo Insert,update o Delete.

Mas o menos ya funciona. Conseguí resolver lo del evento así:

DECLARE @bINSERT [smallint]
DECLARE @bUPDATE [smallint]
DECLARE @bDELETE [smallint]
DECLARE @TEMPTABLA [nvarchar](15)
DECLARE @ACCION [nvarchar](15)

SELECT @ACCION=''

IF (ISNULL((SELECT COUNT(*) FROM INSERTED),0)>0)
BEGIN
SELECT @bINSERT=1
SELECT @TEMPTABLA='INSERTED'
SELECT @ACCION='INSERT'
END
IF (ISNULL((SELECT COUNT(*) FROM DELETED),0)>0)
BEGIN
SELECT @bDELETE=1
SELECT @TEMPTABLA='DELETED'
SELECT @ACCION='DELETE'
END
IF (@bINSERT=1 AND @bDELETE=1)
BEGIN
SELECT @bUPDATE=1
SELECT @TEMPTABLA='INSERTED'
SELECT @ACCION='UPDATE'
END

No creo que sea la mejor forma, pero por lo menos funciona.
Ya sé que debería separar el código para cada caso, pero ya que el
procedimiento es muy similar para los tres casos e intenta ser un método
genérico,
intento hacerlo en un solo trigger.

La duda que tengo ahora es qué pasa cuando alguien hace algo como DELETE
FROM MITABLA. ¿Tengo que recorrer la tabla Deleted? ¿Como?

Gracia por leer todo este rollo

Un Saludo
Jorge

"Carlos Sacristán" <csacristanARROBAocasoPUNTOes> escribió en el mensaje
news:OmbkyE19BHA.1368@tkmsftngp04...

Isaías

unread,
May 9, 2002, 3:13:35 PM5/9/02
to
Mi comentario muy personal (tal vez no les guste a muchos
en este foro).

La solución a tu "problema" es muy sencilla:

NO DEJES QUE NADIE manipule los datos de tus bases,
SIEMPRE (y digo, siempre que se pueda) realiza desarrollos
de 3 capas (Cliente-Transaccion-Base de Datos).

Siempre que se desee hacer una Transaccion en tus bases
(INSERT, DELETE, UPDATE), que sea mediante la ejecución de
Store Procedures, esto hara que tengas siempre el CONTROL
EN TUS MANOS.

Saludos.

>-----Mensaje original-----

>> se copian las filas nuevas en la tabla del desÍ
{ wÀ È ìV^ Ì0 Ì3>
> ìk encadenador y en la tabla

jloria(MVP)

unread,
May 9, 2002, 4:03:28 PM5/9/02
to
Hola Jorge:
Abajo te estoy escribiendo un codigo que hace casi lo que estas pidiendo,
pero me parece que debe tener una leyenda de CUIDADO TRIGGER PELIGROSO por
el impacto que tiene en el desempeno de la base de datos. Si estas claro y
tienes el hardware necesario ahi va:
/* Inicio de Codigo */
/* Tabla que va a monitorear */
CREATE TABLE [TABLA] (
[ID] [int] IDENTITY (1, 1) NOT NULL ,
[Nombre] [varchar] (20) NOT NULL
) ON [PRIMARY]
GO

/* Tabla Bitacora de Comandos */
CREATE TABLE [Bitacora] (
[BitacoraID] [int] IDENTITY (1, 1) NOT NULL ,
[EventType] [char] (14) NOT NULL ,
[Status] [int] NOT NULL ,
[EventInfo] [varchar] (1000) NOT NULL ,
[Usuario] [varchar] (20) NULL ,
[Fecha] [smalldatetime] NULL
) ON [PRIMARY]
GO


/* Trigger de Monitoreo */
CREATE TRIGGER trig_tablabitacora
ON TABLA
FOR DELETE, INSERT, UPDATE
AS
BEGIN
DECLARE @NUMERO INT

INSERT INTO Bitacora (EventType,Status,EventInfo)
EXEC ('DBCC INPUTBUFFER(' + @@SPID +')')

SET @NUMERO=@@IDENTITY
UPDATE BITACORA
SET Usuario=SYSTEM_USER,
Fecha=GETDATE()
WHERE BITACORAID=@NUMERO
END
GO
/* INSERTE REGISTROS */
/* BORRE REGISTRO QUE NO EXISTE */
DELETE TABLA
WHERE ID=4
GO
/* INSERTE UN REGISTRO */
INSERT TABLA
VALUES ('Registro 1')
GO
/* INSERTE 2 REGISTROS */
INSERT TABLA
VALUES ('Registro 2')
INSERT TABLA
VALUES ('Registro 3')
GO
/* BORRE 1 REGISTRO */
DELETE TABLA
WHERE ID=2
GO
SELECT * FROM BITACORA
GO
/* FIN DE CODIGO */

Espero que te sirva,

Javier Loria
Costa Rica (MVP)


"Jorge V" <jorg...@jazzfree.com> wrote in message
news:#QjnET29BHA.1700@tkmsftngp07...

Miguel Egea

unread,
May 10, 2002, 3:17:42 AM5/10/02
to
Miuy Bueno!!!


--
Un Saludo
Miguel Egea
http://www22.brinkster.com/miguele
"jloria(MVP)" <jloria@newhorizons> escribió en el mensaje
news:#U8sTS59BHA.2596@tkmsftngp05...

Carlos Sacristán

unread,
May 10, 2002, 5:33:23 AM5/10/02
to
La verdad es que sí, pero podría estar todavía mejor si declaramos la
tabla bitacora así:

***************

CREATE TABLE [dbo].[Bitacora] (


[BitacoraID] [int] IDENTITY (1, 1) NOT NULL ,
[EventType] [char] (14) NOT NULL ,
[Status] [int] NOT NULL ,
[EventInfo] [varchar] (1000) NOT NULL ,

[Usuario] [varchar] (20) NOT NULL ,
[Fecha] [smalldatetime] NOT NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Bitacora] WITH NOCHECK ADD
CONSTRAINT [DF_Bitacora_Usuario] DEFAULT (suser_sname()) FOR [Usuario],
CONSTRAINT [DF_Bitacora_Fecha] DEFAULT (getdate()) FOR [Fecha]

******************

Y, por otro lado, el trigger en la tabla lo refiniría de la siguiente
manera:

******************


/* Trigger de Monitoreo */
CREATE TRIGGER trig_tablabitacora
ON TABLA
FOR DELETE, INSERT, UPDATE
AS
BEGIN
DECLARE @NUMERO INT

INSERT INTO Bitacora (EventType,Status,EventInfo)
exec sp_executesql N'DBCC INPUTBUFFER( @i )', N'@i int',
@i=@@spid

END
******************

De este modo nos evitamos una instrucción UPDATE... aunque ahora que lo
pienso, la tabla Bitácora bien recibiría un índice sobre las columnas
usuario y fecha, ¿verdad?.

En fin, a ver qué pensáis. Un saludo

--
--
----------------------------------------------
"Sólo una cosa vuelve un sueño imposible: el miedo a fracasar (P.Coelho)"

"Miguel Egea" <migue...@sinergiatec.com> escribió en el mensaje
news:#aLZHL$9BHA.1696@tkmsftngp05...

Miguel Egea

unread,
May 10, 2002, 5:35:36 AM5/10/02
to
Ciertamente Mejor!!! Sois unos monstruos :-)

"Carlos Sacristán" <csacristanARROBAocasoPUNTOes> escribió en el mensaje

news:u8UI8VA#BHA.2040@tkmsftngp05...

jloria(MVP)

unread,
May 10, 2002, 11:54:55 AM5/10/02
to
Sin duda alguna mucho mejor.

Gracias,

Javier Loria
Costa Rica MVP
"Carlos Sacristán" <csacristanARROBAocasoPUNTOes> wrote in message
news:u8UI8VA#BHA.2040@tkmsftngp05...

Miguel Egea

unread,
May 10, 2002, 12:29:50 PM5/10/02
to
Javier si no te importa, me gustaría publicar esto en mi web.
Espero tu respuesta
Gracias de antemano.


--
Un saludo
Miguel Egea
http://www22.brinkster.com/miguele
"jloria(MVP)" <jloria@newhorizons> wrote in message
news:uKfOFsD#BHA.2164@tkmsftngp04...

jloria(MVP)

unread,
May 10, 2002, 1:56:43 PM5/10/02
to
Hola Miguel:
Me siento honrado, por favor publicalo.
Gracias,

Javier Loria
Costa Rica (MVP)

"Miguel Egea" <mcgi...@airtel.net> wrote in message
news:#wTdX$D#BHA.1696@tkmsftngp05...

Miguel Egea

unread,
May 10, 2002, 2:37:48 PM5/10/02
to
Inmediatamente. Gracias :-)


--
Un saludo
Miguel Egea
http://www22.brinkster.com/miguele
"jloria(MVP)" <jloria@newhorizons> wrote in message

news:O5r5IwE#BHA.1924@tkmsftngp02...

Jorge V

unread,
May 13, 2002, 9:49:07 AM5/13/02
to
Muchas gracias a todos, me habeis aclarado muchas cosas

Un Saludo
Jorge

"Miguel Egea" <mcgi...@airtel.net> escribió en el mensaje
news:OfEs3GF#BHA.772@tkmsftngp05...

> > > > las

0 new messages