2012-04-30 15 views
7

No tengo ni idea de dónde empezar o cómo funcionará, y espero que alguien tenga una idea o un método comprobado.Cómo crear una consulta que obtiene solo los datos que se han actualizado en una tabla

Para mostrar un ejemplo de lo que intento hacer, creé un procedimiento almacenado que ACTUALIZA o INSERTA registros nuevos en una tabla local obteniendo registros de una tabla de enlaces. El procedimiento almacenado se ejecuta como un trabajo en SQL Server para actualizar e insertar nuevos registros.

Mi pregunta es: ¿hay alguna manera de consultar los datos en la tabla local para que inicialmente pueda obtener todos los registros pero solo obtener los nuevos registros que se han insertado o los registros antiguos que se actualizan?

No deseo obtener continuamente todos los registros, solo los nuevos registros agregados o los registros actualizados.

¿Esto es posible?

Aquí es el procedimiento almacenado I AVE creado como un ejemplo para la actualización de datos de teléfono local:

CREATE PROCEDURE sp_UPDATE_PHONE_RECORDS 
AS 
BEGIN 
MERGE dbo.PHONE_REC AS Target 
USING (SELECT MEMBER_ID 
     ,HOME_PHONE = dbo.udf_StdPhoneFmt(HOME) 
     ,CELL_PHONE = dbo.udf_StdPhoneFmt(CELL) 
     ,WORK_PHONE = dbo.udf_StdPhoneFmt(WORK) 

FROM PHONE WHERE MEMBER_ID IS NOT NULL) AS SOURCE 

ON (Target.MEMBER_ID = SOURCE.MEMBER_ID) 

WHEN MATCHED THEN 

    UPDATE SET Target.HOME_PHONE = Source.HOME_PHONE,Target.CELL_PHONE = Source.CELL_PHONE, 
    Target.WORK_PHONE = Source.WORK_PHONE 

WHEN NOT MATCHED BY TARGET THEN 
    INSERT (MEMBER_ID, HOME_PHONE, CELL_PHONE ,WORK_PHONE) 

    VALUES (Source.MEMBER_ID, Source.HOME_PHONE, Source.CELL_PHONE, Source.WORK_PHONE); 
END 
GO 

Es esto posible?

¡Gracias a todos!

+1

Se siente como [ La replicación de SQL Server] (http://msdn.microsoft.com/en-us/library/ms151198.aspx) es la herramienta adecuada para este –

Respuesta

6

Lo que normalmente hacemos es agregar dos campos de fecha/hora a la tabla fuente, algo así como Source.LastModifiedOn y Source.CreatedOn.

Luego, cuando el trabajo se ejecuta para actualizar la tabla objetivo, puede decir obtenerme todas las filas Source.LastModifiedOn y Source.CreatedOn desde la última vez que se ejecutó la tarea y hacer las actualizaciones/inserciones basadas en las filas.

Por supuesto, deberá asegurarse de que Source.LastModifiedOn y Source.CreatedOn estén configurados correctamente.

+1

Este es un enfoque interesante. :) ¡Gracias de nuevo! – Asynchronous

4

me gustaría utilizar OUTPUT clause con $action columna:

DECLARE @Target TABLE 
(
    Id INT NOT NULL, 
    Value VARCHAR(10) NULL 
); 
INSERT @Target 
VALUES (1, 'A'), (2, NULL), (3, NULL);  
DECLARE @Source TABLE 
(
    Id INT NOT NULL, 
    Value VARCHAR(10) NULL 
); 
INSERT @Source 
VALUES (2, 'B'), (4, 'D'), (5, 'E'); 
DECLARE @AffectedRows TABLE 
(
    MergeAction  NVARCHAR(10) NOT NULL, 
    Old_Id   INT NULL, 
    Old_Value  VARCHAR(10) NULL, 
    New_Id   INT NULL, 
    New_Value  VARCHAR(10) NULL 
); 

MERGE @Target t 
USING @Source s ON t.Id = s.Id 
WHEN MATCHED THEN 
     UPDATE SET Value = s.Value 
WHEN NOT MATCHED THEN 
     INSERT (Id, Value) VALUES (s.Id, s.Value) 
OUTPUT $action, deleted.Id, deleted.Value, inserted.Id, inserted.Value 
     INTO @AffectedRows(MergeAction, Old_Id, Old_Value, New_Id, New_Value); 

SELECT * FROM @Target; 
SELECT * FROM @AffectedRows; 

Resultados:

Id Value 
-- ----- 
1 A 
2 B <-- updated row 
3 NULL 
4 D <-- inserted row 
5 E <-- inserted row 

MergeAction Old_Id  Old_Value New_Id  New_Value 
----------- ----------- ---------- ----------- --------- 
INSERT  NULL  NULL  4   D 
INSERT  NULL  NULL  5   E 
UPDATE  2   NULL  2   B 
+1

Voy a trabajar con su ejemplo y regresar con comentarios, no quiero marcarlo como respuesta, solo en caso de que tenga otras preguntas. Pero gracias por tomarte tu tiempo para responder. :) – Asynchronous

+0

@UnaverageGuy: Si tiene preguntas, no dude en preguntar. Si sé la respuesta, entonces te ayudaré. –

0

Puede escribir un disparador en su mesa local que se dispara cuando hay una actualización o inserción se realiza en él. Como parte de la lógica de activación, debe insertar los registros actualizados o recientemente insertados en una tabla temporal. Esta es la forma más simple en la que puede mantener un registro de sus cambios en la tabla local.

0

Esta es básicamente una variación del RDotLee's answer, pero es un enfoque alternativo que utilizo a veces, cuando no me importa acerca de la fecha/hora actual cuando se crearon los registros:

acabo de añadir una bit campo llamado modified con valor predeterminado 1.
Si se inserta una nueva fila en la tabla, modified se establece en 1 automáticamente.
Si se actualiza una fila existente, debo asegurarme de que modified también esté configurado en 1.

De esta manera, el trabajo solo necesita buscar todas las filas con modified = 1.
No es necesario realizar un seguimiento de la fecha/hora en que se ejecutó por última vez el trabajo.

Cuando el trabajo se ha ejecutado correctamente, la última cosa que hace es "puesta a cero" el campo modified en todas las filas:

update TheTable set modified = 0 

OMI, este enfoque es menos trabajo cuando simplemente se preocupan por que la las filas se modificaron desde la última ejecución del trabajo, pero no cuando se modificaron.

Pero tiene la misma desventaja que el enfoque "LastModifiedOn/CreatedOn" de RDotLee: debe asegurarse de que cada actualización de la tabla establezca realmente la columna modified en 1, por lo que solo puede usar esto cuando se encuentre control de todo el código que escribe en la tabla.

+0

Bien, encontré una solución que funciona, no estoy seguro de que sea la mejor, es una combinación de las ideas publicadas aquí. Lo que hice fue crear una columna TIME_STAMP en la tabla LOCAL. Esto agrega un SMALLDATETIME a los registros (fila) cada vez que se actualiza un registro o cuando se insertan nuevos registros. Ahora puedo consultar la base de la tabla Local en Record actualizada o insertada en las últimas 24 horas o entre esta hora y esa vez usando TIME_STAMP. ¿Cómo puedo publicar el código aquí? – Asynchronous

+0

@UnaverageGuy ¿Te refieres a TimeStamp? Eso no es un SmallDateTime. Y lo publiqué como una respuesta hace 3 horas. – Paparazzi

+0

No, yo creé una columna en la tabla local y llamé a la columna TIME_STAMP, el tipo de datos es smalldatetime. Lo que necesito saber ahora es cómo consulto la tabla local usando la fecha y hora en la columna TIME_STAMP para obtener todos los registros insertados o actualizados entre esta hora y esa vez. – Asynchronous

0

de TimeStamp

marca de hora se incrementa e inserte o actualización.

En el Maestro lo convierten en una marca de tiempo y en el esclavo que sea un binario (8)

select [timeStampSlave].* 
from [timeStampSlave] 
join [timeStampMaster] 
on [timeStampSlave].[ID] = [timeStampMaster].ID 
and [timeStampSlave].[timeStamp] < [timeStampMaster].[timestamp] 

Para realizar una consulta a través de servidores se puede utilizar la siguiente sintaxis

[MasterSever].[test].[dbo].[timeStampMaster] 
Cuestiones relacionadas