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

#6 MONTREL S. A. \(Dpto. Ingeniería Informática\)
29/10/2003 - 17:34 | Informe spam
Creo que voy a utilizar UPDATE(nombrecampo) como alternativa.

Gracias por tu ayuda

"Javier Loria" escribió en el mensaje
news:
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
#7 Fernando G. Guerrero
29/10/2003 - 19:25 | Informe spam
Me parece una sabia decisión. Como dicen en mi pueblo, "Lo mejor es enemigo
de lo bueno", o dicho de otro modo, a veces intentando encontrar la mejor
solución desperdiciamos demasiado tiempo que podría haber sido empleado de
mejor modo seleccionando una buena solución de partida.

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:
Creo que voy a utilizar UPDATE(nombrecampo) como alternativa.

Gracias por tu ayuda

"Javier Loria" escribió en el mensaje
news:
> 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.
>
>
>


email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida