Ayuda con Trigger

22/09/2008 - 20:17 por Jorge | Informe spam
Hola
Tengo un SQL Server 2005, bajo Win Server 2003.
En la base de datos "Medicos", quiero hacer un trigger para la tabla
T_MEDICO.

Hago lo siguiente:

CREATE TRIGGER [dbo].[tr_T_MEDICO_UPD] ON [dbo].[T_MEDICO]
FOR UPDATE
AS

DECLARE @DATA_OLD VARCHAR(200) -- DATA ANTIGUA
DECLARE @DATA_NEW VARCHAR(200) -- DATA NUEVA

SELECT @DATA_OLD=C_MED_APP FROM DELETED
SELECT @DATA_NEW=C_MED_APP FROM INSERTED
IF RTRIM(@DATA_OLD)<>RTRIM(@DATA_NEW)
INSERT INTO T_LOGTR
(C_LOGTR_FECHA,C_LOGTR_USR,C_LOGTR_TIPO_COD,C_LOGTR_TABLA,C_LOGTR_LLAVE,C_LOGTR_DATA)
SELECT
GETDATE(),SYSTEM_USER,2,'MEDICOS.DBO.T_MEDICO','C_MED_APP',@DATA_OLD+'->'+@DATA_NEW

SELECT @DATA_OLD=C_MED_APM FROM DELETED
SELECT @DATA_NEW=C_MED_APM FROM INSERTED
IF RTRIM(@DATA_OLD)<>RTRIM(@DATA_NEW)
INSERT INTO T_LOGTR
(C_LOGTR_FECHA,C_LOGTR_USR,C_LOGTR_TIPO_COD,C_LOGTR_TABLA,C_LOGTR_LLAVE,C_LOGTR_DATA)
SELECT
GETDATE(),SYSTEM_USER,2,'MEDICOS.DBO.T_MEDICO','C_MED_APM',@DATA_OLD+'->'+@DATA_NEW

...
...

Con esto, una vez que a la tabla T_MEDICO, se la agrege o borre un campo,
tendré que modificar el trigger.
¿Existe o se puede hacer algo mas dinamico?

Intente algo asi:

CREATE TRIGGER [dbo].[tr_T_MEDICO_UPD] ON [dbo].[T_MEDICO]
FOR UPDATE
AS

DECLARE @SQL VARCHAR(8000) -- PARA CONSTRUIR LA CADENA
DECLARE @LLAVE VARCHAR(40) -- VALORES DE IDENTIFICACION UNICA DEL REGISTRO
DECLARE @DATA VARCHAR(2000) -- CAMBIOS EN VALORES

SET @SQL = ''
SET @LLAVE='C_MED_CMP' CAMPO LLAVE

DECLARE @COLUMN VARCHAR(50)

DECLARE CUR CURSOR OPTIMISTIC FOR
SELECT NAME FROM SYS.COLUMNS WHERE OBJECT_ID IN (SELECT OBJECT_ID FROM
SYS.TABLES WHERE NAME='T_MEDICO')
OPEN CUR
FETCH NEXT FROM CUR INTO @COLUMN
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SQL = "INSERT INTO T_LOGTR
(C_LOGTR_FECHA,C_LOGTR_USR,C_LOGTR_TIPO_COD,C_LOGTR_TABLA,C_LOGTR_LLAVE,C_LOGTR_DATA)
"
+ " SELECT
GETDATE(),SYSTEM_USER,2,'MEDICOS.DBO.T_MEDICO',CONVERT(VARCHAR(10),INSERTED."+@LLAVE+"),
"
+ "
'"+@COLUMN+":'+ISNULL(CONVERT(VARCHAR(100),DELETED."+@COLUMN+"),'')+':->'+ISNULL(CONVERT(VARCHAR(100),INSERTED."+@COLUMN+"),'')
"
+ " FROM DELETED, INSERTED "
PRINT @SQL
EXEC(@SQL)

FETCH NEXT FROM CUR INTO @COLUMN
END
CLOSE CUR
DEALLOCATE CUR

Pero me da error:

Msg 208, Level 16, State 1, Line 1
Invalid object name 'DELETED'.

Entiendo que la tabla DELETED, asi como la INSERTED no son tabla "fisicas"
por eso el error.

¿Como puedo hacer?

Saludos
JORGE G.
 

Leer las respuestas

#1 Maxi Accotto
24/09/2008 - 23:17 | Informe spam
El error es porque usted usa SQL Dinamico dentro de un Trigger y dentro de
ese SQL Dinamico llama a tablas que no existen y son virtuales.

Revise el codigo y trate de hacerlo mas eficiente, asi como esta con
cursores y de forma dinamica sera muy eneficiente haciendo que la
transaccion dure mas , generando mas loqueos y hasta problemas de deadlock


Saludos
Maxi Accotto
Microsoft MVP en SQLServer
SQltotalconsulting
-

"Jorge" escribió en el mensaje de
noticias:
Hola
Tengo un SQL Server 2005, bajo Win Server 2003.
En la base de datos "Medicos", quiero hacer un trigger para la tabla
T_MEDICO.

Hago lo siguiente:

CREATE TRIGGER [dbo].[tr_T_MEDICO_UPD] ON [dbo].[T_MEDICO]
FOR UPDATE
AS

DECLARE @DATA_OLD VARCHAR(200) -- DATA ANTIGUA
DECLARE @DATA_NEW VARCHAR(200) -- DATA NUEVA

SELECT @DATA_OLD=C_MED_APP FROM DELETED
SELECT @DATA_NEW=C_MED_APP FROM INSERTED
IF RTRIM(@DATA_OLD)<>RTRIM(@DATA_NEW)
INSERT INTO T_LOGTR
(C_LOGTR_FECHA,C_LOGTR_USR,C_LOGTR_TIPO_COD,C_LOGTR_TABLA,C_LOGTR_LLAVE,C_LOGTR_DATA)
SELECT
GETDATE(),SYSTEM_USER,2,'MEDICOS.DBO.T_MEDICO','C_MED_APP',@DATA_OLD+'->'+@DATA_NEW

SELECT @DATA_OLD=C_MED_APM FROM DELETED
SELECT @DATA_NEW=C_MED_APM FROM INSERTED
IF RTRIM(@DATA_OLD)<>RTRIM(@DATA_NEW)
INSERT INTO T_LOGTR
(C_LOGTR_FECHA,C_LOGTR_USR,C_LOGTR_TIPO_COD,C_LOGTR_TABLA,C_LOGTR_LLAVE,C_LOGTR_DATA)
SELECT
GETDATE(),SYSTEM_USER,2,'MEDICOS.DBO.T_MEDICO','C_MED_APM',@DATA_OLD+'->'+@DATA_NEW

...
...

Con esto, una vez que a la tabla T_MEDICO, se la agrege o borre un campo,
tendré que modificar el trigger.
¿Existe o se puede hacer algo mas dinamico?

Intente algo asi:

CREATE TRIGGER [dbo].[tr_T_MEDICO_UPD] ON [dbo].[T_MEDICO]
FOR UPDATE
AS

DECLARE @SQL VARCHAR(8000) -- PARA CONSTRUIR LA CADENA
DECLARE @LLAVE VARCHAR(40) -- VALORES DE IDENTIFICACION UNICA DEL
REGISTRO
DECLARE @DATA VARCHAR(2000) -- CAMBIOS EN VALORES

SET @SQL = ''
SET @LLAVE='C_MED_CMP' CAMPO LLAVE

DECLARE @COLUMN VARCHAR(50)

DECLARE CUR CURSOR OPTIMISTIC FOR
SELECT NAME FROM SYS.COLUMNS WHERE OBJECT_ID IN (SELECT OBJECT_ID FROM
SYS.TABLES WHERE NAME='T_MEDICO')
OPEN CUR
FETCH NEXT FROM CUR INTO @COLUMN
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SQL = "INSERT INTO T_LOGTR
(C_LOGTR_FECHA,C_LOGTR_USR,C_LOGTR_TIPO_COD,C_LOGTR_TABLA,C_LOGTR_LLAVE,C_LOGTR_DATA)
"
+ " SELECT
GETDATE(),SYSTEM_USER,2,'MEDICOS.DBO.T_MEDICO',CONVERT(VARCHAR(10),INSERTED."+@LLAVE+"),
"
+ "
'"+@COLUMN+":'+ISNULL(CONVERT(VARCHAR(100),DELETED."+@COLUMN+"),'')+':->'+ISNULL(CONVERT(VARCHAR(100),INSERTED."+@COLUMN+"),'')
"
+ " FROM DELETED, INSERTED "
PRINT @SQL
EXEC(@SQL)

FETCH NEXT FROM CUR INTO @COLUMN
END
CLOSE CUR
DEALLOCATE CUR

Pero me da error:

Msg 208, Level 16, State 1, Line 1
Invalid object name 'DELETED'.

Entiendo que la tabla DELETED, asi como la INSERTED no son tabla "fisicas"
por eso el error.

¿Como puedo hacer?

Saludos
JORGE G.


Preguntas similares