Resolver el valor de campos dinamicamente en tablas inserted y deleted

29/10/2003 - 10:32 por MONTREL S. A. \(Dpto. Ingeniería Informática\) | Informe spam
Hola a todos, tengo un problema y es que no puedo acceder al valor de un
campo cuyo nombre tengo almacenado en una variable y además, lo estoy
intentando desde un trigger y la tabla en cuestión es inserted y/o deleted.
El código del trigger es el siguiente:

CREATE TRIGGER [trgDETECTA_CAMBIOS] ON [dbo].Tabla1
FOR UPDATE
AS
DECLARE @NumColumnas INT
DECLARE @Contador INT
DECLARE @Nivel INT
DECLARE @Campo sysname
DECLARE @CampoOld varchar(100)
DECLARE @CampoNew varchar(100)
DECLARE @IDTabla INT
DECLARE @Tabla varchar(150)
DECLARE @Comando varchar(200)

SET @Contador=1
SET @Nivel=1
SET @Tabla='Tabla1'
SET @IDTabla=OBJECT_ID(@Tabla)
SELECT @NumColumnas=COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_NAME=@Tabla

WHILE @Contador <= @NumColumnas
BEGIN
SET @Campo=COL_NAME(@IDTabla, @Contador)

IF SUBSTRING(COLUMNS_UPDATED(), @Nivel, 1) = POWER(2, (@Contador-1))
BEGIN


SELECT @CampoNew=@Campo FROM inserted
SELECT @CampoOld=@Campo FROM deleted

INSERT INTO Tabla2 (DESCRIPCION)
VALUES ('Se modificó el campo ' + @Campo + ': ' + @CampoOld +
'->' + @CampoNew)
END

IF @Contador=8
BEGIN
SET @Contador=1
SET @Nivel=@Nivel + 1
END
ELSE
SET @Contador=@Contador + 1

END

También he intentado hacerlo mediante el procedimiento sp_executesql, pero
como es lógico no es factible, ya que el ámbito de las tablas inserted y
deleted se limita simplemente al cuerpo del trigger.

Lo he intentado todo, pero sin éxito.

Saludos y gracias de antemano.


Juan Manuel Cid Muñoz
Dpto. Ingeniería Informática

MONTREL S. A.

Preguntas similare

Leer las respuestas

#1 Accotto Maximiliano Damian
29/10/2003 - 13:18 | Informe spam
Hola!! mira estuve leyendo tu trigger y queria hacerte una pregunta:

Porque guardas un solo valor?

SELECT @CampoNew=@Campo FROM inserted
SELECT @CampoOld=@Campo FROM deleted




esto hara que se guarde un solo valor, quiere decir que si insertas mas de
un registro en la tabla este trigger no se va a comportar bien.

Te pregunto esto por si es una cuestion especial o si esta mal pensado el
trigger. Porque quizas lo q tengamos que ver es q esperas del trigger y como
se podria hacer, (me explico?)

Gracias

Accotto Maximiliano Damian
"MONTREL S. A. (Dpto. Ingeniería Informática)"
escribió en el mensaje news:u1g$
Hola a todos, tengo un problema y es que no puedo acceder al valor de un
campo cuyo nombre tengo almacenado en una variable y además, lo estoy
intentando desde un trigger y la tabla en cuestión es inserted y/o


deleted.
El código del trigger es el siguiente:

CREATE TRIGGER [trgDETECTA_CAMBIOS] ON [dbo].Tabla1
FOR UPDATE
AS
DECLARE @NumColumnas INT
DECLARE @Contador INT
DECLARE @Nivel INT
DECLARE @Campo sysname
DECLARE @CampoOld varchar(100)
DECLARE @CampoNew varchar(100)
DECLARE @IDTabla INT
DECLARE @Tabla varchar(150)
DECLARE @Comando varchar(200)

SET @Contador=1
SET @Nivel=1
SET @Tabla='Tabla1'
SET @IDTabla=OBJECT_ID(@Tabla)
SELECT @NumColumnas=COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_NAME=@Tabla

WHILE @Contador <= @NumColumnas
BEGIN
SET @Campo=COL_NAME(@IDTabla, @Contador)

IF SUBSTRING(COLUMNS_UPDATED(), @Nivel, 1) = POWER(2,


(@Contador-1))
BEGIN


SELECT @CampoNew=@Campo FROM inserted
SELECT @CampoOld=@Campo FROM deleted

INSERT INTO Tabla2 (DESCRIPCION)
VALUES ('Se modificó el campo ' + @Campo + ': ' + @CampoOld


+
'->' + @CampoNew)
END

IF @Contador=8
BEGIN
SET @Contador=1
SET @Nivel=@Nivel + 1
END
ELSE
SET @Contador=@Contador + 1

END

También he intentado hacerlo mediante el procedimiento sp_executesql, pero
como es lógico no es factible, ya que el ámbito de las tablas inserted y
deleted se limita simplemente al cuerpo del trigger.

Lo he intentado todo, pero sin éxito.

Saludos y gracias de antemano.


Juan Manuel Cid Muñoz
Dpto. Ingeniería Informática

MONTREL S. A.


Respuesta Responder a este mensaje
#2 Fernando G. Guerrero
29/10/2003 - 14:42 | Informe spam
Juan Manuel,

La instrucción SELECT no admite variables como nombre de campos (@Campo):

SELECT @CampoNew=@Campo FROM inserted

Esto no es válido, por lo que no tendrás más remedio que crear un código
menos automático, o utilizar ejecución dinámica para pasar estos valores a
la tabla de auditoría.

Fernando G. Guerrero
SQL Server MVP
CEO & Principal Mentor
Solid Quality Learning
www.solidqualitylearning.com

"Comparte lo que sabes, aprende lo que no sepas"

"MONTREL S. A. (Dpto. Ingeniería Informática)"
wrote in message news:u1g$
Hola a todos, tengo un problema y es que no puedo acceder al valor de un
campo cuyo nombre tengo almacenado en una variable y además, lo estoy
intentando desde un trigger y la tabla en cuestión es inserted y/o


deleted.
El código del trigger es el siguiente:

CREATE TRIGGER [trgDETECTA_CAMBIOS] ON [dbo].Tabla1
FOR UPDATE
AS
DECLARE @NumColumnas INT
DECLARE @Contador INT
DECLARE @Nivel INT
DECLARE @Campo sysname
DECLARE @CampoOld varchar(100)
DECLARE @CampoNew varchar(100)
DECLARE @IDTabla INT
DECLARE @Tabla varchar(150)
DECLARE @Comando varchar(200)

SET @Contador=1
SET @Nivel=1
SET @Tabla='Tabla1'
SET @IDTabla=OBJECT_ID(@Tabla)
SELECT @NumColumnas=COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_NAME=@Tabla

WHILE @Contador <= @NumColumnas
BEGIN
SET @Campo=COL_NAME(@IDTabla, @Contador)

IF SUBSTRING(COLUMNS_UPDATED(), @Nivel, 1) = POWER(2,


(@Contador-1))
BEGIN


SELECT @CampoNew=@Campo FROM inserted
SELECT @CampoOld=@Campo FROM deleted

INSERT INTO Tabla2 (DESCRIPCION)
VALUES ('Se modificó el campo ' + @Campo + ': ' + @CampoOld


+
'->' + @CampoNew)
END

IF @Contador=8
BEGIN
SET @Contador=1
SET @Nivel=@Nivel + 1
END
ELSE
SET @Contador=@Contador + 1

END

También he intentado hacerlo mediante el procedimiento sp_executesql, pero
como es lógico no es factible, ya que el ámbito de las tablas inserted y
deleted se limita simplemente al cuerpo del trigger.

Lo he intentado todo, pero sin éxito.

Saludos y gracias de antemano.


Juan Manuel Cid Muñoz
Dpto. Ingeniería Informática

MONTREL S. A.


Respuesta Responder a este mensaje
#3 Javier Loria
29/10/2003 - 15:53 | Informe spam
Hola:
Si SQL fuera una religion, esto seria "HEREJIA", solo falta agregar un
CURSOR (que el WHILE reemplaza muy bien), para que este completo.
Mis recomendaciones:
a) No "PROGRAMES" en SQL: El SQL no es un lenguaje igual que VB, C#,
C++, Pascal, Java, Fox, etc. Tratar de programar en SQL te va a dar muchos
dolores de cabeza y frustaciones, ya que NO tiene las mismas habilidades.
Estas usando un martillo para cortar madera.
b) Piensa en Conjuntos de Datos: El ciclo que escribes debe hacer de 10
a 100 veces mas lenta la insercion de datos, ahora no es importante porque
pasa de 10 milisegundos a 100 milisegundos y es imperceptible, pero cuando
lo pongas en produccion pasara de 10 segundos a 100 segundo (casi 2 minutos)
o en ciertos procesos de 1 hora a 10 horas. No es exageracion son casos
reales.
c) Es normalmente mala idea combinar Datos con MetaDatos.
Si quieres escribir un codigo que haga +- lo mismo lo escribiria asi:
/* Codigo de Creacion de Tablas */
CREATE TABLE Demo(
DemoID INT NOT NULL PRIMARY KEY,
DemoNombre VARCHAR(35) NOT NULL,
DemoDescripcion VARCHAR(100) NOT NULL
)

CREATE TABLE Descripciones(
DescripcionID INT NOT NULL IDENTITY, -- :(
Descripcion VARCHAR(100)
)
GO
/* Trigger de Auditoria */

CREATE TRIGGER trig_Demo
ON demo.dbo.Demo
FOR UPDATE
AS
IF UPDATE(DemoID)
BEGIN
RAISERROR ('DemoID NUNCA debe ser actualizado en tabla Demo', 16, 1)
ROLLBACK TRANSACTION
END

INSERT INTO Descripciones(Descripcion)
SELECT 'Se modificó el campo ' +
'DemoName: '+
Deleted.DemoNombre+
'->'+
Inserted.DemoNombre
FROM Inserted JOIN Deleted
ON Inserted.DemoID=Deleted.DemoID
WHERE Inserted.DemoNombre<>Deleted.DemoNombre
UNION ALL
SELECT 'Se modificó el campo ' +
'DemoDescripcion: '+
Deleted.DemoDescripcion+
'->'+
Inserted.DemoDescripcion
FROM Inserted JOIN Deleted
ON INSERTED.DemoID=Deleted.DemoID
WHERE Deleted.DemoDescripcion<>Inserted.DemoDescripcion
GO
/* Filas de Pruebas */
INSERT Demo(DemoID, DemoNombre,DemoDescripcion)
SELECT 1, 'Prueba1', 'Descripcion1'
UNION ALL
SELECT 2, 'Prueba2', 'Descripcion2'
UNION ALL
SELECT 3, 'Prueba3', 'Descripcion3'

/* Pruebas de Funcionalidad */
UPDATE Demo
SET DemoNombre='Prueba '+CAST(DemoID AS VARCHAR(3))

SELECT * FROM Descripciones

UPDATE Demo
SET DemoDescripcion='Otra Descripcion'+CAST(DemoID AS VARCHAR(3))
WHERE DemoID<3

SELECT * FROM Descripciones

/* Fin de Codigo */

Probablmente nunca escribiria este codigo porque trataria de usar las
bitacoras de SQL para lograr lo mismo, pero si realmente lo necesitas espero
te sirva,


Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda.




MONTREL S. A. (Dpto. Ingeniería Informática)
escribio:
Hola a todos, tengo un problema y es que no puedo acceder al valor de
un campo cuyo nombre tengo almacenado en una variable y además, lo
estoy intentando desde un trigger y la tabla en cuestión es inserted
y/o deleted. El código del trigger es el siguiente:

CREATE TRIGGER [trgDETECTA_CAMBIOS] ON [dbo].Tabla1
FOR UPDATE
AS
DECLARE @NumColumnas INT
DECLARE @Contador INT
DECLARE @Nivel INT
DECLARE @Campo sysname
DECLARE @CampoOld varchar(100)
DECLARE @CampoNew varchar(100)
DECLARE @IDTabla INT
DECLARE @Tabla varchar(150)
DECLARE @Comando varchar(200)

SET @Contador=1
SET @Nivel=1
SET @Tabla='Tabla1'
SET @IDTabla=OBJECT_ID(@Tabla)
SELECT @NumColumnas=COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_NAME=@Tabla

WHILE @Contador <= @NumColumnas
BEGIN
SET @Campo=COL_NAME(@IDTabla, @Contador)

IF SUBSTRING(COLUMNS_UPDATED(), @Nivel, 1) = POWER(2,
(@Contador-1)) BEGIN


SELECT @CampoNew=@Campo FROM inserted
SELECT @CampoOld=@Campo FROM deleted

INSERT INTO Tabla2 (DESCRIPCION)
VALUES ('Se modificó el campo ' + @Campo + ': ' +
@CampoOld + '->' + @CampoNew)
END

IF @Contador=8
BEGIN
SET @Contador=1
SET @Nivel=@Nivel + 1
END
ELSE
SET @Contador=@Contador + 1

END

También he intentado hacerlo mediante el procedimiento sp_executesql,
pero como es lógico no es factible, ya que el ámbito de las tablas
inserted y deleted se limita simplemente al cuerpo del trigger.

Lo he intentado todo, pero sin éxito.

Saludos y gracias de antemano.


Juan Manuel Cid Muñoz
Dpto. Ingeniería Informática

MONTREL S. A.
Respuesta Responder a este mensaje
#4 MONTREL S. A. \(Dpto. Ingeniería Informática\)
29/10/2003 - 17:04 | Informe spam
La verdad es que en esa tabla normalmente sólo se van a modificar registros
de uno en uno, no va a haber cambios masivos. Pero el caso, es que de
momento me he centrado en el problema de establecer el nombre del campo
dinamicamente. Si llegase a solucionar dicho problema, seguramente
recurriria a un cursor para tratar todos los registros de inserted y
deleted.


"Accotto Maximiliano Damian" escribió en el
mensaje news:
Hola!! mira estuve leyendo tu trigger y queria hacerte una pregunta:

Porque guardas un solo valor?

SELECT @CampoNew=@Campo FROM inserted
> SELECT @CampoOld=@Campo FROM deleted
>

esto hara que se guarde un solo valor, quiere decir que si insertas mas de
un registro en la tabla este trigger no se va a comportar bien.

Te pregunto esto por si es una cuestion especial o si esta mal pensado el
trigger. Porque quizas lo q tengamos que ver es q esperas del trigger y


como
se podria hacer, (me explico?)

Gracias

Accotto Maximiliano Damian
"MONTREL S. A. (Dpto. Ingeniería Informática)"
escribió en el mensaje news:u1g$
> Hola a todos, tengo un problema y es que no puedo acceder al valor de un
> campo cuyo nombre tengo almacenado en una variable y además, lo estoy
> intentando desde un trigger y la tabla en cuestión es inserted y/o
deleted.
> El código del trigger es el siguiente:
>
> CREATE TRIGGER [trgDETECTA_CAMBIOS] ON [dbo].Tabla1
> FOR UPDATE
> AS
> DECLARE @NumColumnas INT
> DECLARE @Contador INT
> DECLARE @Nivel INT
> DECLARE @Campo sysname
> DECLARE @CampoOld varchar(100)
> DECLARE @CampoNew varchar(100)
> DECLARE @IDTabla INT
> DECLARE @Tabla varchar(150)
> DECLARE @Comando varchar(200)
>
> SET @Contador=1
> SET @Nivel=1
> SET @Tabla='Tabla1'
> SET @IDTabla=OBJECT_ID(@Tabla)
> SELECT @NumColumnas=COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
> TABLE_NAME=@Tabla
>
> WHILE @Contador <= @NumColumnas
> BEGIN
> SET @Campo=COL_NAME(@IDTabla, @Contador)
>
> IF SUBSTRING(COLUMNS_UPDATED(), @Nivel, 1) = POWER(2,
(@Contador-1))
> BEGIN
>
>
> SELECT @CampoNew=@Campo FROM inserted
> SELECT @CampoOld=@Campo FROM deleted
>
> INSERT INTO Tabla2 (DESCRIPCION)
> VALUES ('Se modificó el campo ' + @Campo + ': ' +


@CampoOld
+
> '->' + @CampoNew)
> END
>
> IF @Contador=8
> BEGIN
> SET @Contador=1
> SET @Nivel=@Nivel + 1
> END
> ELSE
> SET @Contador=@Contador + 1
>
> END
>
> También he intentado hacerlo mediante el procedimiento sp_executesql,


pero
> como es lógico no es factible, ya que el ámbito de las tablas inserted y
> deleted se limita simplemente al cuerpo del trigger.
>
> Lo he intentado todo, pero sin éxito.
>
> Saludos y gracias de antemano.
>
>
> Juan Manuel Cid Muñoz
> Dpto. Ingeniería Informática
>
> MONTREL S. A.
>
>


Respuesta Responder a este mensaje
#5 MONTREL S. A. \(Dpto. Ingeniería Informática\)
29/10/2003 - 17:08 | Informe spam
Ya probe con ejecucion dinamica con sp_executesql, pero no me funcionó
porque a las tablas inserted y deleted solo puedo referirme dentro del
trigger. Pero no se que quieres decirme con lo de la tabla de auditoría.
Explicate por favor. Gracias.


"Fernando G. Guerrero" escribió en el mensaje
news:%2325$
Juan Manuel,

La instrucción SELECT no admite variables como nombre de campos (@Campo):

SELECT @CampoNew=@Campo FROM inserted

Esto no es válido, por lo que no tendrás más remedio que crear un código
menos automático, o utilizar ejecución dinámica para pasar estos valores a
la tabla de auditoría.

Fernando G. Guerrero
SQL Server MVP
CEO & Principal Mentor
Solid Quality Learning
www.solidqualitylearning.com

"Comparte lo que sabes, aprende lo que no sepas"

"MONTREL S. A. (Dpto. Ingeniería Informática)"
wrote in message news:u1g$
> Hola a todos, tengo un problema y es que no puedo acceder al valor de un
> campo cuyo nombre tengo almacenado en una variable y además, lo estoy
> intentando desde un trigger y la tabla en cuestión es inserted y/o
deleted.
> El código del trigger es el siguiente:
>
> CREATE TRIGGER [trgDETECTA_CAMBIOS] ON [dbo].Tabla1
> FOR UPDATE
> AS
> DECLARE @NumColumnas INT
> DECLARE @Contador INT
> DECLARE @Nivel INT
> DECLARE @Campo sysname
> DECLARE @CampoOld varchar(100)
> DECLARE @CampoNew varchar(100)
> DECLARE @IDTabla INT
> DECLARE @Tabla varchar(150)
> DECLARE @Comando varchar(200)
>
> SET @Contador=1
> SET @Nivel=1
> SET @Tabla='Tabla1'
> SET @IDTabla=OBJECT_ID(@Tabla)
> SELECT @NumColumnas=COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
> TABLE_NAME=@Tabla
>
> WHILE @Contador <= @NumColumnas
> BEGIN
> SET @Campo=COL_NAME(@IDTabla, @Contador)
>
> IF SUBSTRING(COLUMNS_UPDATED(), @Nivel, 1) = POWER(2,
(@Contador-1))
> BEGIN
>
>
> SELECT @CampoNew=@Campo FROM inserted
> SELECT @CampoOld=@Campo FROM deleted
>
> INSERT INTO Tabla2 (DESCRIPCION)
> VALUES ('Se modificó el campo ' + @Campo + ': ' +


@CampoOld
+
> '->' + @CampoNew)
> END
>
> IF @Contador=8
> BEGIN
> SET @Contador=1
> SET @Nivel=@Nivel + 1
> END
> ELSE
> SET @Contador=@Contador + 1
>
> END
>
> También he intentado hacerlo mediante el procedimiento sp_executesql,


pero
> como es lógico no es factible, ya que el ámbito de las tablas inserted y
> deleted se limita simplemente al cuerpo del trigger.
>
> Lo he intentado todo, pero sin éxito.
>
> Saludos y gracias de antemano.
>
>
> Juan Manuel Cid Muñoz
> Dpto. Ingeniería Informática
>
> MONTREL S. A.
>
>


Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida