如何创建仅获取已在表中更新的数据的查询

时间:2012-04-30 21:45:24

标签: sql sql-server sql-server-2008 tsql

我不知道从哪里开始或者这将如何运作,我希望有人有一个想法或一个经过验证的方法。

为了展示我想要做的事情的一个例子,我创建了一个存储过程,它通过从链接表中获取记录来更新或插入Local表中的新记录。存储过程在SQL Server中作为作业运行,以更新和插入新记录。

我的问题是:有没有办法查询本地表中的数据,以便最初我可以获取所有记录,但只获取已插入的新记录或更新的旧记录?

我不想连续获取所有记录,只添加新记录或更新记录。

这可能吗?

以下是我创建的存储过程,作为更新本地电话数据的示例:

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

这可能吗?

谢谢大家!

5 个答案:

答案 0 :(得分:6)

我们通常做的是在源表中添加两个日期/时间字段,例如Source.LastModifiedOn和Source.CreatedOn。

然后当作业运行以更新目标表时,您可以说自上次作业运行以来获取所有Source.LastModifiedOn和Source.CreatedOn行,并根据行执行更新/插入。

当然,您需要确保正确设置Source.LastModifiedOn和Source.CreatedOn。

答案 1 :(得分:4)

我会将OUTPUT clause$action列一起使用:

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;

结果:

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

答案 2 :(得分:0)

您可以在本地表上编写一个触发器,该触发器在对其进行更新或插入时将触发。作为触发器逻辑的一部分,您必须将这些更新或新插入的记录插入临时表中。这是您可以记录对本地表的更改的最简单方法。

答案 3 :(得分:0)

这基本上是RDotLee's answer的变体,但是当我不关心创建记录的实际日期/时间时,它是我有时使用的另一种方法:

我只需添加一个名为bit的{​​{1}}字段,默认值为1 如果在表格中插入新行,modified会自动设置为1 如果现有行已更新,我必须确保modified也设置为1。

这样,作业只需要搜索modified的所有行 无需跟踪上次执行作业的日期/时间。

当作业成功执行时,它最后做的是“重置”所有行中的modified = 1字段:

modified

国际海事组织,如果您只关心 自上次作业以来修改了行,那么这种方法就不那么有效了,但 时修改了

但它与RDotLee的“LastModifiedOn / CreatedOn”方法具有相同的缺点 - 您需要确保表上的每个更新确实将update TheTable set modified = 0 列设置为1,因此您只能在您可以控制写入表的所有代码。

答案 4 :(得分:0)

TimeStamp

TimeStamp会增加并插入或更新。

在Master上使它成为TimeStamp并在Slave上使它成为二进制(8)

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

要跨服务器查询,您可以使用以下语法

[MasterSever].[test].[dbo].[timeStampMaster]