PDA

Ver la Versión Completa : Saber si el dato de un campo ha cambiado en SQL SERVER


elrayo76
12-02-2016, 20:38:56
Necesito si alguien me puede decir como hacer para verificar en SQL SERVER si el dato de un campo ha cambiado (pueden ser mas de un campo)

SELECT
s.Sucursal,
SUBSTRING(UPPER(LTRIM(RTRIM(s.[Server]))), 1, 30) as Nombre1,
SUBSTRING(LTRIM(RTRIM(s.NomSucursal)), 1, 30) as Nombre2,
SUBSTRING(LTRIM(RTRIM(ISNULL(s.Direccion, ''))), 1, 30) as Direccion,
SUBSTRING(UPPER(LTRIM(RTRIM(ISNULL(c.Ciudad, '')))), 1, 30) as Lugar,
SUBSTRING(LTRIM(RTRIM(ISNULL(s.CodigoPostal, ''))), 1, 6) as CodigoPostal,
SUBSTRING(LTRIM(RTRIM(ISNULL(s.Telefono, ''))), 1, 40) as TextoAdicional
FROM DBSucServer.dbo.SucursalesTodas s WITH(NOLOCK)
LEFT JOIN DBSucServer.dbo.Ciudades c WITH(NOLOCK)
ON c.idCiudad = s.idCiudad
WHERE Estado IN ('A', 'F')
AND ((@Sucursal >= 0 AND s.Sucursal = @Sucursal))
ORDER BY s.Sucursal

Tomando como base la consulta que puse necesito saber si alguno de esos campos que se van a insertar ha cambiado en la tabla donde los tengo que insertar. Esto es para que cada vez que mando a insertar el registro con el SP no lo inserte a menos que halla cambiado alguno de los campos.

Alcaro que el campo clave no es nunguno de los que esta en la consulta y que el registro se busca por sucursal. Los registros sin procesar solo podrán tener uno solo, mientras que los procesados puede que allan varios. Además no se puede hacer UPDATE porque se tienen que mantener por un tiempo X los registros procesados

Saludos,
El Rayo

mamcx
13-02-2016, 00:00:09
La manera mas sana es tener un campo timestamp/version que se actualiza al hacer cambios por registro y se compara con el ultimo valor...

Hacerlo *por campo* me parece erroneo. El modelo relacional es muy claro: El valor de una relacion es completo (osea: Lo que llamamos "registro" o fila). Si esta en una relacion, los cambios son a esa relacion, no a un pedacito de ella...

elrayo76
13-02-2016, 00:27:27
El tema es que donde tengo que insertar los datos no es relación de ninguna otra tabla. Lo de la fecha no sirve.

Explico algo para que se entienda mejor.

Si en la tabla temporal existe un registro que tiene el estado de no procesado y por algun motivo se manda nuevamente ese mismo registro, tendría que poder saber si alguno de los campos del registro nuevo es distinto al del que existe en la temporal. De esta forma anularía (pasaría a procesado) el que ya existe y dejaria el que esta viniendo nuevo que todavía no se inserto.

Pense en su momento hacerlo con un UPDATE, pero no sirve, ya que si piso el registro se mandaría a procesar nuevamente un registro que no correspondería si en el mismo no cambio nada.

Saludos,
El Rayo

mamcx
13-02-2016, 00:41:35
No te entiendo... como no puede ser una relacion si estas insertando en una tabla y ademas chequeas contra la misma?

Ahora, si entiendo lo que buscas estas armando un "Task Queue". Podrias explicar la logica (sin SQL, pseudocodigo) del proceso completo?

elrayo76
13-02-2016, 23:03:18
No creo que pueda con pseudocodigo es algo complejo y en este momento no lo tengo a mano.

Lo que quiero es lo siguiente:

1) Leer con SQL datos que salen de distintas tablas.
1) Validar esos datos contra la tabla donde se van a insertar para ver que el registro no existe. Si existe ver que no tenga campos con datos distintos
2) Solo insertar si no existe el registro o alguno de los campos tiene datos distintos.

Nada mas que eso es lo que quiero hacer.

El tema es que no se como validar cada uno de los campos para poder hacerlo de una forma facil y no uno por uno recorriendo la tabla. No se si se puede hacer lo que quiero.

Saludos,
El Rayo

mamcx
14-02-2016, 01:19:27
El asunto es que esto no tiene muchas formas de hacerse, y al final es lo mismo.

La forma mas simple es usando un INSERT...SELECT FROM o mucho mas correcto, un MERGE/UPSERT (http://sqlserverinsight.blogspot.com.co/2012/06/upsert-statement-in-t-sql.html)

El asunto es que la logica se complica por el problema de chequear por campo. La manera mecanica es construir el WHERE comparando campo por campo, pero hacer un DIFF entre lo viejo y lo nuevo es una vuelta mas complicada.

Es MUCHO mas simple si aceptas usar un timestamp/version. La comparacion es solo contra el timestamp y eliminas /re-insertar la fila entera (eso lo hace el UPSERT).

----

Si en la tabla temporal existe un registro que tiene el estado de no procesado y por algun motivo se manda nuevamente ese mismo registro, tendría que poder saber si alguno de los campos del registro nuevo es distinto al del que existe en la temporal. De esta forma anularía (pasaría a procesado) el que ya existe y dejaria el que esta viniendo nuevo que todavía no se inserto.


Si entiendo esto, estas tratando de hacer un task queue. Es importante saberlo, porque hay formas especificas de como hacer esto correctamente.

Porque si lo que quieres es poder mandar un "trabajo" que debe tomar N-Clientes, y asegurarse de que ese trabajo sea idempotente y que solo se procese una sola vez, es un rollo muy diferente.

Se puede con Sql, pero tienes que hacerlo BIEN:

http://rusanu.com/2010/03/26/using-tables-as-queues/

elrayo76
16-02-2016, 14:20:10
Gracias gente, con el MERGE pude resolver lo que necestaba sin problemas.

Saludos,
El Rayo